blob: eddccb2613960e089ec3569f0c51f1acff06681f [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
goog.module('tink.subtle.AesCtrTest');
goog.setTestOnly('tink.subtle.AesCtrTest');
const Bytes = goog.require('google3.third_party.tink.javascript.subtle.bytes');
const Random = goog.require('google3.third_party.tink.javascript.subtle.random');
const {fromRawKey: aesCtrFromRawKey} = goog.require('google3.third_party.tink.javascript.subtle.aes_ctr');
describe('aes ctr test', function() {
beforeEach(function() {
// Use a generous promise timeout for running continuously.
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 1000; // 1000s
});
afterEach(function() {
// Reset the timeout.
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; // 1s
});
it('basic', async function() {
// Set longer time for promiseTimout as the test sometimes takes longer than
// 1 second in Firefox.
const key = Random.randBytes(16);
for (let i = 0; i < 100; i++) {
const msg = Random.randBytes(20);
const cipher = await aesCtrFromRawKey(key, 16);
let ciphertext = await cipher.encrypt(msg);
let plaintext = await cipher.decrypt(ciphertext);
expect(Bytes.toHex(plaintext)).toBe(Bytes.toHex(msg));
}
});
it('probabilistic encryption', async function() {
const cipher = await aesCtrFromRawKey(Random.randBytes(16), 16);
const msg = Random.randBytes(20);
const results = new Set();
for (let i = 0; i < 100; i++) {
const ciphertext = await cipher.encrypt(msg);
results.add(Bytes.toHex(ciphertext));
}
expect(results.size).toBe(100);
});
it('constructor', async function() {
try {
await aesCtrFromRawKey(Random.randBytes(16), 11); // IV size too short
fail('Should throw an exception.');
} catch (e) {
expect(e.toString())
.toBe(
'SecurityException: invalid IV length, must be at least 12 and at most 16');
}
try {
await aesCtrFromRawKey(Random.randBytes(16), 17); // IV size too long
fail('Should throw an exception.');
} catch (e) {
expect(e.toString())
.toBe(
'SecurityException: invalid IV length, must be at least 12 and at most 16');
}
try {
await aesCtrFromRawKey(
Random.randBytes(24), 12); // 192-bit keys not supported
fail('Should throw an exception.');
} catch (e) {
expect(e.toString())
.toBe('InvalidArgumentsException: unsupported AES key size: 24');
}
});
it('constructor, invalid iv sizes', async function() {
try {
await aesCtrFromRawKey(Random.randBytes(16), NaN);
fail('Should throw an exception.');
} catch (e) {
expect(e.toString())
.toBe('SecurityException: invalid IV length, must be an integer');
}
try {
await aesCtrFromRawKey(Random.randBytes(16), 12.5);
fail('Should throw an exception.');
} catch (e) {
expect(e.toString())
.toBe('SecurityException: invalid IV length, must be an integer');
}
try {
await aesCtrFromRawKey(Random.randBytes(16), 0);
fail('Should throw an exception.');
} catch (e) {
expect(e.toString())
.toBe(
'SecurityException: invalid IV length, must be at least 12 and at most 16');
}
});
it('with test vectors', async function() {
// Test data from NIST SP 800-38A pp 55.
const NIST_TEST_VECTORS = [
{
'key': '2b7e151628aed2a6abf7158809cf4f3c',
'message':
'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51' +
'30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710',
'ciphertext':
'874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff' +
'5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee',
'iv': 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'
},
];
for (let i = 0; i < NIST_TEST_VECTORS.length; i++) {
const testVector = NIST_TEST_VECTORS[i];
const key = Bytes.fromHex(testVector['key']);
const iv = Bytes.fromHex(testVector['iv']);
const msg = Bytes.fromHex(testVector['message']);
const ciphertext = Bytes.fromHex(testVector['ciphertext']);
const aesctr = await aesCtrFromRawKey(key, iv.length);
const plaintext = await aesctr.decrypt(Bytes.concat(iv, ciphertext));
expect(Bytes.toHex(plaintext)).toBe(Bytes.toHex(msg));
}
});
});