Skip to content

Commit

Permalink
Fix potential persistence issue (#620)
Browse files Browse the repository at this point in the history
* Fix potential persistence issue

Fix RangeError when converting array buffer to base64
for large arrays. Using String.fromCharCodeApply(null, array)
may cause too many arguments to be passed

* Add test
  • Loading branch information
everdimension authored Oct 3, 2024
1 parent 2ccf5bf commit 11926b4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
34 changes: 34 additions & 0 deletions src/modules/crypto/aes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { decrypt, encrypt } from './aes';

describe('encrypt function', () => {
test('encrypted value is the same after decryption', async () => {
const value = { name: 'apple' };

const password = 'test-123';
const encrypted = await encrypt(password, value);
expect(encrypted).not.toBe(JSON.stringify(value));

const decrypted = await decrypt(password, encrypted);
expect(decrypted).toEqual(value);
});

test('very large value is encrypted correctly', async () => {
function createVeryLargeString() {
// A large string will at some point be split into bytes by the encrypting function
// and those bytes may be passed as arguments, but browsers have a different
// limit on maximum number of agruments: https://stackoverflow.com/a/22747272/3523645
// As a solution we avoid doing that and have this test as a guard, but its outcome
// may differ across javascript environments
const uint8Array = crypto.getRandomValues(new Uint8Array(65536));
return uint8Array.reduce((str, c) => str + String.fromCharCode(c), '');
}
const largeValue = { message: createVeryLargeString() };

const password = 'test-123';
const encrypted = await encrypt(password, largeValue);
expect(encrypted).not.toBe(JSON.stringify(largeValue));

const decrypted = await decrypt(password, encrypted);
expect(decrypted).toEqual(largeValue);
});
});
10 changes: 6 additions & 4 deletions src/modules/crypto/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ export function base64ToUint8Array(base64: string) {
}

export function uint8ArrayToBase64(array: Uint8Array) {
// Explicit casting is needed to satisfy the typechecker
return globalThis.btoa(
String.fromCharCode.apply(null, array as unknown as number[])
);
let str = '';
const length = array.byteLength;
for (let i = 0; i < length; i++) {
str += String.fromCharCode(array[i]);
}
return globalThis.btoa(str);
}

export function arrayBufferToBase64(buffer: ArrayBuffer) {
Expand Down

0 comments on commit 11926b4

Please sign in to comment.