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.

566 lines (473 loc) 19.7 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import {PbAesCtrHmacAeadKey, PbAesCtrHmacAeadKeyFormat, PbAesCtrKey, PbAesCtrKeyFormat, PbAesCtrParams, PbHashType, PbHmacKey, PbHmacKeyFormat, PbHmacParams, PbKeyData} from '../internal/proto'; import {bytesLength} from '../internal/proto_shims'; import * as Random from '../subtle/random'; import {assertExists} from '../testing/internal/test_utils'; import {AesCtrHmacAeadKeyManager} from './aes_ctr_hmac_aead_key_manager'; import {Aead} from './internal/aead'; const KEY_TYPE = 'type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey'; const VERSION = 0; ///////////////////////////////////////////////////////////////////////////// // Helper functions for tests /** creates new AesCtrHmacAeadKeyFormat with allowed parameters */ function createTestKeyFormat(): PbAesCtrHmacAeadKeyFormat { const KEY_SIZE = 16; const IV_SIZE = 12; const TAG_SIZE = 16; const keyFormat = new PbAesCtrHmacAeadKeyFormat(); const aesCtrKeyFormat = new PbAesCtrKeyFormat(); aesCtrKeyFormat.setKeySize(KEY_SIZE); const aesCtrParams = new PbAesCtrParams(); aesCtrParams.setIvSize(IV_SIZE); aesCtrKeyFormat.setParams(aesCtrParams); keyFormat.setAesCtrKeyFormat(aesCtrKeyFormat); // set HMAC key const hmacKeyFormat = new PbHmacKeyFormat(); hmacKeyFormat.setKeySize(KEY_SIZE); const hmacParams = new PbHmacParams(); hmacParams.setHash(PbHashType.SHA1); hmacParams.setTagSize(TAG_SIZE); hmacKeyFormat.setParams(hmacParams); keyFormat.setHmacKeyFormat(hmacKeyFormat); return keyFormat; } /** creates new AesCtrHmacAeadKey with allowed parameters */ function createTestKey(): PbAesCtrHmacAeadKey { const KEY_SIZE = 16; const IV_SIZE = 12; const TAG_SIZE = 16; const key = new PbAesCtrHmacAeadKey(); key.setVersion(0); const aesCtrKey = new PbAesCtrKey(); aesCtrKey.setVersion(0); const aesCtrParams = new PbAesCtrParams(); aesCtrParams.setIvSize(IV_SIZE); aesCtrKey.setParams(aesCtrParams); aesCtrKey.setKeyValue(Random.randBytes(KEY_SIZE)); key.setAesCtrKey(aesCtrKey); // set HMAC key const hmacKey = new PbHmacKey(); hmacKey.setVersion(0); const hmacParams = new PbHmacParams(); hmacParams.setHash(PbHashType.SHA1); hmacParams.setTagSize(TAG_SIZE); hmacKey.setParams(hmacParams); hmacKey.setKeyValue(Random.randBytes(KEY_SIZE)); key.setHmacKey(hmacKey); return key; } /** creates new PbKeyData with allowed parameters */ function createTestKeyData(): PbKeyData { const keyData = new PbKeyData() .setTypeUrl(KEY_TYPE) .setValue(createTestKey().serializeBinary()) .setKeyMaterialType(PbKeyData.KeyMaterialType.SYMMETRIC); return keyData; } describe('aes ctr hmac aead key manager test', function() { ///////////////////////////////////////////////////////////////////////////// // tests for newKey method // newKey method -- key formats it('new key bad key format', async function() { const keyFormat = new PbAesCtrKeyFormat(); const manager = new AesCtrHmacAeadKeyManager(); try { manager.getKeyFactory().newKey(keyFormat); } catch (e: any) { expect(e.toString()) .toBe('SecurityException: Expected AesCtrHmacAeadKeyFormat-proto'); return; } fail('An exception should be thrown.'); }); it('new key bad serialized key', async function() { // this is not a serialized key format const serializedKeyFormat = new Uint8Array(4); const manager = new AesCtrHmacAeadKeyManager(); try { manager.getKeyFactory().newKey(serializedKeyFormat); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Could not parse the given Uint8Array as a serialized' + ' proto of ' + KEY_TYPE); return; } fail('An exception should be thrown.'); }); // newKey method -- bad parametrs of AES CTR KEY format it('new key not supported aes ctr key size', async function() { const keySize: number = 11; const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); keyFormat.getAesCtrKeyFormat()?.setKeySize(keySize); try { manager.getKeyFactory().newKey(keyFormat); } catch (e: any) { expect(e.toString()) .toBe( 'InvalidArgumentsException: unsupported AES key size: ' + keySize); return; } fail('An exception should be thrown.'); }); it('new key iv size out of range', async function() { const ivSizeOutOfRange: number[] = [10, 18]; const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); const ivSizeOutOfRangeLength = ivSizeOutOfRange.length; for (let i = 0; i < ivSizeOutOfRangeLength; i++) { keyFormat.getAesCtrKeyFormat()?.getParams()?.setIvSize( ivSizeOutOfRange[i]); try { manager.getKeyFactory().newKey(keyFormat); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid AES CTR HMAC key format: IV size is ' + 'out of range: ' + ivSizeOutOfRange[i]); continue; } fail('An exception should be thrown.'); } }); // newKey method -- bad parametrs of HMAC KEY format it('new key small hmac key size', async function() { const keySize: number = 11; const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); keyFormat.getHmacKeyFormat()?.setKeySize(keySize); try { manager.getKeyFactory().newKey(keyFormat); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid AES CTR HMAC key format: HMAC key is' + ' too small: ' + keySize); return; } fail('An exception should be thrown.'); }); it('new key hash type unsupported', async function() { const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); keyFormat.getHmacKeyFormat()?.getParams()?.setHash(PbHashType.UNKNOWN_HASH); try { manager.getKeyFactory().newKey(keyFormat); } catch (e: any) { expect(e.toString()).toBe('SecurityException: Unknown hash type.'); return; } fail('An exception should be thrown.'); }); it('new key small tag size', async function() { const SMALL_TAG_SIZE = 8; const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); keyFormat.getHmacKeyFormat()?.getParams()?.setTagSize(SMALL_TAG_SIZE); try { manager.getKeyFactory().newKey(keyFormat); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid HMAC params: tag size ' + SMALL_TAG_SIZE + ' is too small.'); return; } fail('An exception should be thrown.'); }); it('new key big tag size for hash type', async function() { const tagSizes = [ {'hashType': PbHashType.SHA1, 'tagSize': 22}, {'hashType': PbHashType.SHA256, 'tagSize': 34}, {'hashType': PbHashType.SHA512, 'tagSize': 66}, ]; const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); const tagSizesLength = tagSizes.length; for (let i = 0; i < tagSizesLength; i++) { keyFormat.getHmacKeyFormat()?.getParams()?.setHash( tagSizes[i]['hashType']); keyFormat.getHmacKeyFormat()?.getParams()?.setTagSize( tagSizes[i]['tagSize']); try { manager.getKeyFactory().newKey(keyFormat); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid HMAC params: tag size ' + tagSizes[i]['tagSize'] + ' is out of range.'); continue; } fail('An exception should be thrown.'); } }); it('new key via format proto', async function() { const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); const key = manager.getKeyFactory().newKey(keyFormat); // testing AES CTR key expect(bytesLength(key.getAesCtrKey()?.getKeyValue())) .toBe(keyFormat.getAesCtrKeyFormat()?.getKeySize()); expect(key.getAesCtrKey()?.getVersion()).toBe(0); expect(key.getAesCtrKey()?.getParams()?.getIvSize()) .toBe(keyFormat.getAesCtrKeyFormat()?.getParams()?.getIvSize()); // testing HMAC key expect(bytesLength(key.getHmacKey()?.getKeyValue())) .toBe(keyFormat.getHmacKeyFormat()?.getKeySize()); expect(key.getHmacKey()?.getVersion()).toBe(0); expect(key.getHmacKey()?.getParams()?.getHash()) .toBe(keyFormat.getHmacKeyFormat()?.getParams()?.getHash()); expect(key.getHmacKey()?.getParams()?.getTagSize()) .toBe(keyFormat.getHmacKeyFormat()?.getParams()?.getTagSize()); }); it('new key via serialized format proto', async function() { const manager = new AesCtrHmacAeadKeyManager(); const keyFormat = createTestKeyFormat(); const serializedKeyFormat = keyFormat.serializeBinary(); const key = manager.getKeyFactory().newKey(serializedKeyFormat); // testing AES CTR key expect(bytesLength(key.getAesCtrKey()?.getKeyValue())) .toBe(keyFormat.getAesCtrKeyFormat()?.getKeySize()); expect(key.getAesCtrKey()?.getVersion()).toBe(0); expect(key.getAesCtrKey()?.getParams()?.getIvSize()) .toBe(keyFormat.getAesCtrKeyFormat()?.getParams()?.getIvSize()); // testing HMAC key expect(bytesLength(key.getHmacKey()?.getKeyValue())) .toBe(keyFormat.getHmacKeyFormat()?.getKeySize()); expect(key.getHmacKey()?.getVersion()).toBe(0); expect(key.getHmacKey()?.getParams()?.getHash()) .toBe(keyFormat.getHmacKeyFormat()?.getParams()?.getHash()); expect(key.getHmacKey()?.getParams()?.getTagSize()) .toBe(keyFormat.getHmacKeyFormat()?.getParams()?.getTagSize()); }); ///////////////////////////////////////////////////////////////////////////// // tests for NewKeyData method it('new key data bad serialized key', async function() { const serializedKeyFormats = [new Uint8Array(1), new Uint8Array(0)]; const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const serializedKeyFormatsLength = serializedKeyFormats.length; for (let i = 0; i < serializedKeyFormatsLength; i++) { try { aeadKeyManager.getKeyFactory().newKeyData(serializedKeyFormats[i]); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Could not parse the given Uint8Array as a ' + 'serialized proto of ' + KEY_TYPE); continue; } fail( 'An exception should be thrown for the string: ' + serializedKeyFormats[i]); } }); it('new key data from valid key', async function() { const keyFormat = createTestKeyFormat(); const serializedKeyFormat = keyFormat.serializeBinary(); const manager = new AesCtrHmacAeadKeyManager(); const keyData = manager.getKeyFactory().newKeyData(serializedKeyFormat); expect(keyData.getTypeUrl()).toBe(KEY_TYPE); expect(keyData.getKeyMaterialType()) .toBe(PbKeyData.KeyMaterialType.SYMMETRIC); const key = PbAesCtrHmacAeadKey.deserializeBinary(keyData.getValue()); expect(bytesLength(key.getAesCtrKey()?.getKeyValue())) .toBe(keyFormat.getAesCtrKeyFormat()?.getKeySize()); expect(bytesLength(key.getHmacKey()?.getKeyValue())) .toBe(keyFormat.getHmacKeyFormat()?.getKeySize()); }); ///////////////////////////////////////////////////////////////////////////// // tests for getPrimitive method it('get primitive unsupported key data type', async function() { const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const keyData = createTestKeyData().setTypeUrl('bad type url'); try { await aeadKeyManager.getPrimitive(Aead, keyData); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Key type ' + keyData.getTypeUrl() + ' is not supported. This key manager supports ' + KEY_TYPE + '.'); return; } fail('An exception should be thrown'); }); it('get primitive unsupported key type', async function() { const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const key = new PbAesCtrKey(); try { await aeadKeyManager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Given key type is not supported. ' + 'This key manager supports ' + KEY_TYPE + '.'); return; } fail('An exception should be thrown'); }); it('get primitive bad version', async function() { const version = 1; const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const key: PbAesCtrHmacAeadKey = createTestKey(); key.getAesCtrKey()?.setVersion(version); try { await aeadKeyManager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Version is out of bound, must be between 0 ' + 'and ' + VERSION + '.'); return; } fail('An exception should be thrown'); }); it('get primitive short aes ctr key', async function() { const keySize = 5; const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const key: PbAesCtrHmacAeadKey = createTestKey(); key.getAesCtrKey()?.setKeyValue(new Uint8Array(keySize)); try { await aeadKeyManager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()) .toBe( 'InvalidArgumentsException: unsupported AES key size: ' + keySize); return; } fail('An exception should be thrown'); }); it('get primitive aes ctr key small iv size', async function() { const ivSizeOutOfRange: number[] = [9, 19]; const manager = new AesCtrHmacAeadKeyManager(); const key: PbAesCtrHmacAeadKey = createTestKey(); const ivSizeOutOfRangeLength = ivSizeOutOfRange.length; for (let i = 0; i < ivSizeOutOfRangeLength; i++) { key.getAesCtrKey()?.getParams()?.setIvSize(ivSizeOutOfRange[i]); try { await manager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid AES CTR HMAC key format: IV size is ' + 'out of range: ' + ivSizeOutOfRange[i]); continue; } fail('An exception should be thrown.'); } }); it('get primitive short hmac key', async function() { const keySize = 5; const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const key: PbAesCtrHmacAeadKey = createTestKey(); key.getHmacKey()?.setKeyValue(new Uint8Array(keySize)); try { await aeadKeyManager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid AES CTR HMAC key format: HMAC key is' + ' too small: ' + keySize); return; } fail('An exception should be thrown'); }); it('get primitive hmac key unsupported hash type', async function() { const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const key: PbAesCtrHmacAeadKey = createTestKey(); key.getHmacKey()?.getParams()?.setHash(PbHashType.UNKNOWN_HASH); try { await aeadKeyManager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()).toBe('SecurityException: Unknown hash type.'); return; } fail('An exception should be thrown'); }); it('get primitive hmac key small tag size', async function() { const SMALL_TAG_SIZE = 9; const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const key: PbAesCtrHmacAeadKey = createTestKey(); key.getHmacKey()?.getParams()?.setTagSize(SMALL_TAG_SIZE); try { await aeadKeyManager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid HMAC params: tag size ' + SMALL_TAG_SIZE + ' is too small.'); return; } fail('An exception should be thrown'); }); it('get primitive hmac big tag size', async function() { const tagSizes = [ {'hashType': PbHashType.SHA1, 'tagSize': 22}, {'hashType': PbHashType.SHA256, 'tagSize': 34}, {'hashType': PbHashType.SHA512, 'tagSize': 66}, ]; const manager = new AesCtrHmacAeadKeyManager(); const key: PbAesCtrHmacAeadKey = createTestKey(); const tagSizesLength = tagSizes.length; for (let i = 0; i < tagSizesLength; i++) { const params = assertExists(key.getHmacKey()?.getParams()); params.setHash(tagSizes[i]['hashType']); params.setTagSize(tagSizes[i]['tagSize']); try { await manager.getPrimitive(Aead, key); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: Invalid HMAC params: tag size ' + tagSizes[i]['tagSize'] + ' is out of range.'); continue; } fail('An exception should be thrown.'); } }); // tests for getting primitive from valid key/keyData it('get primitive from key', async function() { const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const key = createTestKey(); const plaintext = Random.randBytes(8); const aad = Random.randBytes(8); const primitive: Aead = await aeadKeyManager.getPrimitive(Aead, key); const ciphertext = await primitive.encrypt(plaintext, aad); const decryptedCiphertext = await primitive.decrypt(ciphertext, aad); expect(decryptedCiphertext).toEqual(plaintext); }); it('get primitive from key data', async function() { const aeadKeyManager = new AesCtrHmacAeadKeyManager(); const keyData = createTestKeyData(); const plaintext = Random.randBytes(8); const aad = Random.randBytes(8); const primitive: Aead = await aeadKeyManager.getPrimitive(Aead, keyData); const ciphertext = await primitive.encrypt(plaintext, aad); const decryptedCiphertext = await primitive.decrypt(ciphertext, aad); expect(decryptedCiphertext).toEqual(plaintext); }); ///////////////////////////////////////////////////////////////////////////// // tests for getVersion, getKeyType and doesSupport methods it('get version should be zero', async function() { const manager = new AesCtrHmacAeadKeyManager(); expect(manager.getVersion()).toBe(0); }); it('get key type should be aes ctr hmac aead key', async function() { const manager = new AesCtrHmacAeadKeyManager(); expect(manager.getKeyType()).toBe(KEY_TYPE); }); it('does support should support aes ctr hmac aead key', async function() { const manager = new AesCtrHmacAeadKeyManager(); expect(manager.doesSupport(KEY_TYPE)).toBe(true); }); it('get primitive type should be aead', async function() { const manager = new AesCtrHmacAeadKeyManager(); expect(manager.getPrimitiveType()).toBe(Aead); }); });