storage-manager/workers/src/encrypt.test.ts
Ravi Khadiwala cb7b2fe861 Randomly generate IVs
We include the IV in the encrypted payload, so we can let the server
choose them.
2024-10-29 17:44:58 -05:00

57 lines
2.0 KiB
TypeScript

// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { describe, expect, it } from 'vitest';
import {
randBytes,
readableStreamFrom,
readAll,
authenticateAndDecryptWithIv
} from './testutil';
import { Encrypter, streamEncrypt } from './encrypt';
describe('streamEncrypt', () => {
const keyBytes: Uint8Array = randBytes(32);
const hmacKey = randBytes(32);
const iv = randBytes(16);
it.each([1, 3, 113])('handles chunks of size %s', async (chunkSize) => {
const plaintext = randBytes(1763);
const encrypter = await Encrypter.create(iv, hmacKey, keyBytes);
const { readable: source, writable: inp } = new TransformStream();
const { readable: out, writable: dst } = new TransformStream();
const [writePromise, readPromise] = [streamEncrypt(encrypter, source, dst, 128), readAll(out)];
const writer = inp.getWriter();
for (let i = 0; i < plaintext.length; i += chunkSize) {
await writer.write(plaintext.subarray(i, i + chunkSize));
}
await writer.close();
await writePromise;
const encrypted = await readPromise;
const decrypted = await authenticateAndDecryptWithIv(iv, keyBytes, hmacKey, encrypted);
expect(encrypted.length).toBe(encrypter.encryptedLength(plaintext.length));
expect(decrypted).toEqual(plaintext);
});
it.each([
0, 16, 17, 32, 1023, 1024, 1025, 1024 * 3 + 7
])('encrypts a single chunk of size %s', async (plaintextLength: number) => {
const plaintext = randBytes(plaintextLength);
const encrypter = await Encrypter.create(iv, hmacKey, keyBytes);
const source = readableStreamFrom(plaintext);
const { readable: actual, writable: dst } = new TransformStream();
const encrypt = streamEncrypt(encrypter, source, dst, 1024);
const ciphertext = await readAll(actual);
const decrypted = await authenticateAndDecryptWithIv(iv, keyBytes, hmacKey, ciphertext);
await encrypt;
expect(decrypted).toEqual(plaintext);
expect(ciphertext.length).toBe(encrypter.encryptedLength(plaintextLength));
});
});