diff --git a/ts/test/session/unit/crypto/attachmentsEncrypter_test.ts b/ts/test/session/unit/crypto/attachmentsEncrypter_test.ts new file mode 100644 index 0000000000..afd24859df --- /dev/null +++ b/ts/test/session/unit/crypto/attachmentsEncrypter_test.ts @@ -0,0 +1,43 @@ +import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import { decryptAttachment, encryptAttachment } from '../../../../util/crypto/attachmentsEncrypter'; + +use(chaiAsPromised); + +function makeBuffer(length: number, offset: number) { + const buffer = new ArrayBuffer(length); + const view = new Uint8Array(buffer); + + for (let index = 0; index < length; index += 1) { + view[index] = (index + offset) % 256; + } + + return buffer; +} + +describe('attachmentsEncrypter', () => { + it('decrypts attachments encrypted with the matching digest', async () => { + const plaintext = makeBuffer(48, 3); + const keys = makeBuffer(64, 7); + const iv = makeBuffer(16, 11); + + const encrypted = await encryptAttachment(plaintext, keys, iv); + const decrypted = await decryptAttachment(encrypted.ciphertext, keys, encrypted.digest); + + expect(new Uint8Array(decrypted)).to.deep.equal(new Uint8Array(plaintext)); + }); + + it('rejects truncated attachment digests', async () => { + const plaintext = makeBuffer(48, 3); + const keys = makeBuffer(64, 7); + const iv = makeBuffer(16, 11); + + const encrypted = await encryptAttachment(plaintext, keys, iv); + const truncatedDigest = encrypted.digest.slice(0, 16); + + await expect(decryptAttachment(encrypted.ciphertext, keys, truncatedDigest)).to.be.rejectedWith( + 'Bad digest length' + ); + }); +}); diff --git a/ts/util/crypto/attachmentsEncrypter.ts b/ts/util/crypto/attachmentsEncrypter.ts index 153848347d..c03c8f21a3 100644 --- a/ts/util/crypto/attachmentsEncrypter.ts +++ b/ts/util/crypto/attachmentsEncrypter.ts @@ -45,6 +45,10 @@ async function verifyMAC(data: any, key: any, mac: any, length: any) { async function verifyDigest(data: ArrayBuffer, theirDigest: ArrayBuffer) { return crypto.subtle.digest({ name: 'SHA-256' }, data).then(ourDigest => { + if (theirDigest.byteLength !== ourDigest.byteLength) { + throw new Error('Bad digest length'); + } + const a = new Uint8Array(ourDigest); const b = new Uint8Array(theirDigest); let result = 0;