From cac818173050ec1e18d73d0f880c826901cf4abd Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Tue, 2 Jun 2020 11:51:28 -0700 Subject: Add new Base64URL<->Buffer helper methods --- .../browser/src/helpers/base64URLStringToBuffer.ts | 33 ++++++++++++++++++++++ .../src/helpers/bufferToBase64URLString.test.ts | 15 ++++++++++ .../browser/src/helpers/bufferToBase64URLString.ts | 21 ++++++++++++++ .../browser/src/helpers/toBase64String.test.ts | 15 ---------- packages/browser/src/helpers/toBase64String.ts | 6 ---- 5 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 packages/browser/src/helpers/base64URLStringToBuffer.ts create mode 100644 packages/browser/src/helpers/bufferToBase64URLString.test.ts create mode 100644 packages/browser/src/helpers/bufferToBase64URLString.ts delete mode 100644 packages/browser/src/helpers/toBase64String.test.ts delete mode 100644 packages/browser/src/helpers/toBase64String.ts (limited to 'packages/browser/src') diff --git a/packages/browser/src/helpers/base64URLStringToBuffer.ts b/packages/browser/src/helpers/base64URLStringToBuffer.ts new file mode 100644 index 0000000..baa258f --- /dev/null +++ b/packages/browser/src/helpers/base64URLStringToBuffer.ts @@ -0,0 +1,33 @@ +/** + * Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a + * credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or + * excludeCredentials + * + * Helper method to compliment `bufferToBase64URLString` + */ +export default function base64URLStringToBuffer(base64URLString: string): ArrayBuffer { + // Convert from Base64URL to Base64 + const base64 = base64URLString.replace(/-/g, '+').replace(/_/g, '/'); + /** + * Pad with '=' until it's a multiple of four + * (4 - (85 % 4 = 1) = 3) % 4 = 3 padding + * (4 - (86 % 4 = 2) = 2) % 4 = 2 padding + * (4 - (87 % 4 = 3) = 1) % 4 = 1 padding + * (4 - (88 % 4 = 0) = 4) % 4 = 0 padding + */ + const padLength = (4 - (base64.length % 4)) % 4; + const padded = base64.padEnd(base64.length + padLength, '='); + + // Convert to a binary string + const binary = atob(padded); + + // Convert binary string to buffer + const buffer = new ArrayBuffer(binary.length); + const bytes = new Uint8Array(buffer); + + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i); + } + + return buffer; +} diff --git a/packages/browser/src/helpers/bufferToBase64URLString.test.ts b/packages/browser/src/helpers/bufferToBase64URLString.test.ts new file mode 100644 index 0000000..bbcb11b --- /dev/null +++ b/packages/browser/src/helpers/bufferToBase64URLString.test.ts @@ -0,0 +1,15 @@ +import toBase64String from './toBase64String'; + +import toUint8Array from './toUint8Array'; + +test('should convert a Buffer to a string with a length that is a multiple of 4', () => { + const base64 = toBase64String(Buffer.from('123456', 'ascii')); + + expect(base64.length % 4).toEqual(0); +}); + +test('should convert a Uint8Array to a string with a length that is a multiple of 4', () => { + const base64 = toBase64String(toUint8Array('123456')); + + expect(base64.length % 4).toEqual(0); +}); diff --git a/packages/browser/src/helpers/bufferToBase64URLString.ts b/packages/browser/src/helpers/bufferToBase64URLString.ts new file mode 100644 index 0000000..954f4b0 --- /dev/null +++ b/packages/browser/src/helpers/bufferToBase64URLString.ts @@ -0,0 +1,21 @@ +/** + * Convert the given array buffer into a Base64URL-encoded string. Ideal for converting various + * credential response ArrayBuffers to string for sending back to the server as JSON. + * + * Helper method to compliment `base64URLStringToBuffer` + */ +export default function bufferToBase64URLString(buffer: ArrayBuffer): string { + const bytes = new Uint8Array(buffer); + let str = ''; + + for (const charCode of bytes) { + str += String.fromCharCode(charCode); + } + + const base64String = btoa(str); + + return base64String + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=/g, ''); +} diff --git a/packages/browser/src/helpers/toBase64String.test.ts b/packages/browser/src/helpers/toBase64String.test.ts deleted file mode 100644 index bbcb11b..0000000 --- a/packages/browser/src/helpers/toBase64String.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import toBase64String from './toBase64String'; - -import toUint8Array from './toUint8Array'; - -test('should convert a Buffer to a string with a length that is a multiple of 4', () => { - const base64 = toBase64String(Buffer.from('123456', 'ascii')); - - expect(base64.length % 4).toEqual(0); -}); - -test('should convert a Uint8Array to a string with a length that is a multiple of 4', () => { - const base64 = toBase64String(toUint8Array('123456')); - - expect(base64.length % 4).toEqual(0); -}); diff --git a/packages/browser/src/helpers/toBase64String.ts b/packages/browser/src/helpers/toBase64String.ts deleted file mode 100644 index 3178695..0000000 --- a/packages/browser/src/helpers/toBase64String.ts +++ /dev/null @@ -1,6 +0,0 @@ -import base64js from 'base64-js'; - -export default function toBase64String(buffer: ArrayBuffer): string { - // TODO: Make sure converting buffer to Uint8Array() is correct - return base64js.fromByteArray(new Uint8Array(buffer)).replace(/\+/g, '-').replace(/\//g, '_'); -} -- cgit v1.2.3