UNPKG

pooja-docucomb-tink-crypto

Version:

A multi-language, cross-platform library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.

198 lines (186 loc) 7.87 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import * as Bytes from './bytes'; import {aesCtrHmacFromRawKeys} from './encrypt_then_authenticate'; import * as Random from './random'; describe('encrypt then authenticate test', function() { beforeEach(function() { // Use a generous promise timeout for running continuously. jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 1000; // 1000s }); afterEach(function() { // Reset the promise timeout to default value. jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; // 1s }); it('basic', async function() { const aead = await aesCtrHmacFromRawKeys( Random.randBytes(16) /* aesKey */, 12 /* ivSize */, 'SHA-256', Random.randBytes(16) /* hmacKey */, 10 /* tagSize */); for (let i = 0; i < 100; i++) { const msg = Random.randBytes(20); let ciphertext = await aead.encrypt(msg); let plaintext = await aead.decrypt(ciphertext); expect(Bytes.toHex(plaintext)).toBe(Bytes.toHex(msg)); ciphertext = await aead.encrypt(msg); plaintext = await aead.decrypt(ciphertext); expect(Bytes.toHex(plaintext)).toBe(Bytes.toHex(msg)); const aad = Random.randBytes(20); ciphertext = await aead.encrypt(msg, aad); plaintext = await aead.decrypt(ciphertext, aad); expect(Bytes.toHex(plaintext)).toBe(Bytes.toHex(msg)); } }); it('probabilistic encryption', async function() { const aead = await aesCtrHmacFromRawKeys( Random.randBytes(16) /* aesKey */, 12 /* ivSize */, 'SHA-256', Random.randBytes(16) /* hmacKey */, 10 /* tagSize */); const msg = Random.randBytes(20); const aad = Random.randBytes(20); const results = new Set(); for (let i = 0; i < 100; i++) { const ciphertext = await aead.encrypt(msg, aad); results.add(Bytes.toHex(ciphertext)); } expect(results.size).toBe(100); }); it('bit flip ciphertext', async function() { const aead = await aesCtrHmacFromRawKeys( Random.randBytes(16) /* aesKey */, 16 /* ivSize */, 'SHA-256', Random.randBytes(16) /* hmacKey */, 16 /* tagSize */); const plaintext = Random.randBytes(8); const aad = Random.randBytes(8); const ciphertext = await aead.encrypt(plaintext, aad); for (let i = 0; i < ciphertext.length; i++) { for (let j = 0; j < 8; j++) { const c1 = new Uint8Array(ciphertext); c1[i] = (c1[i] ^ (1 << j)); try { await aead.decrypt(c1, aad); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()).toBe('SecurityException: invalid MAC'); } } } }); it('bit flip aad', async function() { const aead = await aesCtrHmacFromRawKeys( Random.randBytes(16) /* aesKey */, 16 /* ivSize */, 'SHA-256', Random.randBytes(16) /* hmacKey */, 16 /* tagSize */); const plaintext = Random.randBytes(8); const aad = Random.randBytes(8); const ciphertext = await aead.encrypt(plaintext, aad); for (let i = 0; i < aad.length; i++) { for (let j = 0; j < 8; j++) { const aad1 = new Uint8Array(aad); aad1[i] = (aad1[i] ^ (1 << j)); try { await aead.decrypt(ciphertext, aad1); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()).toBe('SecurityException: invalid MAC'); } } } }); it('truncation', async function() { const aead = await aesCtrHmacFromRawKeys( Random.randBytes(16) /* aesKey */, 16 /* ivSize */, 'SHA-256', Random.randBytes(16) /* hmacKey */, 16 /* tagSize */); const plaintext = Random.randBytes(8); const aad = Random.randBytes(8); const ciphertext = await aead.encrypt(plaintext, aad); for (let i = 1; i <= ciphertext.length; i++) { const c1 = new Uint8Array(ciphertext.buffer, 0, ciphertext.length - i); try { await aead.decrypt(c1, aad); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { if (c1.length < 32) { expect(e.toString()).toBe('SecurityException: ciphertext too short'); } else { expect(e.toString()).toBe('SecurityException: invalid MAC'); } } } }); it('with rfc test vectors', async function() { // Test data from // https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05. As we // use CTR while RFC uses CBC mode, it's not possible to compare plaintexts. // However, the test is still valueable to make sure that we correcly // compute HMAC over ciphertext and aad. const RFC_TEST_VECTORS = [ { 'macKey': '000102030405060708090a0b0c0d0e0f', 'encryptionKey': '101112131415161718191a1b1c1d1e1f', 'ciphertext': '1af38c2dc2b96ffdd86694092341bc04' + 'c80edfa32ddf39d5ef00c0b468834279' + 'a2e46a1b8049f792f76bfe54b903a9c9' + 'a94ac9b47ad2655c5f10f9aef71427e2' + 'fc6f9b3f399a221489f16362c7032336' + '09d45ac69864e3321cf82935ac4096c8' + '6e133314c54019e8ca7980dfa4b9cf1b' + '384c486f3a54c51078158ee5d79de59f' + 'bd34d848b3d69550a67646344427ade5' + '4b8851ffb598f7f80074b9473c82e2db' + '652c3fa36b0a7c5b3219fab3a30bc1c4', 'aad': '546865207365636f6e64207072696e63' + '69706c65206f66204175677573746520' + '4b6572636b686f666673', 'hashAlgoName': 'SHA-256', 'ivSize': 16, 'tagSize': 16 }, { 'macKey': '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', 'encryptionKey': '202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f', 'ciphertext': '1af38c2dc2b96ffdd86694092341bc04' + '4affaaadb78c31c5da4b1b590d10ffbd' + '3dd8d5d302423526912da037ecbcc7bd' + '822c301dd67c373bccb584ad3e9279c2' + 'e6d12a1374b77f077553df829410446b' + '36ebd97066296ae6427ea75c2e0846a1' + '1a09ccf5370dc80bfecbad28c73f09b3' + 'a3b75e662a2594410ae496b2e2e6609e' + '31e6e02cc837f053d21f37ff4f51950b' + 'be2638d09dd7a4930930806d0703b1f6' + '4dd3b4c088a7f45c216839645b2012bf' + '2e6269a8c56a816dbc1b267761955bc5', 'aad': '546865207365636f6e64207072696e6369706c65206f662041756775737465204b6572636b686f666673', 'hashAlgoName': 'SHA-512', 'ivSize': 16, 'tagSize': 32 }, ]; for (let i = 0; i < RFC_TEST_VECTORS.length; i++) { const testVector = RFC_TEST_VECTORS[i]; const aead = await aesCtrHmacFromRawKeys( Bytes.fromHex(testVector['encryptionKey']), testVector['ivSize'], testVector['hashAlgoName'], Bytes.fromHex(testVector['macKey']), testVector['tagSize']); const ciphertext = Bytes.fromHex(testVector['ciphertext']); const aad = Bytes.fromHex(testVector['aad']); try { await aead.decrypt(ciphertext, aad); } catch (e) { fail(e); } } }); });