Skip to content

Commit

Permalink
encoding: Add strToBase64 function and tests
Browse files Browse the repository at this point in the history
The function encodes a JavaScript string to a string in Base64 format.

The way to reliably encode strings to Base64 is described in
many places, including:
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa#Unicode_strings

Instead of the `btoa` function we use `base64.encode` from our
external base64 library to prevent the error:
'InvalidCharacterError: The string to be encoded contains
characters outside of the Latin1 range.'

Note: JavaScript strings are UCS-2 or UTF-16 (not UTF-8)
http://es5.github.io/x2.html
  • Loading branch information
borisyankov committed Aug 2, 2018
1 parent 90b807b commit efa180f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
32 changes: 31 additions & 1 deletion src/utils/__tests__/encoding-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
hexToAscii,
asciiToHex,
xorHexStrings,
strToBase64,
extractApiKey,
} from '../encoding';

Expand Down Expand Up @@ -61,11 +62,40 @@ describe('asciiToHex', () => {
});
});

describe('strToBase64', () => {
test('can handle an empty string', () => {
const obj = '';
const expected = '';

const result = strToBase64(obj);

expect(result).toBe(expected);
});

test('can encode any string', () => {
const obj = {
key: 'ABCabc123',
empty: null,
array: [1, 2, 3],
};
const expected = 'W29iamVjdCBPYmplY3Rd';

const result = strToBase64(obj);

expect(result).toBe(expected);
});

test('supports unicode characters', () => {
const obj = { key: '😇😈' };
const expected = 'W29iamVjdCBPYmplY3Rd';
const result = strToBase64(obj);
expect(result).toBe(expected);
});
});
describe('extractApiKey', () => {
test('correctly extracts an API key that has been XORed with a OTP', () => {
const key = 'testing';
const otp = 'A8348A93A83493';

const encoded = xorHexStrings(asciiToHex(key), otp);
expect(extractApiKey(encoded, otp)).toBe(key);
});
Expand Down
5 changes: 5 additions & 0 deletions src/utils/encoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export const base64ToHex = (bytes: string) => asciiToHex(base64.decode(bytes));

export const hexToBase64 = (hex: string) => base64.encode(hexToAscii(hex));

// https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
// `base64.encode` used instead of `btoa` to support Unicode input
export const strToBase64 = (text: string): string =>
base64.encode(unescape(encodeURIComponent(text)));

// Extract an API key encoded as a hex string XOR'ed with a one time pad (OTP)
// (this is used during the OAuth flow)
export const extractApiKey = (encoded: string, otp: string) =>
Expand Down

0 comments on commit efa180f

Please sign in to comment.