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.

794 lines (671 loc) 27.9 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import {Aead} from '../aead'; import {AeadConfig} from '../aead/aead_config'; import {AeadKeyTemplates} from '../aead/aead_key_templates'; import {AesCtrHmacAeadKeyManager} from '../aead/aes_ctr_hmac_aead_key_manager'; import {SecurityException} from '../exception/security_exception'; import * as HybridConfig from '../hybrid/hybrid_config'; import {HybridKeyTemplates} from '../hybrid/hybrid_key_templates'; import {Mac} from '../mac'; import {EncryptThenAuthenticate} from '../subtle/encrypt_then_authenticate'; import {assertExists, assertInstanceof} from '../testing/internal/test_utils'; import * as KeyManager from './key_manager'; import * as PrimitiveSet from './primitive_set'; import {PrimitiveWrapper} from './primitive_wrapper'; import {PbAesCtrHmacAeadKey, PbAesCtrHmacAeadKeyFormat, PbAesCtrKey, PbAesCtrKeyFormat, PbAesCtrParams, PbEciesAeadHkdfPrivateKey, PbEciesAeadHkdfPublicKey, PbHashType, PbHmacKeyFormat, PbHmacParams, PbKeyData, PbKeyTemplate, PbMessage} from './proto'; import {bytesAsU8, bytesLength} from './proto_shims'; import * as Registry from './registry'; import {Constructor} from './util'; //////////////////////////////////////////////////////////////////////////////// // tests //////////////////////////////////////////////////////////////////////////////// describe('registry test', function() { afterEach(function() { Registry.reset(); }); ///////////////////////////////////////////////////////////////////////////// // tests for registerPrimitiveWrapper method it('register primitive wrapper, overwriting with same class', function() { Registry.registerPrimitiveWrapper(new DummyPrimitiveWrapper1( new DummyPrimitive1Impl1(), DummyPrimitive1)); Registry.registerPrimitiveWrapper(new DummyPrimitiveWrapper1( new DummyPrimitive1Impl2(), DummyPrimitive1)); }); it('register primitive wrapper, overwriting with different class', function() { class DummyPrimitiveWrapper1Alternative implements PrimitiveWrapper<DummyPrimitive1> { wrap(): DummyPrimitive1 { throw new Error(); } getPrimitiveType() { return DummyPrimitive1; } } Registry.registerPrimitiveWrapper(new DummyPrimitiveWrapper1( new DummyPrimitive1Impl1(), DummyPrimitive1)); try { Registry.registerPrimitiveWrapper( new DummyPrimitiveWrapper1Alternative()); fail('An exception should be thrown.'); } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: primitive wrapper for type ' + DummyPrimitive1 + ' has already been registered and cannot be overwritten'); } }); ///////////////////////////////////////////////////////////////////////////// // tests for wrap method it('wrap, should work', function() { const p1 = new DummyPrimitive1Impl1(); const p2 = new DummyPrimitive2Impl(); Registry.registerPrimitiveWrapper( new DummyPrimitiveWrapper1(p1, DummyPrimitive1)); Registry.registerPrimitiveWrapper( new DummyPrimitiveWrapper2(p2, DummyPrimitive2)); expect(Registry.wrap(new PrimitiveSet.PrimitiveSet(DummyPrimitive1))) .toBe(p1); expect(Registry.wrap(new PrimitiveSet.PrimitiveSet(DummyPrimitive2))) .toBe(p2); }); it('wrap, not registered primitive type', function() { expect(() => { Registry.wrap(new PrimitiveSet.PrimitiveSet(DummyPrimitive1)); }).toThrowError('no primitive wrapper found for type ' + DummyPrimitive1); }); ///////////////////////////////////////////////////////////////////////////// // tests for registerKeyManager method it('register key manager, overwriting attempt', function() { const keyType = 'someKeyType'; try { Registry.registerKeyManager(new DummyKeyManager1(keyType)); Registry.registerKeyManager(new DummyKeyManager2(keyType)); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.keyManagerOverwrittingAttempt(keyType)); return; } fail('An exception should be thrown.'); }); // Testing newKeyAllowed behavior -- should hold the most restrictive setting. it('register key manager, more restrictive new key allowed', async function() { const keyType = 'someTypeUrl'; const keyManager1 = new DummyKeyManager1(keyType); const keyTemplate = new PbKeyTemplate().setTypeUrl(keyType); // Register the key manager with new_key_allowed and test that it is // possible to create a new key data. Registry.registerKeyManager(keyManager1); await Registry.newKeyData(keyTemplate); // Restrict the key manager and test that new key data cannot be created. Registry.registerKeyManager(keyManager1, false); try { await Registry.newKeyData(keyTemplate); } catch (e: any) { expect(e.toString()).toBe(ExceptionText.newKeyForbidden(keyType)); return; } fail('An exception should be thrown.'); }); it('register key manager, less restrictive new key allowed', async function() { const keyType = 'someTypeUrl'; const keyManager1 = new DummyKeyManager1(keyType); const keyTemplate = new PbKeyTemplate().setTypeUrl(keyType); Registry.registerKeyManager(keyManager1, false); // Re-registering key manager with less restrictive setting should not be // possible and the restriction has to be still true (i.e. new key data // cannot be created). try { Registry.registerKeyManager(keyManager1); fail('An exception should be thrown.'); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.prohibitedChangeToLessRestricted( keyManager1.getKeyType())); } try { await Registry.newKeyData(keyTemplate); } catch (e: any) { expect(e.toString()).toBe(ExceptionText.newKeyForbidden(keyType)); return; } fail('An exception should be thrown.'); }); ///////////////////////////////////////////////////////////////////////////// // tests for getKeyManager method it('get key manager, should work', function() { const numberOfKeyManagers = 10; const keyManagers1 = []; const keyManagers2 = []; for (let i = 0; i < numberOfKeyManagers; i++) { keyManagers1.push(new DummyKeyManager1('someKeyType' + i.toString())); keyManagers2.push(new DummyKeyManager2('otherKeyType' + i.toString())); Registry.registerKeyManager(keyManagers1[i]); Registry.registerKeyManager(keyManagers2[i]); } let result; for (let i = 0; i < numberOfKeyManagers; i++) { result = Registry.getKeyManager(keyManagers1[i].getKeyType()); expect(result).toEqual(keyManagers1[i]); result = Registry.getKeyManager(keyManagers2[i].getKeyType()); expect(result).toEqual(keyManagers2[i]); } }); it('get key manager, not registered key type', function() { const keyType = 'some_key_type'; try { Registry.getKeyManager(keyType); } catch (e: any) { expect(e.toString()).toBe(ExceptionText.notRegisteredKeyType(keyType)); return; } fail('An exception should be thrown.'); }); ///////////////////////////////////////////////////////////////////////////// // tests for newKeyData method it('new key data, no manager for given key type', async function() { const keyManager1 = new DummyKeyManager1('someKeyType'); const differentKeyType = 'otherKeyType'; const keyTemplate = new PbKeyTemplate().setTypeUrl(differentKeyType); Registry.registerKeyManager(keyManager1); try { await Registry.newKeyData(keyTemplate); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.notRegisteredKeyType(differentKeyType)); return; } fail('An exception should be thrown.'); }); it('new key data, new key disallowed', async function() { const keyManager1 = new DummyKeyManager1('someKeyType'); const keyTemplate = new PbKeyTemplate().setTypeUrl(keyManager1.getKeyType()); Registry.registerKeyManager(keyManager1, false); try { await Registry.newKeyData(keyTemplate); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.newKeyForbidden(keyManager1.getKeyType())); return; } fail('An exception should be thrown.'); }); it('new key data, new key allowed', async function() { const keyTypes: string[] = []; for (let i = 0; i < 10; i++) { keyTypes.push('someKeyType' + i.toString()); } const keyTypesLength = keyTypes.length; for (let i = 0; i < keyTypesLength; i++) { Registry.registerKeyManager(new DummyKeyManager1(keyTypes[i]), true); } for (let i = 0; i < keyTypesLength; i++) { const keyTemplate = new PbKeyTemplate().setTypeUrl(keyTypes[i]); const result = await Registry.newKeyData(keyTemplate); expect(result.getTypeUrl()).toBe(keyTypes[i]); } }); it('new key data, new key is allowed automatically', async function() { const keyTypes: string[] = []; for (let i = 0; i < 10; i++) { keyTypes.push('someKeyType' + i.toString()); } const keyTypesLength = keyTypes.length; for (let i = 0; i < keyTypesLength; i++) { Registry.registerKeyManager(new DummyKeyManager1(keyTypes[i])); } for (let i = 0; i < keyTypesLength; i++) { const keyTemplate = new PbKeyTemplate().setTypeUrl(keyTypes[i]); const result = await Registry.newKeyData(keyTemplate); expect(result.getTypeUrl()).toBe(keyTypes[i]); } }); it('new key data, with aes ctr hmac aead key', async function() { const manager = new AesCtrHmacAeadKeyManager(); Registry.registerKeyManager(manager); const keyTemplate = createAesCtrHmacAeadTestKeyTemplate(); const keyData = await Registry.newKeyData(keyTemplate); // Checks that correct AES CTR HMAC AEAD key was returned. const keyFormat = PbAesCtrHmacAeadKeyFormat.deserializeBinary(keyTemplate.getValue()); const key = PbAesCtrHmacAeadKey.deserializeBinary(keyData.getValue()); // Check AES CTR key. expect(keyFormat.getAesCtrKeyFormat()?.getKeySize()) .toBe(bytesLength(key.getAesCtrKey()?.getKeyValue())); expect(keyFormat.getAesCtrKeyFormat()?.getParams()) .toEqual(key.getAesCtrKey()?.getParams()); // Check HMAC key. expect(keyFormat.getHmacKeyFormat()?.getKeySize()) .toBe(bytesLength(key.getHmacKey()?.getKeyValue())); expect(keyFormat.getHmacKeyFormat()?.getParams()) .toEqual(key.getHmacKey()?.getParams()); }); ///////////////////////////////////////////////////////////////////////////// // tests for newKey method it('new key, no manager for given key type', async function() { const notRegisteredKeyType = 'not_registered_key_type'; const keyTemplate = new PbKeyTemplate().setTypeUrl(notRegisteredKeyType); try { await Registry.newKey(keyTemplate); fail('An exception should be thrown.'); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.notRegisteredKeyType(notRegisteredKeyType)); } }); it('new key, new key disallowed', async function() { const keyManager = new DummyKeyManagerForNewKeyTests('someKeyType'); const keyTemplate = new PbKeyTemplate().setTypeUrl(keyManager.getKeyType()); Registry.registerKeyManager(keyManager, /* opt_newKeyAllowed = */ false); try { await Registry.newKey(keyTemplate); fail('An exception should be thrown.'); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.newKeyForbidden(keyManager.getKeyType())); } }); it('new key, should work', async function() { const keyTypes: string[] = []; const newKeyMethodResult: Uint8Array[] = []; const keyTypesLength = 10; // Add some keys to Registry. for (let i = 0; i < keyTypesLength; i++) { keyTypes.push('someKeyType' + i.toString()); newKeyMethodResult.push(new Uint8Array([i + 1])); Registry.registerKeyManager( new DummyKeyManagerForNewKeyTests(keyTypes[i], newKeyMethodResult[i]), /* newKeyAllowed = */ true); } // For every keyType verify that it calls new key method of the // corresponding KeyManager (KeyFactory). for (let i = 0; i < keyTypesLength; i++) { const keyTemplate = new PbKeyTemplate().setTypeUrl(keyTypes[i]); const key = assertInstanceof(await Registry.newKey(keyTemplate), PbAesCtrKey); // The new key method of DummyKeyFactory returns an AesCtrKey which // KeyValue is set to corresponding value in newKeyMethodResult. expect(bytesAsU8(key.getKeyValue())).toEqual(newKeyMethodResult[i]); } }); it('new key, with aes ctr hmac aead key', async function() { const manager = new AesCtrHmacAeadKeyManager(); Registry.registerKeyManager(manager); const keyTemplate = AeadKeyTemplates.aes256CtrHmacSha256(); const key = assertInstanceof( await Registry.newKey(keyTemplate), PbAesCtrHmacAeadKey); // Checks that correct AES CTR HMAC AEAD key was returned. const keyFormat = PbAesCtrHmacAeadKeyFormat.deserializeBinary(keyTemplate.getValue()); // Check AES CTR key. expect(keyFormat.getAesCtrKeyFormat()?.getKeySize()) .toBe(bytesLength(key.getAesCtrKey()?.getKeyValue())); expect(keyFormat.getAesCtrKeyFormat()?.getParams()) .toEqual(key.getAesCtrKey()?.getParams()); // Check HMAC key. expect(keyFormat.getHmacKeyFormat()?.getKeySize()) .toBe(bytesLength(key.getHmacKey()?.getKeyValue())); expect(keyFormat.getHmacKeyFormat()?.getParams()) .toEqual(key.getHmacKey()?.getParams()); }); ///////////////////////////////////////////////////////////////////////////// // tests for getPrimitive method it('get primitive, different key types', async function() { const keyDataType = 'key_data_key_type_url'; const anotherType = 'another_key_type_url'; const keyData = new PbKeyData().setTypeUrl(keyDataType); try { await Registry.getPrimitive(Aead, keyData, anotherType); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.keyTypesAreNotMatching(keyDataType, anotherType)); return; } fail('An exception should be thrown.'); }); it('get primitive, without defining key type', async function() { // Get primitive from key proto without key type. try { await Registry.getPrimitive(Aead, new PbHmacParams()); fail('An exception should be thrown.'); } catch (e: any) { expect(e.toString()).toBe(ExceptionText.keyTypeNotDefined()); } }); it('get primitive, missing key manager', async function() { const keyDataType = 'key_data_key_type_url'; const keyData = new PbKeyData().setTypeUrl(keyDataType); try { await Registry.getPrimitive(Aead, keyData); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.notRegisteredKeyType(keyDataType)); return; } fail('An exception should be thrown.'); }); it('get primitive, from aes ctr hmac aead key data', async function() { const manager = new AesCtrHmacAeadKeyManager(); Registry.registerKeyManager(manager); const keyTemplate = createAesCtrHmacAeadTestKeyTemplate(); const keyData = await Registry.newKeyData(keyTemplate); const primitive = await Registry.getPrimitive(manager.getPrimitiveType(), keyData); expect(primitive instanceof EncryptThenAuthenticate).toBe(true); }); it('get primitive, from aes ctr hmac aead key', async function() { const manager = new AesCtrHmacAeadKeyManager(); Registry.registerKeyManager(manager); const keyTemplate = createAesCtrHmacAeadTestKeyTemplate(); const keyData = await Registry.newKeyData(keyTemplate); const key = PbAesCtrHmacAeadKey.deserializeBinary(keyData.getValue()); const primitive = await Registry.getPrimitive( manager.getPrimitiveType(), key, keyData.getTypeUrl()); expect(primitive instanceof EncryptThenAuthenticate).toBe(true); }); it('get primitive, mac from aes ctr hmac aead key', async function() { const manager = new AesCtrHmacAeadKeyManager(); Registry.registerKeyManager(manager); const keyTemplate = createAesCtrHmacAeadTestKeyTemplate(); const keyData = await Registry.newKeyData(keyTemplate); const key = PbAesCtrHmacAeadKey.deserializeBinary(keyData.getValue()); try { await Registry.getPrimitive(Mac, key, keyData.getTypeUrl()); } catch (e: any) { expect(e.toString().includes(ExceptionText.getPrimitiveBadPrimitive())) .toBe(true); return; } fail('An exception should be thrown.'); }); describe('get public key data', function() { it('not private key factory', function() { AeadConfig.register(); const notPrivateTypeUrl = AeadConfig.AES_GCM_TYPE_URL; try { Registry.getPublicKeyData(notPrivateTypeUrl, new Uint8Array(8)); fail('An exception should be thrown.'); } catch (e: any) { expect(e.toString()) .toBe(ExceptionText.notPrivateKeyFactory(notPrivateTypeUrl)); } }); it('invalid private key proto serialization', function() { HybridConfig.register(); const typeUrl = HybridConfig.ECIES_AEAD_HKDF_PRIVATE_KEY_TYPE; try { Registry.getPublicKeyData(typeUrl, new Uint8Array(10)); fail('An exception should be thrown.'); } catch (e: any) { expect(e.toString()).toBe(ExceptionText.couldNotParse(typeUrl)); } }); it('should work', async function() { HybridConfig.register(); const privateKeyData = await Registry.newKeyData( HybridKeyTemplates.eciesP256HkdfHmacSha256Aes128Gcm()); const privateKey = PbEciesAeadHkdfPrivateKey.deserializeBinary( privateKeyData.getValue()); const publicKeyData = Registry.getPublicKeyData( privateKeyData.getTypeUrl(), bytesAsU8(privateKeyData.getValue())); expect(HybridConfig.ECIES_AEAD_HKDF_PUBLIC_KEY_TYPE) .toBe(publicKeyData.getTypeUrl()); expect(PbKeyData.KeyMaterialType.ASYMMETRIC_PUBLIC) .toBe(publicKeyData.getKeyMaterialType()); const expectedPublicKey = assertExists(privateKey.getPublicKey()); const publicKey = PbEciesAeadHkdfPublicKey.deserializeBinary(publicKeyData.getValue()); expect(publicKey).toEqual(expectedPublicKey); }); }); }); //////////////////////////////////////////////////////////////////////////////// // helper functions and classes for tests //////////////////////////////////////////////////////////////////////////////// /** * Class which holds texts for each type of exception. * @final */ class ExceptionText { static notImplemented(): string { return 'SecurityException: Not implemented yet.'; } static newKeyForbidden(keyType: string): string { return 'SecurityException: New key operation is forbidden for key type: ' + keyType + '.'; } static notRegisteredKeyType(keyType: string): string { return 'SecurityException: Key manager for key type ' + keyType + ' has not been registered.'; } static nullKeyManager(): string { return 'SecurityException: Key manager cannot be null.'; } static undefinedKeyType(): string { return 'SecurityException: Key type has to be defined.'; } static keyManagerOverwrittingAttempt(keyType: string): string { return 'SecurityException: Key manager for key type ' + keyType + ' has already been registered and cannot be overwritten.'; } static notSupportedKey(givenKeyType: string): string { return 'SecurityException: The provided key manager does not support ' + 'key type ' + givenKeyType + '.'; } static prohibitedChangeToLessRestricted(keyType: string): string { return 'SecurityException: Key manager for key type ' + keyType + ' has already been registered with forbidden new key operation.'; } static keyTypesAreNotMatching( keyTypeFromKeyData: string, keyTypeParam: string): string { return 'SecurityException: Key type is ' + keyTypeParam + ', but it is expected to be ' + keyTypeFromKeyData + ' or undefined.'; } static keyTypeNotDefined(): string { return 'SecurityException: Key type has to be specified.'; } static nullKeysetHandle(): string { return 'SecurityException: Keyset handle has to be non-null.'; } static getPrimitiveBadPrimitive(): string { return 'Requested primitive type which is not supported by this ' + 'key manager.'; } static notPrivateKeyFactory(typeUrl: string): string { return 'SecurityException: Key manager for key type ' + typeUrl + ' does not have a private key factory.'; } static couldNotParse(typeUrl: string): string { return 'SecurityException: Input cannot be parsed as ' + typeUrl + ' key-proto.'; } } /** Creates AES CTR HMAC AEAD key format which can be used in tests */ function createAesCtrHmacAeadTestKeyTemplate(): PbKeyTemplate { const KEY_SIZE = 16; const IV_SIZE = 12; const TAG_SIZE = 16; const keyFormat = new PbAesCtrHmacAeadKeyFormat().setAesCtrKeyFormat( new PbAesCtrKeyFormat()); keyFormat.getAesCtrKeyFormat()?.setKeySize(KEY_SIZE); keyFormat.getAesCtrKeyFormat()?.setParams(new PbAesCtrParams()); keyFormat.getAesCtrKeyFormat()?.getParams()?.setIvSize(IV_SIZE); // set HMAC key keyFormat.setHmacKeyFormat(new PbHmacKeyFormat()); keyFormat.getHmacKeyFormat()?.setKeySize(KEY_SIZE); keyFormat.getHmacKeyFormat()?.setParams(new PbHmacParams()); keyFormat.getHmacKeyFormat()?.getParams()?.setHash(PbHashType.SHA1); keyFormat.getHmacKeyFormat()?.getParams()?.setTagSize(TAG_SIZE); let keyTemplate = new PbKeyTemplate() .setTypeUrl( 'type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey') .setValue(keyFormat.serializeBinary()); return keyTemplate; } // Key factory and key manager classes used in tests /** @final */ class DummyKeyFactory implements KeyManager.KeyFactory { constructor( private readonly keyType: string, private readonly newKeyMethodResult = new Uint8Array(10)) {} /** */ newKey(keyFormat: PbMessage|Uint8Array) { const key = new PbAesCtrKey().setKeyValue(this.newKeyMethodResult); return key; } /** */ newKeyData(serializedKeyFormat: Uint8Array) { const keyData = new PbKeyData() .setTypeUrl(this.keyType) .setValue(this.newKeyMethodResult) .setKeyMaterialType(PbKeyData.KeyMaterialType.UNKNOWN_KEYMATERIAL); return keyData; } } // Primitive abstract types for testing purposes. abstract class DummyPrimitive1 { abstract operation1(): number; } abstract class DummyPrimitive2 { abstract operation2(): string; } // Primitive implementations for testing purposes. class DummyPrimitive1Impl1 extends DummyPrimitive1 { operation1() { return 1; } } class DummyPrimitive1Impl2 extends DummyPrimitive1 { operation1() { return 2; } } class DummyPrimitive2Impl extends DummyPrimitive2 { operation2() { return 'dummy'; } } const DEFAULT_PRIMITIVE_TYPE = Aead; /** @final */ class DummyKeyManager1 implements KeyManager.KeyManager<DummyPrimitive1> { private readonly KEY_FACTORY: KeyManager.KeyFactory; constructor( private readonly keyType: string, private readonly primitive: DummyPrimitive1 = new DummyPrimitive1Impl1(), private readonly primitiveType = DummyPrimitive1) { this.KEY_FACTORY = new DummyKeyFactory(keyType); } async getPrimitive( primitiveType: Constructor<DummyKeyManager1>, key: PbKeyData|PbMessage) { return this.primitive; } doesSupport(keyType: string) { return keyType === this.getKeyType(); } getKeyType() { return this.keyType; } getPrimitiveType(): Constructor<DummyPrimitive1> { return this.primitiveType; } getVersion(): number { throw new SecurityException('Not implemented, only for testing purposes.'); } getKeyFactory() { return this.KEY_FACTORY; } } /** @final */ class DummyKeyManager2 implements KeyManager.KeyManager<DummyPrimitive2> { private readonly KEY_FACTORY: KeyManager.KeyFactory; constructor( private readonly keyType: string, private readonly primitive: DummyPrimitive2 = new DummyPrimitive2Impl(), private readonly primitiveType = DummyPrimitive2) { this.KEY_FACTORY = new DummyKeyFactory(keyType); } async getPrimitive( primitiveType: Constructor<DummyKeyManager2>, key: PbKeyData|PbMessage) { return this.primitive; } doesSupport(keyType: string) { return keyType === this.getKeyType(); } getKeyType() { return this.keyType; } getPrimitiveType() { return this.primitiveType; } getVersion(): number { throw new SecurityException('Not implemented, only for testing purposes.'); } getKeyFactory() { return this.KEY_FACTORY; } } /** @final */ class DummyKeyManagerForNewKeyTests implements KeyManager.KeyManager<string> { private readonly KEY_FACTORY: KeyManager.KeyFactory; constructor( private readonly keyType: string, opt_newKeyMethodResult?: Uint8Array) { this.KEY_FACTORY = new DummyKeyFactory(keyType, opt_newKeyMethodResult); } async getPrimitive( primitiveType: Constructor<DummyKeyManagerForNewKeyTests>, key: PbKeyData|PbMessage): Promise<string> { throw new SecurityException('Not implemented, function is not needed.'); } doesSupport(keyType: string) { return keyType === this.getKeyType(); } getKeyType() { return this.keyType; } getPrimitiveType(): never { throw new SecurityException('Not implemented, function is not needed.'); } getVersion(): never { throw new SecurityException('Not implemented, function is not needed.'); } getKeyFactory() { return this.KEY_FACTORY; } } // PrimitiveWrapper classes for testing purposes /** @final */ class DummyPrimitiveWrapper1 implements PrimitiveWrapper<DummyPrimitive1> { constructor( private readonly primitive: DummyPrimitive1, private readonly primitiveType: Constructor<DummyPrimitive1>) {} wrap(primitiveSet: PrimitiveSet.PrimitiveSet<DummyPrimitive1>) { return this.primitive; } getPrimitiveType() { return this.primitiveType; } } /** @final */ class DummyPrimitiveWrapper2 implements PrimitiveWrapper<DummyPrimitive2> { constructor( private readonly primitive: DummyPrimitive2, private readonly primitiveType: Constructor<DummyPrimitive2>) {} wrap(primitiveSet: PrimitiveSet.PrimitiveSet<DummyPrimitive2>) { return this.primitive; } getPrimitiveType() { return this.primitiveType; } }