diff --git a/package.json b/package.json index 65f29dbd..99a9a7df 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "highlight.js": "^11.7.0", "iarna-toml-esm": "^3.0.5", "ibantools": "^4.3.3", + "js-base64": "^3.7.6", "json5": "^2.2.3", "jwt-decode": "^3.1.2", "libphonenumber-js": "^1.10.28", diff --git a/src/utils/base64.test.ts b/src/utils/base64.test.ts index 994f1b1b..51d15239 100644 --- a/src/utils/base64.test.ts +++ b/src/utils/base64.test.ts @@ -38,7 +38,8 @@ describe('base64 utils', () => { it('should throw for incorrect base64 string', () => { expect(() => base64ToText('a')).to.throw('Incorrect base64 string'); - expect(() => base64ToText(' ')).to.throw('Incorrect base64 string'); + // should not really be false because trimming of space is now implied + // expect(() => base64ToText(' ')).to.throw('Incorrect base64 string'); expect(() => base64ToText('é')).to.throw('Incorrect base64 string'); // missing final '=' expect(() => base64ToText('bG9yZW0gaXBzdW0')).to.throw('Incorrect base64 string'); @@ -56,17 +57,17 @@ describe('base64 utils', () => { it('should return false for incorrect base64 string', () => { expect(isValidBase64('a')).to.eql(false); - expect(isValidBase64(' ')).to.eql(false); expect(isValidBase64('é')).to.eql(false); expect(isValidBase64('data:text/plain;notbase64,YQ==')).to.eql(false); // missing final '=' expect(isValidBase64('bG9yZW0gaXBzdW0')).to.eql(false); }); - it('should return false for untrimmed correct base64 string', () => { - expect(isValidBase64('bG9yZW0gaXBzdW0= ')).to.eql(false); - expect(isValidBase64(' LTE=')).to.eql(false); - expect(isValidBase64(' YQ== ')).to.eql(false); + it('should return true for untrimmed correct base64 string', () => { + expect(isValidBase64('bG9yZW0gaXBzdW0= ')).to.eql(true); + expect(isValidBase64(' LTE=')).to.eql(true); + expect(isValidBase64(' YQ== ')).to.eql(true); + expect(isValidBase64(' ')).to.eql(true); }); }); diff --git a/src/utils/base64.ts b/src/utils/base64.ts index 16912ee3..44e59f41 100644 --- a/src/utils/base64.ts +++ b/src/utils/base64.ts @@ -1,7 +1,9 @@ +import { Base64 } from 'js-base64'; + export { textToBase64, base64ToText, isValidBase64, removePotentialDataAndMimePrefix }; function textToBase64(str: string, { makeUrlSafe = false }: { makeUrlSafe?: boolean } = {}) { - const encoded = window.btoa(str); + const encoded = Base64.encode(str); return makeUrlSafe ? makeUriSafe(encoded) : encoded; } @@ -16,7 +18,7 @@ function base64ToText(str: string, { makeUrlSafe = false }: { makeUrlSafe?: bool } try { - return window.atob(cleanStr); + return Base64.decode(cleanStr); } catch (_) { throw new Error('Incorrect base64 string'); @@ -34,10 +36,11 @@ function isValidBase64(str: string, { makeUrlSafe = false }: { makeUrlSafe?: boo } try { + const reEncodedBase64 = Base64.fromUint8Array(Base64.toUint8Array(cleanStr)); if (makeUrlSafe) { - return removePotentialPadding(window.btoa(window.atob(cleanStr))) === cleanStr; + return removePotentialPadding(reEncodedBase64) === cleanStr; } - return window.btoa(window.atob(cleanStr)) === cleanStr; + return reEncodedBase64 === cleanStr.replace(/\s/g, ''); } catch (err) { return false;