From f538dc81b70cea82e3ebeb89376dbf20e7bdbabc Mon Sep 17 00:00:00 2001 From: seebees Date: Fri, 12 Jul 2019 11:02:08 -0700 Subject: [PATCH 01/10] fix: Encryption Context changes resolves #54 1. browser/node encrypt function public api should match 1. Encryption context should _only_ be optional in the public interface 1. Encryption context moved into cryptographic materials Internally, it is much more consistent to require an encryption context. Moving the encryption context onto the cryptographic materials brings them in line with the python keyring implementation. It also makes control of the encryption context in the CMM and **not** the keyrings very clear in the interface. NOTE: encrypt in encrypt-node now expects `encryptionContext` instead of `context`. This is **ONLY** done because the project is still in beta. --- ...yptographic_materials_cache_key_helpers.ts | 6 +- .../src/clone_cryptographic_material.ts | 23 +++---- ...cryptographic_materials_decorators.test.ts | 4 +- .../test/clone_cryptographic_material.test.ts | 12 ++-- ...ocal_cryptographic_materials_cache.test.ts | 52 ++++++---------- modules/encrypt-browser/src/encrypt.ts | 6 +- modules/encrypt-node/src/encrypt_stream.ts | 15 ++--- modules/encrypt-node/test/encrypt.test.ts | 12 ++-- modules/example-node/src/aes_simple.ts | 2 +- modules/example-node/src/kms_simple.ts | 2 +- modules/example-node/src/kms_stream.ts | 2 +- modules/example-node/src/multi_keyring.ts | 2 +- modules/example-node/src/rsa_simple.ts | 2 +- .../src/kms_keyring_browser.ts | 9 ++- .../test/kms_keyring_browser.test.ts | 4 +- .../test/kms_keyring_node.test.ts | 4 +- modules/kms-keyring/src/helpers.ts | 6 +- modules/kms-keyring/src/kms_keyring.ts | 32 +++++++--- .../test/kms_keyring.ondecrypt.test.ts | 19 +++--- .../test/kms_keyring.onencrypt.test.ts | 14 ++--- ...browser_cryptographic_materials_manager.ts | 53 ++++++++-------- ...er_cryptographic_materials_manager.test.ts | 60 +++++++++--------- .../test/keyring_helpers.test.ts | 6 +- .../test/material_helpers.test.ts | 60 +++++++++--------- .../node_cryptographic_materials_manager.ts | 56 +++++++++-------- .../test/material_helpers.test.ts | 22 +++---- ...de_cryptographic_materials_manager.test.ts | 59 +++++++++--------- .../src/cryptographic_material.ts | 61 ++++++++++++------- modules/material-management/src/keyring.ts | 16 ++--- .../material-management/src/multi_keyring.ts | 13 ++-- modules/material-management/src/types.ts | 10 ++- .../test/cryptographic_material.test.ts | 56 +++++++++++------ .../material-management/test/keyring.test.ts | 30 ++++----- .../test/multi_keyring.test.ts | 24 ++++---- .../src/raw_aes_keyring_browser.ts | 13 ++-- .../test/raw_aes_keyring_browser.test.ts | 4 +- .../src/raw_aes_keyring_node.ts | 11 ++-- .../test/raw_aes_keyring_node.test.ts | 4 +- modules/raw-keyring/src/raw_aes_material.ts | 5 +- .../raw-keyring/src/raw_keyring_decorators.ts | 15 ++--- .../test/raw_keyring_decorators.test.ts | 12 ++-- .../src/raw_rsa_keyring_web_crypto.ts | 5 +- .../test/raw_rsa_keyring_web_crypto.test.ts | 8 +-- .../test/raw_rsa_keyring_node.test.ts | 8 +-- 44 files changed, 436 insertions(+), 403 deletions(-) diff --git a/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts b/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts index e556d85d2..9351a0a88 100644 --- a/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts +++ b/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts @@ -84,13 +84,13 @@ export function buildCryptographicMaterialsCacheKeyHelpers ): Promise encryptedDataKeysHash(encryptedDataKeys: ReadonlyArray): Promise - encryptionContextHash(context?: EncryptionContext): Promise + encryptionContextHash(context: EncryptionContext): Promise } diff --git a/modules/cache-material/src/clone_cryptographic_material.ts b/modules/cache-material/src/clone_cryptographic_material.ts index 4d0f9b4a9..a62d84636 100644 --- a/modules/cache-material/src/clone_cryptographic_material.ts +++ b/modules/cache-material/src/clone_cryptographic_material.ts @@ -19,24 +19,23 @@ import { WebCryptoEncryptionMaterial, WebCryptoDecryptionMaterial, isEncryptionMaterial, - isDecryptionMaterial + isDecryptionMaterial, + NodeAlgorithmSuite } from '@aws-crypto/material-management' type Material = NodeEncryptionMaterial|NodeDecryptionMaterial|WebCryptoEncryptionMaterial|WebCryptoDecryptionMaterial export function cloneMaterial (source: M): M { - const clone = source instanceof NodeEncryptionMaterial - ? new NodeEncryptionMaterial(source.suite) - : source instanceof NodeDecryptionMaterial - ? new NodeDecryptionMaterial(source.suite) - : source instanceof WebCryptoEncryptionMaterial - ? new WebCryptoEncryptionMaterial(source.suite) - : source instanceof WebCryptoDecryptionMaterial - ? new WebCryptoDecryptionMaterial(source.suite) - : false + const { suite, encryptionContext } = source - if (!clone) throw new Error('Unsupported material type') + const clone = suite instanceof NodeAlgorithmSuite + ? source instanceof NodeEncryptionMaterial + ? new NodeEncryptionMaterial(suite, encryptionContext) + : new NodeDecryptionMaterial(suite, encryptionContext) + : source instanceof WebCryptoEncryptionMaterial + ? new WebCryptoEncryptionMaterial(suite, encryptionContext) + : new WebCryptoDecryptionMaterial(suite, encryptionContext) const udk = new Uint8Array(source.getUnencryptedDataKey()) clone.setUnencryptedDataKey(udk, source.keyringTrace[0]) @@ -61,6 +60,8 @@ export function cloneMaterial (source: M): M { if (source.suite.signatureCurve && source.verificationKey) { clone.setVerificationKey(source.verificationKey) } + } else { + throw new Error('Material mismatch') } return clone diff --git a/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts b/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts index 66ae7e293..80170c064 100644 --- a/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts +++ b/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts @@ -207,12 +207,12 @@ describe('Cryptographic Material Functions', () => { const edk1 = new EncryptedDataKey({ providerId: 'keyNamespace', providerInfo: 'keyName', encryptedDataKey: new Uint8Array([1]) }) const edk2 = new EncryptedDataKey({ providerId: 'p2', providerInfo: 'pi2', encryptedDataKey: new Uint8Array([2]) }) - const encryptionMaterial = new NodeEncryptionMaterial(nodeSuite) + const encryptionMaterial = new NodeEncryptionMaterial(nodeSuite, {}) .setUnencryptedDataKey(udk128, trace) .addEncryptedDataKey(edk1, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) .addEncryptedDataKey(edk2, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) - const decryptionMaterial = new NodeDecryptionMaterial(nodeSuite) + const decryptionMaterial = new NodeDecryptionMaterial(nodeSuite, {}) .setUnencryptedDataKey(udk128, trace) const context = {} diff --git a/modules/cache-material/test/clone_cryptographic_material.test.ts b/modules/cache-material/test/clone_cryptographic_material.test.ts index c87e3bece..91f94862c 100644 --- a/modules/cache-material/test/clone_cryptographic_material.test.ts +++ b/modules/cache-material/test/clone_cryptographic_material.test.ts @@ -46,7 +46,7 @@ const cryptoKey: any = { type: 'secret', algorithm: { name: webCryptoSuite.encry describe('cloneMaterial', () => { it('clone NodeEncryptionMaterial', () => { - const material = new NodeEncryptionMaterial(nodeSuite) + const material = new NodeEncryptionMaterial(nodeSuite, { some: 'context' }) .setUnencryptedDataKey(udk128, trace) .addEncryptedDataKey(edk1, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) .addEncryptedDataKey(edk2, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) @@ -56,20 +56,22 @@ describe('cloneMaterial', () => { expect(test.getUnencryptedDataKey()).to.deep.equal(udk128) expect(test.keyringTrace).to.deep.equal(material.keyringTrace) expect(test.encryptedDataKeys).to.deep.equal(material.encryptedDataKeys) + expect(test.encryptionContext).to.deep.equal(material.encryptionContext) }) it('clone NodeDecryptionMaterial', () => { - const material = new NodeDecryptionMaterial(nodeSuite) + const material = new NodeDecryptionMaterial(nodeSuite, { some: 'context' }) .setUnencryptedDataKey(udk128, trace) const test = cloneMaterial(material) expect(test).to.be.instanceOf(NodeDecryptionMaterial) expect(test.getUnencryptedDataKey()).to.deep.equal(udk128) expect(test.keyringTrace).to.deep.equal(material.keyringTrace) + expect(test.encryptionContext).to.deep.equal(material.encryptionContext) }) it('clone WebCryptoEncryptionMaterial', () => { - const material = new WebCryptoEncryptionMaterial(webCryptoSuite) + const material = new WebCryptoEncryptionMaterial(webCryptoSuite, { some: 'context' }) .setUnencryptedDataKey(udk128, trace) .setCryptoKey(cryptoKey, trace) .addEncryptedDataKey(edk1, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) @@ -81,10 +83,11 @@ describe('cloneMaterial', () => { expect(test.getCryptoKey()).to.deep.equal(cryptoKey) expect(test.keyringTrace).to.deep.equal(material.keyringTrace) expect(test.encryptedDataKeys).to.deep.equal(material.encryptedDataKeys) + expect(test.encryptionContext).to.deep.equal(material.encryptionContext) }) it('clone WebCryptoDecryptionMaterial', () => { - const material = new WebCryptoDecryptionMaterial(webCryptoSuite) + const material = new WebCryptoDecryptionMaterial(webCryptoSuite, { some: 'context' }) .setUnencryptedDataKey(udk128, trace) .setCryptoKey(cryptoKey, trace) @@ -93,5 +96,6 @@ describe('cloneMaterial', () => { expect(test.getUnencryptedDataKey()).to.deep.equal(udk128) expect(test.getCryptoKey()).to.deep.equal(cryptoKey) expect(test.keyringTrace).to.deep.equal(material.keyringTrace) + expect(test.encryptionContext).to.deep.equal(material.encryptionContext) }) }) diff --git a/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts b/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts index 7c69c75c2..8a1a5a3a4 100644 --- a/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts +++ b/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts @@ -26,8 +26,8 @@ import { } from '@aws-crypto/material-management' const nodeSuite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) -const encryptionMaterial = new NodeEncryptionMaterial(nodeSuite) -const decryptionMaterial = new NodeDecryptionMaterial(nodeSuite) +const encryptionMaterial = new NodeEncryptionMaterial(nodeSuite, {}) +const decryptionMaterial = new NodeDecryptionMaterial(nodeSuite, {}) describe('getLocalCryptographicMaterialsCache', () => { const { @@ -41,8 +41,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('putEncryptionResponse', () => { const key = 'some encryption key' const response: any = { - material: encryptionMaterial, - context: {} + material: encryptionMaterial } putEncryptionResponse(key, response, 1) @@ -56,8 +55,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Precondition: putEncryptionResponse plaintextLength can not be negative.', () => { const response: any = { - material: encryptionMaterial, - context: {} + material: encryptionMaterial } const u: any = undefined const s: any = 'not-number' @@ -70,8 +68,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Postcondition: Only return EncryptionMaterial.', () => { const key = 'some decryption key' const response: any = { - material: decryptionMaterial, - context: {} + material: decryptionMaterial } putDecryptionResponse(key, response) @@ -82,8 +79,7 @@ describe('getLocalCryptographicMaterialsCache', () => { const key = 'some encryption key' const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const response: any = { - material: new NodeEncryptionMaterial(suite), - context: {} + material: new NodeEncryptionMaterial(suite, {}) } expect(() => putEncryptionResponse(key, response, 1)).to.throw() @@ -92,8 +88,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('putDecryptionResponse', () => { const key = 'some decryption key' const response: any = { - material: decryptionMaterial, - context: {} + material: decryptionMaterial } putDecryptionResponse(key, response) @@ -108,8 +103,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Precondition: Only cache DecryptionMaterial.', () => { const key = 'some decryption key' const response: any = { - material: 'not material', - context: {} + material: 'not material' } expect(() => putDecryptionResponse(key, response)).to.throw() @@ -119,8 +113,7 @@ describe('getLocalCryptographicMaterialsCache', () => { const key = 'some decryption key' const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const response: any = { - material: new NodeEncryptionMaterial(suite), - context: {} + material: new NodeEncryptionMaterial(suite, {}) } expect(() => putDecryptionResponse(key, response)).to.throw() @@ -143,8 +136,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Precondition: Only cache EncryptionMaterial.', () => { const key = 'some encryption key' const response: any = { - material: 'not material', - context: {} + material: 'not material' } expect(() => putEncryptionResponse(key, response, 1)).to.throw() @@ -158,8 +150,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Postcondition: Only return DecryptionMaterial.', () => { const key = 'some encryption key' const response: any = { - material: encryptionMaterial, - context: {} + material: encryptionMaterial } putEncryptionResponse(key, response, 1) @@ -173,8 +164,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('zero is an acceptable plaintextLength', () => { const key = 'some encryption key' const response: any = { - material: encryptionMaterial, - context: {} + material: encryptionMaterial } putEncryptionResponse(key, response, 0) @@ -197,8 +187,7 @@ describe('cache eviction', () => { const key1 = 'key lost' const key2 = 'key replace' const response: any = { - material: decryptionMaterial, - context: {} + material: decryptionMaterial } putDecryptionResponse(key1, response) @@ -218,8 +207,7 @@ describe('cache eviction', () => { const key = 'key deleted' const response: any = { - material: decryptionMaterial, - context: {} + material: decryptionMaterial } putDecryptionResponse(key, response) @@ -236,8 +224,7 @@ describe('cache eviction', () => { const key = 'key lost' const response: any = { - material: decryptionMaterial, - context: {} + material: decryptionMaterial } putDecryptionResponse(key, response, 1) @@ -255,8 +242,7 @@ describe('cache eviction', () => { const key1 = 'key lost' const key2 = 'key replace' const response: any = { - material: encryptionMaterial, - context: {} + material: encryptionMaterial } putEncryptionResponse(key1, response, 0) @@ -276,8 +262,7 @@ describe('cache eviction', () => { const key = 'key lost' const response: any = { - material: encryptionMaterial, - context: {} + material: encryptionMaterial } putEncryptionResponse(key, response, 1, 1) @@ -294,8 +279,7 @@ describe('cache eviction', () => { const key = 'key lost' const response: any = { - material: encryptionMaterial, - context: {} + material: encryptionMaterial } putEncryptionResponse(key, response, 1, 1) diff --git a/modules/encrypt-browser/src/encrypt.ts b/modules/encrypt-browser/src/encrypt.ts index 33ef913e7..9b48d1001 100644 --- a/modules/encrypt-browser/src/encrypt.ts +++ b/modules/encrypt-browser/src/encrypt.ts @@ -58,7 +58,7 @@ export interface EncryptResult { export async function encrypt ( cmm: KeyringWebCrypto|WebCryptoMaterialsManager, plaintext: Uint8Array, - { suiteId, encryptionContext, frameLength = FRAME_LENGTH }: EncryptInput = {} + { suiteId, encryptionContext = {}, frameLength = FRAME_LENGTH }: EncryptInput = {} ): Promise { const backend = await getWebCryptoBackend() if (!backend) throw new Error('No supported crypto backend') @@ -79,7 +79,7 @@ export async function encrypt ( plaintextLength } - const { material, context } = await cmm.getEncryptionMaterials(encryptionRequest) + const { material } = await cmm.getEncryptionMaterials(encryptionRequest) const { kdfGetSubtleEncrypt, subtleSign, dispose } = await getEncryptHelper(material) const messageId = await backend.randomValues(MESSAGE_ID_LENGTH) @@ -91,7 +91,7 @@ export async function encrypt ( type: ObjectType.CUSTOMER_AE_DATA, suiteId: id, messageId, - encryptionContext: context, + encryptionContext: material.encryptionContext, encryptedDataKeys: material.encryptedDataKeys, contentType: ContentType.FRAMED_DATA, headerIvLength: ivLength, diff --git a/modules/encrypt-node/src/encrypt_stream.ts b/modules/encrypt-node/src/encrypt_stream.ts index 0d126d896..28e161e9f 100644 --- a/modules/encrypt-node/src/encrypt_stream.ts +++ b/modules/encrypt-node/src/encrypt_stream.ts @@ -38,7 +38,7 @@ const { serializeMessageHeader, headerAuthIv } = serializeFactory(fromUtf8) export interface EncryptStreamInput { suiteId?: AlgorithmSuiteIdentifier - context?: EncryptionContext + encryptionContext?: EncryptionContext frameLength?: number plaintextLength?: number } @@ -54,7 +54,7 @@ export function encryptStream ( cmm: KeyringNode|NodeMaterialsManager, op: EncryptStreamInput = {} ): Duplex { - const { suiteId, context, frameLength = FRAME_LENGTH } = op + const { suiteId, encryptionContext = {}, frameLength = FRAME_LENGTH } = op /* If the cmm is a Keyring, wrap it with NodeDefaultCryptographicMaterialsManager. */ cmm = cmm instanceof KeyringNode @@ -65,11 +65,11 @@ export function encryptStream ( const wrappingStream = new Duplexify() - cmm.getEncryptionMaterials({ suite, encryptionContext: context, frameLength }) - .then(async ({ material, context }) => { + cmm.getEncryptionMaterials({ suite, encryptionContext, frameLength }) + .then(async ({ material }) => { const { dispose, getSigner } = getEncryptHelper(material) - const { getCipher, messageHeader, rawHeader } = getEncryptionInfo(material, frameLength, context) + const { getCipher, messageHeader, rawHeader } = getEncryptionInfo(material, frameLength) wrappingStream.emit('MessageHeader', messageHeader) @@ -90,8 +90,9 @@ export function encryptStream ( return wrappingStream } -export function getEncryptionInfo (material : NodeEncryptionMaterial, frameLength: number, context: EncryptionContext) { +export function getEncryptionInfo (material : NodeEncryptionMaterial, frameLength: number) { const { kdfGetCipher } = getEncryptHelper(material) + const { encryptionContext } = material const messageId = randomBytes(MESSAGE_ID_LENGTH) const { id, ivLength } = material.suite @@ -100,7 +101,7 @@ export function getEncryptionInfo (material : NodeEncryptionMaterial, frameLengt type: ObjectType.CUSTOMER_AE_DATA, suiteId: id, messageId, - encryptionContext: context, + encryptionContext, encryptedDataKeys: Object.freeze(material.encryptedDataKeys), // freeze me please contentType: ContentType.FRAMED_DATA, headerIvLength: ivLength, diff --git a/modules/encrypt-node/test/encrypt.test.ts b/modules/encrypt-node/test/encrypt.test.ts index f7d3c9318..f1f536347 100644 --- a/modules/encrypt-node/test/encrypt.test.ts +++ b/modules/encrypt-node/test/encrypt.test.ts @@ -90,10 +90,10 @@ describe('encrypt structural testing', () => { }) it('encrypt a buffer', async () => { - const context = { simple: 'context' } + const encryptionContext = { simple: 'context' } const plaintext = Buffer.from('asdf') - const { ciphertext, messageHeader } = await encrypt(keyRing, plaintext, { context }) + const { ciphertext, messageHeader } = await encrypt(keyRing, plaintext, { encryptionContext }) /* The default algorithm suite will add a signature key to the context. * So I only check that the passed context elements exist. @@ -109,7 +109,7 @@ describe('encrypt structural testing', () => { }) it('encrypt a stream', async () => { - const context = { simple: 'context' } + const encryptionContext = { simple: 'context' } let pushed = false const plaintext = from((_: number, next: Function) => { @@ -118,7 +118,7 @@ describe('encrypt structural testing', () => { next(null, 'asdf') }) - const { ciphertext, messageHeader } = await encrypt(keyRing, plaintext, { context }) + const { ciphertext, messageHeader } = await encrypt(keyRing, plaintext, { encryptionContext }) /* The default algorithm suite will add a signature key to the context. * So I only check that the passed context elements exist. @@ -139,7 +139,7 @@ describe('encrypt structural testing', () => { }) it('encryptStream', async () => { - const context = { simple: 'context' } + const encryptionContext = { simple: 'context' } const data = randomBytes(300) const i = data.values() @@ -155,7 +155,7 @@ describe('encrypt structural testing', () => { let messageHeader: any const buffer: Buffer[] = [] const stream = plaintext - .pipe(encryptStream(keyRing, { context, frameLength: 5 })) + .pipe(encryptStream(keyRing, { encryptionContext, frameLength: 5 })) .on('MessageHeader', (header: MessageHeader) => { // MessageHeader should only be called once if (messageHeader) throw new Error('I should never see this error') diff --git a/modules/example-node/src/aes_simple.ts b/modules/example-node/src/aes_simple.ts index 4f3aecb14..5d4efc5d4 100644 --- a/modules/example-node/src/aes_simple.ts +++ b/modules/example-node/src/aes_simple.ts @@ -57,7 +57,7 @@ export async function aesTest () { const cleartext = 'asdf' /* Encrypt the data. */ - const { ciphertext } = await encrypt(keyring, cleartext, { context }) + const { ciphertext } = await encrypt(keyring, cleartext, { encryptionContext: context }) /* Decrypt the data. */ const { plaintext, messageHeader } = await decrypt(keyring, ciphertext) diff --git a/modules/example-node/src/kms_simple.ts b/modules/example-node/src/kms_simple.ts index 2c2e79ca8..f2e249a34 100644 --- a/modules/example-node/src/kms_simple.ts +++ b/modules/example-node/src/kms_simple.ts @@ -52,7 +52,7 @@ export async function kmsSimpleTest () { const cleartext = 'asdf' /* Encrypt the data. */ - const { ciphertext } = await encrypt(keyring, cleartext, { context }) + const { ciphertext } = await encrypt(keyring, cleartext, { encryptionContext: context }) /* Decrypt the data. */ const { plaintext, messageHeader } = await decrypt(keyring, ciphertext) diff --git a/modules/example-node/src/kms_stream.ts b/modules/example-node/src/kms_stream.ts index 455c11586..a8f4d596f 100644 --- a/modules/example-node/src/kms_stream.ts +++ b/modules/example-node/src/kms_stream.ts @@ -66,7 +66,7 @@ export async function kmsStreamTest (filename: string) { /* Create a simple pipeline to encrypt the package.json for this project. */ const stream = createReadStream(filename) - .pipe(encryptStream(keyring, { context })) + .pipe(encryptStream(keyring, { encryptionContext: context })) .pipe(decryptStream(new KmsKeyringNode({ discovery: true }))) .on('MessageHeader', ({ encryptionContext }: MessageHeader) => { /* Verify the encryption context. diff --git a/modules/example-node/src/multi_keyring.ts b/modules/example-node/src/multi_keyring.ts index 5c86854b0..8fa98f71f 100644 --- a/modules/example-node/src/multi_keyring.ts +++ b/modules/example-node/src/multi_keyring.ts @@ -76,7 +76,7 @@ export async function multiKeyringTest () { const cleartext = 'asdf' /* Encrypt the data. */ - const { ciphertext } = await encrypt(keyring, cleartext, { context }) + const { ciphertext } = await encrypt(keyring, cleartext, { encryptionContext: context }) /* Decrypt the data. * This decrypt call could be done with **any** of the 3 keyrings. diff --git a/modules/example-node/src/rsa_simple.ts b/modules/example-node/src/rsa_simple.ts index 4f8904272..cfdc247ae 100644 --- a/modules/example-node/src/rsa_simple.ts +++ b/modules/example-node/src/rsa_simple.ts @@ -59,7 +59,7 @@ export async function rsaTest () { const cleartext = 'asdf' /* Encrypt the data. */ - const { ciphertext } = await encrypt(keyring, cleartext, { context }) + const { ciphertext } = await encrypt(keyring, cleartext, { encryptionContext: context }) /* Decrypt the data. */ const { plaintext, messageHeader } = await decrypt(keyring, ciphertext) diff --git a/modules/kms-keyring-browser/src/kms_keyring_browser.ts b/modules/kms-keyring-browser/src/kms_keyring_browser.ts index 24cd9554b..a80f6d3e9 100644 --- a/modules/kms-keyring-browser/src/kms_keyring_browser.ts +++ b/modules/kms-keyring-browser/src/kms_keyring_browser.ts @@ -28,7 +28,6 @@ import { WebCryptoAlgorithmSuite, // eslint-disable-line no-unused-vars WebCryptoEncryptionMaterial, // eslint-disable-line no-unused-vars WebCryptoDecryptionMaterial, // eslint-disable-line no-unused-vars - EncryptionContext, // eslint-disable-line no-unused-vars EncryptedDataKey, // eslint-disable-line no-unused-vars immutableClass, importForWebCryptoEncryptionMaterial, @@ -55,14 +54,14 @@ export class KmsKeyringBrowser extends KmsKeyringClass(KeyringWebCrypto as KeyRi super({ clientProvider, keyIds, generatorKeyId, grantTokens, discovery }) } - async _onEncrypt (material: WebCryptoEncryptionMaterial, context?: EncryptionContext) { - const _material = await super._onEncrypt(material, context) + async _onEncrypt (material: WebCryptoEncryptionMaterial) { + const _material = await super._onEncrypt(material) return importForWebCryptoEncryptionMaterial(_material) } - async _onDecrypt (material: WebCryptoDecryptionMaterial, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext) { - const _material = await super._onDecrypt(material, encryptedDataKeys, context) + async _onDecrypt (material: WebCryptoDecryptionMaterial, encryptedDataKeys: EncryptedDataKey[]) { + const _material = await super._onDecrypt(material, encryptedDataKeys) return importForWebCryptoDecryptionMaterial(_material) } diff --git a/modules/kms-keyring-browser/test/kms_keyring_browser.test.ts b/modules/kms-keyring-browser/test/kms_keyring_browser.test.ts index e49344a5a..7aca80e04 100644 --- a/modules/kms-keyring-browser/test/kms_keyring_browser.test.ts +++ b/modules/kms-keyring-browser/test/kms_keyring_browser.test.ts @@ -70,7 +70,7 @@ describe('RawAesKeyringWebCrypto encrypt/decrypt', () => { it('can encrypt and create unencrypted data key', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const test = await keyring.onEncrypt(material) expect(test.hasValidKey()).to.equal(true) const udk = test.getUnencryptedDataKey() @@ -82,7 +82,7 @@ describe('RawAesKeyringWebCrypto encrypt/decrypt', () => { it('can decrypt an EncryptedDataKey', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) const test = await keyring.onDecrypt(material, [encryptedDataKey]) expect(test.hasValidKey()).to.equal(true) // The UnencryptedDataKey should be zeroed, because the cryptoKey has been set diff --git a/modules/kms-keyring-node/test/kms_keyring_node.test.ts b/modules/kms-keyring-node/test/kms_keyring_node.test.ts index 310024c61..7fd943b4f 100644 --- a/modules/kms-keyring-node/test/kms_keyring_node.test.ts +++ b/modules/kms-keyring-node/test/kms_keyring_node.test.ts @@ -58,7 +58,7 @@ describe('RawAesKeyringWebCrypto encrypt/decrypt', () => { it('can encrypt and create unencrypted data key', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const test = await keyring.onEncrypt(material) expect(test.hasValidKey()).to.equal(true) udk = test.getUnencryptedDataKey() @@ -70,7 +70,7 @@ describe('RawAesKeyringWebCrypto encrypt/decrypt', () => { it('can decrypt an EncryptedDataKey', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const test = await keyring.onDecrypt(material, [encryptedDataKey]) expect(test.hasValidKey()).to.equal(true) expect(test.getUnencryptedDataKey()).to.deep.equal(udk) diff --git a/modules/kms-keyring/src/helpers.ts b/modules/kms-keyring/src/helpers.ts index 69c48e384..2b0274497 100644 --- a/modules/kms-keyring/src/helpers.ts +++ b/modules/kms-keyring/src/helpers.ts @@ -39,7 +39,7 @@ export async function generateDataKey ( clientProvider: KmsClientSupplier, NumberOfBytes: number, KeyId: string, - EncryptionContext?: EncryptionContext, + EncryptionContext: EncryptionContext, GrantTokens?: string[] ): Promise { const region = regionFromKmsKeyArn(KeyId) @@ -60,7 +60,7 @@ export async function encrypt ( clientProvider: KmsClientSupplier, Plaintext: Uint8Array, KeyId: string, - EncryptionContext?: EncryptionContext, + EncryptionContext: EncryptionContext, GrantTokens?: string[] ): Promise { const region = regionFromKmsKeyArn(KeyId) @@ -81,7 +81,7 @@ export async function encrypt ( export async function decrypt ( clientProvider: KmsClientSupplier, { providerId, providerInfo, encryptedDataKey }: EncryptedDataKey, - EncryptionContext?: EncryptionContext, + EncryptionContext: EncryptionContext, GrantTokens?: string[] ): Promise { /* Precondition: The EDK must be a KMS edk. */ diff --git a/modules/kms-keyring/src/kms_keyring.ts b/modules/kms-keyring/src/kms_keyring.ts index 4795805ae..095a64813 100644 --- a/modules/kms-keyring/src/kms_keyring.ts +++ b/modules/kms-keyring/src/kms_keyring.ts @@ -24,7 +24,6 @@ import { EncryptionMaterial, // eslint-disable-line no-unused-vars DecryptionMaterial, // eslint-disable-line no-unused-vars SupportedAlgorithmSuites, // eslint-disable-line no-unused-vars - EncryptionContext, // eslint-disable-line no-unused-vars KeyringTrace, // eslint-disable-line no-unused-vars KeyringTraceFlag, EncryptedDataKey, // eslint-disable-line no-unused-vars @@ -48,8 +47,8 @@ export interface KeyRing clientProvider: KmsClientSupplier grantTokens?: string[] isDiscovery: boolean - _onEncrypt(material: EncryptionMaterial, context?: EncryptionContext): Promise> - _onDecrypt(material: DecryptionMaterial, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext): Promise> + _onEncrypt(material: EncryptionMaterial): Promise> + _onDecrypt(material: DecryptionMaterial, encryptedDataKeys: EncryptedDataKey[]): Promise> } export interface KmsKeyRingConstructible { @@ -92,14 +91,20 @@ export function KmsKeyringClass, context?: EncryptionContext) { + async _onEncrypt (material: EncryptionMaterial) { /* Check for early return (Postcondition): Discovery Keyrings do not encrypt. */ if (this.isDiscovery) return material const keyIds = this.keyIds.slice() const { clientProvider, generatorKeyId, grantTokens } = this if (generatorKeyId && !material.hasUnencryptedDataKey) { - const dataKey = await generateDataKey(clientProvider, material.suite.keyLengthBytes, generatorKeyId, context, grantTokens) + const dataKey = await generateDataKey( + clientProvider, + material.suite.keyLengthBytes, + generatorKeyId, + material.encryptionContext, + grantTokens + ) /* Precondition: A generatorKeyId must generate if we do not have an unencrypted data key. * Client supplier is allowed to return undefined if, for example, user wants to exclude particular * regions. But if we are here it means that user configured keyring with a KMS key that was @@ -130,7 +135,13 @@ export function KmsKeyringClass, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext) { + async _onDecrypt (material: DecryptionMaterial, encryptedDataKeys: EncryptedDataKey[]) { const keyIds = this.keyIds.slice() const { clientProvider, generatorKeyId, grantTokens } = this if (generatorKeyId) keyIds.unshift(generatorKeyId) @@ -162,7 +173,12 @@ export function KmsKeyringClass { return { decrypt } function decrypt ({ CiphertextBlob, EncryptionContext, GrantTokens }: any) { - expect(EncryptionContext === context).to.equal(true) + expect(EncryptionContext).to.deep.equal(context) expect(GrantTokens).to.equal(grantTokens) return { Plaintext: new Uint8Array(suite.keyLengthBytes), @@ -70,9 +70,8 @@ describe('KmsKeyring: _onDecrypt', }) const material = await testKeyring.onDecrypt( - new NodeDecryptionMaterial(suite), - [edk], - context + new NodeDecryptionMaterial(suite, context), + [edk] ) expect(material.hasUnencryptedDataKey).to.equal(true) @@ -95,7 +94,7 @@ describe('KmsKeyring: _onDecrypt', const clientProvider: any = () => { return { decrypt } function decrypt ({ CiphertextBlob, EncryptionContext, GrantTokens }: any) { - expect(EncryptionContext === context).to.equal(true) + expect(EncryptionContext).to.deep.equal(context) expect(GrantTokens).to.equal(grantTokens) return { Plaintext: new Uint8Array(suite.keyLengthBytes), @@ -118,9 +117,8 @@ describe('KmsKeyring: _onDecrypt', }) const material = await testKeyring.onDecrypt( - new NodeDecryptionMaterial(suite), - [edk], - context + new NodeDecryptionMaterial(suite, context), + [edk] ) expect(material.hasUnencryptedDataKey).to.equal(true) @@ -161,9 +159,8 @@ describe('KmsKeyring: _onDecrypt', }) const material = await testKeyring.onDecrypt( - new NodeDecryptionMaterial(suite), - [edk], - context + new NodeDecryptionMaterial(suite, context), + [edk] ) expect(material.hasUnencryptedDataKey).to.equal(false) diff --git a/modules/kms-keyring/test/kms_keyring.onencrypt.test.ts b/modules/kms-keyring/test/kms_keyring.onencrypt.test.ts index 752d1c722..202fbf460 100644 --- a/modules/kms-keyring/test/kms_keyring.onencrypt.test.ts +++ b/modules/kms-keyring/test/kms_keyring.onencrypt.test.ts @@ -44,7 +44,7 @@ describe('KmsKeyring: _onEncrypt', () => { const clientProvider: any = () => { return { generateDataKey, encrypt } function generateDataKey ({ KeyId, EncryptionContext, GrantTokens }: any) { - expect(EncryptionContext === context).to.equal(true) + expect(EncryptionContext).to.deep.equal(context) expect(GrantTokens).to.equal(grantTokens) return { Plaintext: new Uint8Array(suite.keyLengthBytes), @@ -53,7 +53,7 @@ describe('KmsKeyring: _onEncrypt', () => { } } function encrypt ({ KeyId, EncryptionContext, GrantTokens }: any) { - expect(EncryptionContext === context).to.equal(true) + expect(EncryptionContext).to.deep.equal(context) expect(GrantTokens).to.equal(grantTokens) return { KeyId, @@ -70,7 +70,7 @@ describe('KmsKeyring: _onEncrypt', () => { grantTokens }) - const material = await testKeyring.onEncrypt(new NodeEncryptionMaterial(suite), context) + const material = await testKeyring.onEncrypt(new NodeEncryptionMaterial(suite, context)) expect(material.hasUnencryptedDataKey).to.equal(true) @@ -114,7 +114,7 @@ describe('KmsKeyring: _onEncrypt', () => { grantTokens }) - await expect(testKeyring.onEncrypt(new NodeEncryptionMaterial(suite), context)) + await expect(testKeyring.onEncrypt(new NodeEncryptionMaterial(suite, context))) .to.rejectedWith(Error) }) @@ -136,7 +136,7 @@ describe('KmsKeyring: _onEncrypt', () => { grantTokens }) - await expect(testKeyring.onEncrypt(new NodeEncryptionMaterial(suite), context)) + await expect(testKeyring.onEncrypt(new NodeEncryptionMaterial(suite, context))) .to.rejectedWith(Error) }) @@ -160,7 +160,7 @@ describe('KmsKeyring: _onEncrypt', () => { generatorKeyId }) - const seedMaterial = new NodeEncryptionMaterial(suite) + const seedMaterial = new NodeEncryptionMaterial(suite, {}) .setUnencryptedDataKey(new Uint8Array(suite.keyLengthBytes), { keyName: 'keyName', keyNamespace: 'keyNamespace', @@ -197,7 +197,7 @@ describe('KmsKeyring: _onEncrypt', () => { generatorKeyId }) - const seedMaterial = new NodeEncryptionMaterial(suite) + const seedMaterial = new NodeEncryptionMaterial(suite, {}) .setUnencryptedDataKey(new Uint8Array(suite.keyLengthBytes), { keyName: 'keyName', keyNamespace: 'keyNamespace', diff --git a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts index 9e442e3a8..9eae4a07e 100644 --- a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts +++ b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts @@ -48,11 +48,10 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM } async getEncryptionMaterials ({ suite, encryptionContext }: WebCryptoEncryptionRequest): Promise { suite = suite || new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) - const material = new WebCryptoEncryptionMaterial(suite) - const context = await this._generateSigningKeyAndUpdateEncryptionContext(material, encryptionContext) - - await this.keyring.onEncrypt(material, context) + const material = await this + .keyring + .onEncrypt(await this._initializeEncryptionMaterial(suite, encryptionContext)) /* Postcondition: The WebCryptoEncryptionMaterial must contain a valid dataKey. */ needs(material.hasValidKey(), 'Unencrypted data key is invalid.') @@ -60,25 +59,25 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM /* Postcondition: The WebCryptoEncryptionMaterial must contain at least 1 EncryptedDataKey. */ needs(material.encryptedDataKeys.length, 'No EncryptedDataKeys: the ciphertext can never be decrypted.') - return { material, context } + return { material } } async decryptMaterials ({ suite, encryptedDataKeys, encryptionContext }: WebCryptoDecryptionRequest): Promise { - const material = await this._loadVerificationKeyFromEncryptionContext(new WebCryptoDecryptionMaterial(suite), encryptionContext) - - await this.keyring.onDecrypt(material, encryptedDataKeys.slice(), encryptionContext) + const material = await this + .keyring + .onDecrypt(await this._initializeDecryptionMaterial(suite, encryptionContext), encryptedDataKeys.slice()) /* Postcondition: The WebCryptoDecryptionMaterial must contain a valid dataKey. */ needs(material.hasValidKey(), 'Unencrypted data key is invalid.') - return { material, context: encryptionContext || {} } + return { material } } - async _generateSigningKeyAndUpdateEncryptionContext (material: WebCryptoEncryptionMaterial, context?: EncryptionContext) { - const { signatureCurve: namedCurve } = material.suite + async _initializeEncryptionMaterial (suite: WebCryptoAlgorithmSuite, encryptionContext: EncryptionContext) { + const { signatureCurve: namedCurve } = suite - /* Precondition: The algorithm suite specification must support a signatureCurve to generate a signing key. */ - if (!namedCurve) return { ...context } + /* Check for early return (Postcondition): The WebCryptoAlgorithmSuite specification must support a signatureCurve to generate a signing key. */ + if (!namedCurve) return new WebCryptoEncryptionMaterial(suite, encryptionContext) const backend = await getWebCryptoBackend() const subtle = getNonZeroByteBackend(backend) @@ -90,22 +89,25 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM const { publicKey, privateKey } = await subtle.generateKey(webCryptoAlgorithm, extractable, usages) const publicKeyBytes = await subtle.exportKey(format, publicKey) - const compressPoint = SignatureKey.encodeCompressPoint(new Uint8Array(publicKeyBytes), material.suite) - const signatureKey = new SignatureKey(privateKey, compressPoint, material.suite) - material.setSignatureKey(signatureKey) - return { ...context, [ENCODED_SIGNER_KEY]: toBase64(compressPoint) } + const compressPoint = SignatureKey.encodeCompressPoint(new Uint8Array(publicKeyBytes), suite) + const signatureKey = new SignatureKey(privateKey, compressPoint, suite) + return new WebCryptoEncryptionMaterial( + suite, + { ...encryptionContext, [ENCODED_SIGNER_KEY]: toBase64(compressPoint) } + ) + .setSignatureKey(signatureKey) } - async _loadVerificationKeyFromEncryptionContext (material: WebCryptoDecryptionMaterial, context?: EncryptionContext) { - const { signatureCurve: namedCurve } = material.suite + async _initializeDecryptionMaterial (suite: WebCryptoAlgorithmSuite, encryptionContext: EncryptionContext) { + const { signatureCurve: namedCurve } = suite - /* Precondition: The algorithm suite specification must support a signatureCurve to extract a verification key. */ - if (!namedCurve) return material + /* Check for early return (Postcondition): The WebCryptoAlgorithmSuite specification must support a signatureCurve to extract a verification key. */ + if (!namedCurve) return new WebCryptoDecryptionMaterial(suite, encryptionContext) /* Precondition: WebCryptoDefaultCryptographicMaterialsManager If the algorithm suite specification requires a signatureCurve a context must exist. */ - if (!context) throw new Error('Context does not contain required public key.') + if (!encryptionContext) throw new Error('Context does not contain required public key.') - const { [ENCODED_SIGNER_KEY]: compressPoint } = context + const { [ENCODED_SIGNER_KEY]: compressPoint } = encryptionContext /* Precondition: WebCryptoDefaultCryptographicMaterialsManager The context must contain the public key. */ needs(compressPoint, 'Context does not contain required public key.') @@ -117,10 +119,11 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM const usages = ['verify'] const format = 'raw' - const publicKeyBytes = VerificationKey.decodeCompressPoint(fromBase64(compressPoint), material.suite) + const publicKeyBytes = VerificationKey.decodeCompressPoint(fromBase64(compressPoint), suite) const publicKey = await subtle.importKey(format, publicKeyBytes, webCryptoAlgorithm, extractable, usages) - return material.setVerificationKey(new VerificationKey(publicKey, material.suite)) + return new WebCryptoDecryptionMaterial(suite, encryptionContext) + .setVerificationKey(new VerificationKey(publicKey, suite)) } } diff --git a/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts b/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts index 8a1b2fe5f..d5527a936 100644 --- a/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts +++ b/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts @@ -70,21 +70,21 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { } const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const material = new WebCryptoEncryptionMaterial(suite) const keyring = new TestKeyring() const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring) - const test = await cmm._generateSigningKeyAndUpdateEncryptionContext(material, { some: 'context' }) - expect(Object.keys(test)).lengthOf(2) + const test = await cmm._initializeEncryptionMaterial(suite, { some: 'context' }) - const { signatureKey } = material + expect(test).to.be.instanceOf(WebCryptoEncryptionMaterial) + const { signatureKey, encryptionContext } = test if (!signatureKey) throw new Error('I should never see this error') - expect(test).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(signatureKey.compressPoint)) - expect(test).to.have.haveOwnProperty('some').and.to.equal('context') + expect(Object.keys(encryptionContext)).lengthOf(2) + expect(encryptionContext).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(signatureKey.compressPoint)) + expect(encryptionContext).to.have.haveOwnProperty('some').and.to.equal('context') }) - it('Precondition: The algorithm suite specification must support a signatureCurve to generate a signing key.', async () => { + it('Check for early return (Postcondition): The WebCryptoAlgorithmSuite specification must support a signatureCurve to generate a signing key.', async () => { class TestKeyring extends KeyringWebCrypto { async _onEncrypt (): Promise { throw new Error('I should never see this error') @@ -95,13 +95,12 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { } const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) const keyring = new TestKeyring() const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring) - const test = await cmm._generateSigningKeyAndUpdateEncryptionContext(material, { some: 'context' }) - expect(Object.keys(test)).lengthOf(1) - expect(test).to.have.haveOwnProperty('some').and.to.equal('context') + const { encryptionContext } = await cmm._initializeEncryptionMaterial(suite, { some: 'context' }) + expect(Object.keys(encryptionContext)).lengthOf(1) + expect(encryptionContext).to.have.haveOwnProperty('some').and.to.equal('context') }) it('set a verificationKey from context', async () => { @@ -119,13 +118,14 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring) const context = { some: 'context', [ENCODED_SIGNER_KEY]: 'A29gmBT/NscB90u6npOulZQwAAiKVtoShudOm2J2sCgC' } - const test = await cmm._loadVerificationKeyFromEncryptionContext(new WebCryptoDecryptionMaterial(suite), context) + const test = await cmm._initializeDecryptionMaterial(suite, context) + expect(test).to.be.instanceOf(WebCryptoDecryptionMaterial) const { verificationKey } = test if (!verificationKey) throw new Error('I should never see this error') expect(verificationKey.signatureCurve).to.equal(suite.signatureCurve) }) - it('Precondition: The algorithm suite specification must support a signatureCurve to extract a verification key.', async () => { + it('Check for early return (Postcondition): The WebCryptoAlgorithmSuite specification must support a signatureCurve to extract a verification key.', async () => { class TestKeyring extends KeyringWebCrypto { async _onEncrypt (): Promise { throw new Error('I should never see this error') @@ -140,7 +140,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring) const context = { some: 'context' } - const test = await cmm._loadVerificationKeyFromEncryptionContext(new WebCryptoDecryptionMaterial(suite), context) + const test = await cmm._initializeDecryptionMaterial(suite, context) expect(test.verificationKey).to.equal(undefined) }) @@ -158,7 +158,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { const keyring = new TestKeyring() const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring) - expect(cmm._loadVerificationKeyFromEncryptionContext(new WebCryptoDecryptionMaterial(suite), {})).to.rejectedWith(Error) + expect(cmm._initializeDecryptionMaterial(suite, {})).to.rejectedWith(Error) }) it('Precondition: WebCryptoDefaultCryptographicMaterialsManager The context must contain the public key.', async () => { @@ -176,7 +176,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { const cmm = new WebCryptoDefaultCryptographicMaterialsManager(keyring) const context = { missing: 'signer key' } - expect(cmm._loadVerificationKeyFromEncryptionContext(new WebCryptoDecryptionMaterial(suite), context)).to.rejectedWith(Error) + expect(cmm._initializeDecryptionMaterial(suite, context)).to.rejectedWith(Error) }) it('can return an encryption response', async () => { @@ -203,11 +203,11 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { some: 'context' } - const test = await cmm.getEncryptionMaterials({ suite, encryptionContext }) - expect(Object.keys(test.context)).lengthOf(2) - if (!test.material.signatureKey) throw new Error('I should never see this error') - expect(test.context).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(test.material.signatureKey.compressPoint)) - expect(test.context).to.have.haveOwnProperty('some').and.to.equal('context') + const { material } = await cmm.getEncryptionMaterials({ suite, encryptionContext }) + expect(Object.keys(material.encryptionContext)).lengthOf(2) + if (!material.signatureKey) throw new Error('I should never see this error') + expect(material.encryptionContext).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(material.signatureKey.compressPoint)) + expect(material.encryptionContext).to.have.haveOwnProperty('some').and.to.equal('context') }) it('will pick a default Algorithm Suite', async () => { @@ -233,11 +233,11 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { some: 'context' } - const test = await cmm.getEncryptionMaterials({ encryptionContext }) - expect(Object.keys(test.context)).lengthOf(2) - if (!test.material.signatureKey) throw new Error('I should never see this error') - expect(test.context).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(test.material.signatureKey.compressPoint)) - expect(test.context).to.have.haveOwnProperty('some').and.to.equal('context') + const { material } = await cmm.getEncryptionMaterials({ encryptionContext }) + expect(Object.keys(material.encryptionContext)).lengthOf(2) + if (!material.signatureKey) throw new Error('I should never see this error') + expect(material.encryptionContext).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(material.signatureKey.compressPoint)) + expect(material.encryptionContext).to.have.haveOwnProperty('some').and.to.equal('context') }) it('Postcondition: The WebCryptoEncryptionMaterial must contain a valid dataKey.', async () => { @@ -309,10 +309,10 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { const encryptionContext = { some: 'context', [ENCODED_SIGNER_KEY]: 'A29gmBT/NscB90u6npOulZQwAAiKVtoShudOm2J2sCgC' } const edk = new EncryptedDataKey({ providerId: ' keyNamespace', providerInfo: 'keyName', encryptedDataKey: new Uint8Array(5) }) - const test = await cmm.decryptMaterials({ suite, encryptionContext, encryptedDataKeys: [edk] }) - if (!test.material.verificationKey) throw new Error('I should never see this error') - expect(test.context).to.deep.equal(encryptionContext) - expect(test.material.verificationKey.signatureCurve).to.equal(suite.signatureCurve) + const { material } = await cmm.decryptMaterials({ suite, encryptionContext, encryptedDataKeys: [edk] }) + if (!material.verificationKey) throw new Error('I should never see this error') + expect(material.encryptionContext).to.deep.equal(encryptionContext) + expect(material.verificationKey.signatureCurve).to.equal(suite.signatureCurve) }) it('Postcondition: The WebCryptoDecryptionMaterial must contain a valid dataKey.', async () => { diff --git a/modules/material-management-browser/test/keyring_helpers.test.ts b/modules/material-management-browser/test/keyring_helpers.test.ts index 8a882432b..2d9689861 100644 --- a/modules/material-management-browser/test/keyring_helpers.test.ts +++ b/modules/material-management-browser/test/keyring_helpers.test.ts @@ -90,7 +90,7 @@ describe('importForWebCryptoDecryptionMaterial', () => { it('Check for early return (Postcondition): If no key was able to be decrypted, return.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) await importForWebCryptoDecryptionMaterial(material) expect(material.hasCryptoKey).to.equal(false) @@ -99,7 +99,7 @@ describe('importForWebCryptoDecryptionMaterial', () => { function getWebCryptoDecryptionMaterial () { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } return material.setUnencryptedDataKey(udk, trace) @@ -107,7 +107,7 @@ function getWebCryptoDecryptionMaterial () { function getWebCryptoEncryptionMaterial () { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } return material.setUnencryptedDataKey(udk, trace) diff --git a/modules/material-management-browser/test/material_helpers.test.ts b/modules/material-management-browser/test/material_helpers.test.ts index 741ed3650..69c5c571c 100644 --- a/modules/material-management-browser/test/material_helpers.test.ts +++ b/modules/material-management-browser/test/material_helpers.test.ts @@ -46,7 +46,7 @@ declare const CryptoKey: CryptoKey describe('_importCryptoKey', () => { it('can import WebCryptoEncryptionMaterial with a algorithm suite without a KDF', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -61,7 +61,7 @@ describe('_importCryptoKey', () => { it('can import WebCryptoEncryptionMaterial with a algorithm suite with a KDF', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -75,7 +75,7 @@ describe('_importCryptoKey', () => { it('can import WebCryptoDecryptionMaterial with a algorithm suite without a KDF', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -89,7 +89,7 @@ describe('_importCryptoKey', () => { it('can import WebCryptoDecryptionMaterial with a algorithm suite with a KDF', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -105,7 +105,7 @@ describe('_importCryptoKey', () => { describe('importCryptoKey', () => { it('can import when backend is isFullSupportWebCryptoBackend', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -118,7 +118,7 @@ describe('importCryptoKey', () => { it('can import when backend is mixed support', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -145,7 +145,7 @@ describe('importCryptoKey', () => { describe('WebCryptoKdf', () => { it('returns a valid kdf key', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -162,7 +162,7 @@ describe('WebCryptoKdf', () => { it('Check for early return (Postcondition): No WebCrypto KDF, just return the unencrypted data key.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -179,7 +179,7 @@ describe('WebCryptoKdf', () => { it('Precondition: Valid HKDF values must exist for browsers.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -192,7 +192,7 @@ describe('WebCryptoKdf', () => { it('Postcondition: The derived key must conform to the algorith suite specification.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -213,7 +213,7 @@ describe('WebCryptoKdf', () => { describe('getSubtleFunction', () => { it('can get encrypt', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -236,7 +236,7 @@ describe('getSubtleFunction', () => { it('Precondition: The material must have a CryptoKey.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -247,7 +247,7 @@ describe('getSubtleFunction', () => { it('Precondition: The cryptoKey and backend must match in terms of Mixed vs Full support.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -270,7 +270,7 @@ describe('getSubtleFunction', () => { it('Precondition: The length of the IV must match the algorithm suite specification.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const trace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(udk, trace) @@ -290,8 +290,8 @@ describe('getSubtleFunction', () => { it('no kdf, simple backend, can encrypt/decrypt', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } const decryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } @@ -317,8 +317,8 @@ describe('getSubtleFunction', () => { it('KDF, simple backend, can encrypt/decrypt', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } const decryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } @@ -344,8 +344,8 @@ describe('getSubtleFunction', () => { it('no kdf, mixed backend, can encrypt/decrypt', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } const decryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } @@ -385,8 +385,8 @@ describe('getSubtleFunction', () => { it('kdf, mixed backend, can encrypt/decrypt', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } const decryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } @@ -431,7 +431,7 @@ describe('getSubtleFunction', () => { describe('getEncryptHelper/getDecryptionHelper', () => { it('encryption helpers without a signature', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } encryptionMaterial.setUnencryptedDataKey(udk, encryptTrace) @@ -449,7 +449,7 @@ describe('getEncryptHelper/getDecryptionHelper', () => { it('decryption helpers without a signature ', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } decryptionMaterial.setUnencryptedDataKey(udk, encryptTrace) @@ -467,7 +467,7 @@ describe('getEncryptHelper/getDecryptionHelper', () => { it('encryption helpers with a signature', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const { signatureKey } = await sigKeys(suite) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } @@ -488,7 +488,7 @@ describe('getEncryptHelper/getDecryptionHelper', () => { it('decryption helpers with a signature ', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const { verificationKey } = await sigKeys(suite) const decryptionTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } @@ -509,22 +509,22 @@ describe('getEncryptHelper/getDecryptionHelper', () => { it('Precondition: WebCryptoEncryptionMaterial must have a valid data key.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) expect(getEncryptHelper(encryptionMaterial)).to.rejectedWith(Error) }) it('Precondition: WebCryptoDecryptionMaterial must have a valid data key.', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) expect(getDecryptionHelper(decryptionMaterial)).to.rejectedWith(Error) }) it('can verify what was signed', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const decryptionMaterial = new WebCryptoDecryptionMaterial(suite) - const encryptionMaterial = new WebCryptoEncryptionMaterial(suite) + const decryptionMaterial = new WebCryptoDecryptionMaterial(suite, {}) + const encryptionMaterial = new WebCryptoEncryptionMaterial(suite, {}) const udk = synchronousRandomValues(suite.keyLengthBytes) const { signatureKey, verificationKey } = await sigKeys(suite) const encryptTrace = { keyName: 'keyName', keyNamespace: 'keyNamespace', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } diff --git a/modules/material-management-node/src/node_cryptographic_materials_manager.ts b/modules/material-management-node/src/node_cryptographic_materials_manager.ts index ede548b2f..a6574fe68 100644 --- a/modules/material-management-node/src/node_cryptographic_materials_manager.ts +++ b/modules/material-management-node/src/node_cryptographic_materials_manager.ts @@ -48,11 +48,10 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa async getEncryptionMaterials ({ suite, encryptionContext }: NodeEncryptionRequest): Promise { suite = suite || new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) - const material = new NodeEncryptionMaterial(suite) - const context = await this._generateSigningKeyAndUpdateEncryptionContext(material, encryptionContext) - - await this.keyring.onEncrypt(material, context) + const material = await this + .keyring + .onEncrypt(this._initializeEncryptionMaterial(suite, encryptionContext)) /* Postcondition: The NodeEncryptionMaterial must contain a valid dataKey. */ needs(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.') @@ -60,13 +59,13 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa /* Postcondition: The NodeEncryptionMaterial must contain at least 1 EncryptedDataKey. */ needs(material.encryptedDataKeys.length, 'No EncryptedDataKeys: the ciphertext can never be decrypted.') - return { material, context } + return { material } } async decryptMaterials ({ suite, encryptedDataKeys, encryptionContext }: NodeDecryptionRequest): Promise { - const material = await this._loadVerificationKeyFromEncryptionContext(new NodeDecryptionMaterial(suite), encryptionContext) - - await this.keyring.onDecrypt(material, encryptedDataKeys.slice(), encryptionContext) + const material = await this + .keyring + .onDecrypt(this._initializeDecryptionMaterial(suite, encryptionContext), encryptedDataKeys.slice()) /* Postcondition: The NodeDecryptionMaterial must contain a valid dataKey. * See: cryptographic_materials.ts, `getUnencryptedDataKey` also verifies @@ -74,47 +73,50 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa */ needs(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.') - return { material, context: encryptionContext || {} } + return { material } } - async _generateSigningKeyAndUpdateEncryptionContext (material: NodeEncryptionMaterial, context?: EncryptionContext) { - const { signatureCurve: namedCurve } = material.suite + _initializeEncryptionMaterial (suite: NodeAlgorithmSuite, encryptionContext: EncryptionContext) { + const { signatureCurve: namedCurve } = suite /* Check for early return (Postcondition): The algorithm suite specification must support a signatureCurve to generate a ECDH key. */ - if (!namedCurve) return Object.freeze({ ...context }) + if (!namedCurve) return new NodeEncryptionMaterial(suite, encryptionContext) const ecdh = createECDH(namedCurve) ecdh.generateKeys() // @ts-ignore I want a compressed buffer. const compressPoint = ecdh.getPublicKey(undefined, 'compressed') const privateKey = ecdh.getPrivateKey() - const signatureKey = new SignatureKey(privateKey, new Uint8Array(compressPoint), material.suite) - - material.setSignatureKey(signatureKey) - - return Object.freeze({ - ...context, - [ENCODED_SIGNER_KEY]: compressPoint.toString('base64') - }) + const signatureKey = new SignatureKey(privateKey, new Uint8Array(compressPoint), suite) + + return new NodeEncryptionMaterial( + suite, + { + ...encryptionContext, + [ENCODED_SIGNER_KEY]: compressPoint.toString('base64') + } + ) + .setSignatureKey(signatureKey) } - async _loadVerificationKeyFromEncryptionContext (material: NodeDecryptionMaterial, context?: EncryptionContext) { - const { signatureCurve: namedCurve } = material.suite + _initializeDecryptionMaterial (suite: NodeAlgorithmSuite, encryptionContext: EncryptionContext) { + const { signatureCurve: namedCurve } = suite /* Check for early return (Postcondition): The algorithm suite specification must support a signatureCurve to load a signature key. */ - if (!namedCurve) return material + if (!namedCurve) return new NodeDecryptionMaterial(suite, encryptionContext) /* Precondition: NodeDefaultCryptographicMaterialsManager If the algorithm suite specification requires a signatureCurve a context must exist. */ - if (!context) throw new Error('Context does not contain required public key.') + if (!encryptionContext) throw new Error('Context does not contain required public key.') - const { [ENCODED_SIGNER_KEY]: compressPoint } = context + const { [ENCODED_SIGNER_KEY]: compressPoint } = encryptionContext /* Precondition: NodeDefaultCryptographicMaterialsManager The context must contain the public key. */ needs(compressPoint, 'Context does not contain required public key.') - const publicKeyBytes = VerificationKey.decodeCompressPoint(Buffer.from(compressPoint, 'base64'), material.suite) + const publicKeyBytes = VerificationKey.decodeCompressPoint(Buffer.from(compressPoint, 'base64'), suite) - return material.setVerificationKey(new VerificationKey(publicKeyBytes, material.suite)) + return new NodeDecryptionMaterial(suite, encryptionContext) + .setVerificationKey(new VerificationKey(publicKeyBytes, suite)) } } immutableClass(NodeDefaultCryptographicMaterialsManager) diff --git a/modules/material-management-node/test/material_helpers.test.ts b/modules/material-management-node/test/material_helpers.test.ts index 4d944d699..d165ce1ce 100644 --- a/modules/material-management-node/test/material_helpers.test.ts +++ b/modules/material-management-node/test/material_helpers.test.ts @@ -25,7 +25,7 @@ import { Decipheriv, Cipheriv, createECDH } from 'crypto' describe('nodeKdf', () => { it('Check for early return (Postcondition): No Node.js KDF, just return the unencrypted data key.', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -36,7 +36,7 @@ describe('nodeKdf', () => { it('HKDF SHA256', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -48,7 +48,7 @@ describe('nodeKdf', () => { it('HKDF SHA384', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -88,7 +88,7 @@ describe('nodeKdf', () => { describe('getCryptoStream', () => { it('return a Cipheriv', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -101,7 +101,7 @@ describe('getCryptoStream', () => { it('return a Decipheriv', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -114,7 +114,7 @@ describe('getCryptoStream', () => { it('Precondition: The length of the IV must match the algorithm suite specification.', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -126,7 +126,7 @@ describe('getCryptoStream', () => { it('Precondition: The material must have not been zeroed.', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -141,7 +141,7 @@ describe('getCryptoStream', () => { describe('getEncryptHelper', () => { it('basic shape', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -161,7 +161,7 @@ describe('getEncryptHelper', () => { it('signer', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY } @@ -192,7 +192,7 @@ describe('getEncryptHelper', () => { describe('getDecryptionHelper', () => { it('first test', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } material.setUnencryptedDataKey(dataKey, trace) @@ -212,7 +212,7 @@ describe('getDecryptionHelper', () => { it('verify', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const dataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } diff --git a/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts b/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts index 711eee7a2..79aeceb4c 100644 --- a/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts +++ b/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts @@ -57,7 +57,7 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { expect(() => new NodeDefaultCryptographicMaterialsManager({} as any)).to.throw() }) - it('should create a signature key and append it to context', async () => { + it('should create signature key and append the verification key to context and return NodeEncryptionMaterial', async () => { class TestKeyring extends KeyringNode { async _onEncrypt (): Promise { throw new Error('never') @@ -70,14 +70,15 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const cmm = new NodeDefaultCryptographicMaterialsManager(keyring) const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const material = new NodeEncryptionMaterial(suite) const context = { some: 'context' } - const test = await cmm._generateSigningKeyAndUpdateEncryptionContext(material, context) - expect(Object.keys(test)).lengthOf(2) - expect(Object.isFrozen(test)).to.equal(true) + const test = cmm._initializeEncryptionMaterial(suite, context) + expect(test).to.be.instanceOf(NodeEncryptionMaterial) + expect(test.suite).to.equal(suite) + expect(Object.keys(test.encryptionContext)).lengthOf(2) + expect(Object.isFrozen(test.encryptionContext)).to.equal(true) expect(Object.isFrozen(context)).to.equal(false) - expect(test).to.have.ownProperty('some').and.to.equal('context') - expect(test).to.have.ownProperty(ENCODED_SIGNER_KEY) + expect(test.encryptionContext).to.have.ownProperty('some').and.to.equal('context') + expect(test.encryptionContext).to.have.ownProperty(ENCODED_SIGNER_KEY) }) it('Check for early return (Postcondition): The algorithm suite specification must support a signatureCurve to generate a ECDH key.', async () => { @@ -93,13 +94,14 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const cmm = new NodeDefaultCryptographicMaterialsManager(keyring) const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) const context = { some: 'context' } - const test = await cmm._generateSigningKeyAndUpdateEncryptionContext(material, context) - expect(Object.keys(test)).lengthOf(1) - expect(Object.isFrozen(test)).to.equal(true) + const test = cmm._initializeEncryptionMaterial(suite, context) + expect(test).to.be.instanceOf(NodeEncryptionMaterial) + expect(test.suite).to.equal(suite) + expect(Object.keys(test.encryptionContext)).lengthOf(1) + expect(Object.isFrozen(test.encryptionContext)).to.equal(true) expect(Object.isFrozen(context)).to.equal(false) - expect(test).to.have.ownProperty('some').and.to.equal('context') + expect(test.encryptionContext).to.have.ownProperty('some').and.to.equal('context') }) it('Set the verification key.', async () => { @@ -116,14 +118,14 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const context = await cmm._generateSigningKeyAndUpdateEncryptionContext( - new NodeEncryptionMaterial(suite), + const { encryptionContext } = cmm._initializeEncryptionMaterial( + suite, { some: 'context' } ) - const material = await cmm._loadVerificationKeyFromEncryptionContext( - new NodeDecryptionMaterial(suite), - context + const material = cmm._initializeDecryptionMaterial( + suite, + encryptionContext ) expect(material.verificationKey).to.have.ownProperty('publicKey') }) @@ -141,10 +143,9 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const cmm = new NodeDefaultCryptographicMaterialsManager(keyring) const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeDecryptionMaterial(suite) const context = { some: 'context' } - const test = await cmm._loadVerificationKeyFromEncryptionContext(material, context) - expect(test === material).to.equal(true) + const { encryptionContext } = cmm._initializeDecryptionMaterial(suite, context) + expect(encryptionContext).to.deep.equal(context) }) it('Precondition: NodeDefaultCryptographicMaterialsManager If the algorithm suite specification requires a signatureCurve a context must exist.', async () => { @@ -160,9 +161,7 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const cmm = new NodeDefaultCryptographicMaterialsManager(keyring) const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - await expect(cmm._loadVerificationKeyFromEncryptionContext( - new NodeDecryptionMaterial(suite) - )).to.rejectedWith(Error) + expect(() => cmm._initializeDecryptionMaterial(suite, undefined as any)).to.throw() }) it('Precondition: NodeDefaultCryptographicMaterialsManager The context must contain the public key.', async () => { @@ -178,10 +177,10 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const cmm = new NodeDefaultCryptographicMaterialsManager(keyring) const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - await expect(cmm._loadVerificationKeyFromEncryptionContext( - new NodeDecryptionMaterial(suite), + expect(() => cmm._initializeDecryptionMaterial( + suite, { no: 'signature' } - )).to.rejectedWith(Error) + )).to.throw() }) it('Postcondition: The NodeEncryptionMaterial must contain a valid dataKey.', async () => { @@ -198,7 +197,7 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const keyring = new TestKeyring() const cmm = new NodeDefaultCryptographicMaterialsManager(keyring) - await expect(cmm.getEncryptionMaterials({ suite })).to.rejectedWith(Error) + await expect(cmm.getEncryptionMaterials({ suite, encryptionContext: {} })).to.rejectedWith(Error) }) it('Postcondition: The NodeEncryptionMaterial must contain at least 1 EncryptedDataKey.', async () => { @@ -217,7 +216,7 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { const keyring = new TestKeyring() const cmm = new NodeDefaultCryptographicMaterialsManager(keyring) - await expect(cmm.getEncryptionMaterials({ suite })).to.rejectedWith(Error) + await expect(cmm.getEncryptionMaterials({ suite, encryptionContext: {} })).to.rejectedWith(Error) }) it('Postcondition: The NodeDecryptionMaterial must contain a valid dataKey.', async () => { @@ -237,7 +236,7 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { providerId: 'p', providerInfo: 'p', encryptedDataKey: new Uint8Array(5) })] - await expect(cmm.decryptMaterials({ suite, encryptedDataKeys })).to.rejectedWith(Error) + await expect(cmm.decryptMaterials({ suite, encryptedDataKeys, encryptionContext: {} })).to.rejectedWith(Error) }) it('Return decryption material', async () => { @@ -259,7 +258,7 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { providerId: 'p', providerInfo: 'p', encryptedDataKey: new Uint8Array(5) })] - const { material } = await cmm.decryptMaterials({ suite, encryptedDataKeys }) + const { material } = await cmm.decryptMaterials({ suite, encryptedDataKeys, encryptionContext: {} }) expect(material.hasUnencryptedDataKey).to.equal(true) }) }) diff --git a/modules/material-management/src/cryptographic_material.ts b/modules/material-management/src/cryptographic_material.ts index 9e033236d..b9206ee7b 100644 --- a/modules/material-management/src/cryptographic_material.ts +++ b/modules/material-management/src/cryptographic_material.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { MixedBackendCryptoKey, SupportedAlgorithmSuites } from './types' // eslint-disable-line no-unused-vars +import { MixedBackendCryptoKey, SupportedAlgorithmSuites, EncryptionContext } from './types' // eslint-disable-line no-unused-vars import { EncryptedDataKey } from './encrypted_data_key' import { SignatureKey, VerificationKey } from './signature_key' import { frozenClass, readOnlyProperty } from './immutable_class' @@ -22,6 +22,23 @@ import { NodeAlgorithmSuite } from './node_algorithms' import { WebCryptoAlgorithmSuite } from './web_crypto_algorithms' import { needs } from './needs' +/* + * This public interface to the CryptographicMaterial object is provided for + * developers of CMMs and keyrings only. If you are a user of the AWS Encryption + * SDK and you are not developing your own CMMs and/or keyrings, you do not + * need to use it and you should not do so. + * + * The CryptographicMaterial's purpose is to bind together all the required elements for + * encrypting or decrypting a payload. + * The functional data key (unencrypted or CryptoKey) is the most sensitive data and needs to + * be protected. The longer this data persists in memory the + * greater the opportunity to be invalidated. Because + * a Caching CMM exists is it important to insure that the + * unencrypted data key and it's meta data can not be manipulated, + * and that the unencrypted data key can be zeroed when + * it is no longer needed. + */ + let timingSafeEqual: (a: Uint8Array, b: Uint8Array) => boolean try { /* It is possible for `require` to return an empty object, or an object @@ -53,23 +70,6 @@ function portableTimingSafeEqual (a: Uint8Array, b: Uint8Array) { return (diff === 0) } -/* - * This public interface to the CryptographicMaterial object is provided for - * developers of CMMs and keyrings only. If you are a user of the AWS Encryption - * SDK and you are not developing your own CMMs and/or keyrings, you do not - * need to use it and you should not do so. - * - * The CryptographicMaterial's purpose is to bind together all the required elements for - * encrypting or decrypting a payload. - * The functional data key (unencrypted or CryptoKey) is the most sensitive data and needs to - * be protected. The longer this data persists in memory the - * greater the opportunity to be invalidated. Because - * a Caching CMM exists is it important to insure that the - * unencrypted data key and it's meta data can not be manipulated, - * and that the unencrypted data key can be zeroed when - * it is no longer needed. - */ - export interface FunctionalCryptographicMaterial { hasValidKey: () => boolean } @@ -82,6 +82,7 @@ export interface CryptographicMaterial> { hasUnencryptedDataKey: boolean unencryptedDataKeyLength: number keyringTrace: KeyringTrace[] + encryptionContext: Readonly } export interface EncryptionMaterial> extends CryptographicMaterial { @@ -117,10 +118,14 @@ export class NodeEncryptionMaterial implements addEncryptedDataKey!: (edk: EncryptedDataKey, flags: KeyringTraceFlag) => NodeEncryptionMaterial setSignatureKey!: (key: SignatureKey) => NodeEncryptionMaterial signatureKey?: SignatureKey - constructor (suite: NodeAlgorithmSuite) { + encryptionContext: Readonly + constructor (suite: NodeAlgorithmSuite, encryptionContext: EncryptionContext) { /* Precondition: NodeEncryptionMaterial suite must be NodeAlgorithmSuite. */ needs(suite instanceof NodeAlgorithmSuite, 'Suite must be a NodeAlgorithmSuite') this.suite = suite + /* Precondition: NodeEncryptionMaterial encryptionContext must be an object, even if it is empty. */ + needs(encryptionContext && typeof encryptionContext === 'object', 'Encryption context must be set') + this.encryptionContext = Object.freeze({ ...encryptionContext }) // EncryptionMaterial have generated a data key on setUnencryptedDataKey const setFlags = KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY decorateCryptographicMaterial(this, setFlags) @@ -146,10 +151,14 @@ export class NodeDecryptionMaterial implements keyringTrace: KeyringTrace[] = [] setVerificationKey!: (key: VerificationKey) => NodeDecryptionMaterial verificationKey?: VerificationKey - constructor (suite: NodeAlgorithmSuite) { + encryptionContext: Readonly + constructor (suite: NodeAlgorithmSuite, encryptionContext: EncryptionContext) { /* Precondition: NodeDecryptionMaterial suite must be NodeAlgorithmSuite. */ needs(suite instanceof NodeAlgorithmSuite, 'Suite must be a NodeAlgorithmSuite') this.suite = suite + /* Precondition: NodeDecryptionMaterial encryptionContext must be an object, even if it is empty. */ + needs(encryptionContext && typeof encryptionContext === 'object', 'Encryption context must be set') + this.encryptionContext = Object.freeze({ ...encryptionContext }) // DecryptionMaterial have decrypted a data key on setUnencryptedDataKey const setFlags = KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY decorateCryptographicMaterial(this, setFlags) @@ -182,11 +191,15 @@ export class WebCryptoEncryptionMaterial implements getCryptoKey!: () => CryptoKey|MixedBackendCryptoKey hasCryptoKey!: boolean validUsages: ReadonlyArray - constructor (suite: WebCryptoAlgorithmSuite) { + encryptionContext: Readonly + constructor (suite: WebCryptoAlgorithmSuite, encryptionContext: EncryptionContext) { /* Precondition: WebCryptoEncryptionMaterial suite must be WebCryptoAlgorithmSuite. */ needs(suite instanceof WebCryptoAlgorithmSuite, 'Suite must be a WebCryptoAlgorithmSuite') this.suite = suite this.validUsages = Object.freeze(['deriveKey', 'encrypt']) + /* Precondition: WebCryptoEncryptionMaterial encryptionContext must be an object, even if it is empty. */ + needs(encryptionContext && typeof encryptionContext === 'object', 'Encryption context must be set') + this.encryptionContext = Object.freeze({ ...encryptionContext }) // EncryptionMaterial have generated a data key on setUnencryptedDataKey const setFlag = KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY decorateCryptographicMaterial(this, setFlag) @@ -218,11 +231,15 @@ export class WebCryptoDecryptionMaterial implements getCryptoKey!: () => CryptoKey|MixedBackendCryptoKey hasCryptoKey!: boolean validUsages: ReadonlyArray - constructor (suite: WebCryptoAlgorithmSuite) { + encryptionContext: Readonly + constructor (suite: WebCryptoAlgorithmSuite, encryptionContext: EncryptionContext) { /* Precondition: WebCryptoDecryptionMaterial suite must be WebCryptoAlgorithmSuite. */ needs(suite instanceof WebCryptoAlgorithmSuite, 'Suite must be a WebCryptoAlgorithmSuite') this.suite = suite this.validUsages = Object.freeze(['deriveKey', 'decrypt']) + /* Precondition: WebCryptoDecryptionMaterial encryptionContext must be an object, even if it is empty. */ + needs(encryptionContext && typeof encryptionContext === 'object', 'Encryption context must be set') + this.encryptionContext = Object.freeze({ ...encryptionContext }) // DecryptionMaterial have decrypted a data key on setUnencryptedDataKey const setFlag = KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY decorateCryptographicMaterial(this, setFlag) diff --git a/modules/material-management/src/keyring.ts b/modules/material-management/src/keyring.ts index ed54990a2..5e0c13fc0 100644 --- a/modules/material-management/src/keyring.ts +++ b/modules/material-management/src/keyring.ts @@ -17,7 +17,7 @@ import { EncryptedDataKey } from './encrypted_data_key' import { immutableBaseClass, immutableClass } from './immutable_class' import { isEncryptionMaterial, isDecryptionMaterial } from './cryptographic_material' -import { EncryptionContext, EncryptionMaterial, DecryptionMaterial, SupportedAlgorithmSuites } from './types' // eslint-disable-line no-unused-vars +import { EncryptionMaterial, DecryptionMaterial, SupportedAlgorithmSuites } from './types' // eslint-disable-line no-unused-vars import { needs } from './needs' import { NodeAlgorithmSuite } from './node_algorithms' // eslint-disable-line no-unused-vars import { WebCryptoAlgorithmSuite } from './web_crypto_algorithms' // eslint-disable-line no-unused-vars @@ -30,9 +30,9 @@ import { WebCryptoAlgorithmSuite } from './web_crypto_algorithms' // eslint-disa */ export abstract class Keyring { - async onEncrypt (material: EncryptionMaterial, context?: EncryptionContext): Promise> { + async onEncrypt (material: EncryptionMaterial): Promise> { /* Precondition: material must be a type of isEncryptionMaterial. - * There are several security properties that NodeEncryptionMaterial and WebCryptoEncrypionMaterial + * There are several security properties that NodeEncryptionMaterial and WebCryptoEncryptionMaterial * posses. * The unencryptedDataKey can only be written once. * If a data key has not already been generated, there must be no EDKs. @@ -40,7 +40,7 @@ export abstract class Keyring { */ needs(isEncryptionMaterial(material), 'Unsupported type of material.') - const _material = await this._onEncrypt(material, context) + const _material = await this._onEncrypt(material) /* Postcondition: The EncryptionMaterial objects must be the same. * See cryptographic_materials.ts. The CryptographicMaterial objects @@ -58,7 +58,7 @@ export abstract class Keyring { return material } - abstract _onEncrypt(material: EncryptionMaterial, context?: EncryptionContext): Promise> + abstract _onEncrypt(material: EncryptionMaterial): Promise> /* NOTE: The order of EDK's passed to the onDecrypt function is a clear * intent on the part of the person who did the encryption. @@ -71,7 +71,7 @@ export abstract class Keyring { * who called encrypt can control the order of EDK and in the * configuration of the KMS Keyring. */ - async onDecrypt (material: DecryptionMaterial, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext): Promise> { + async onDecrypt (material: DecryptionMaterial, encryptedDataKeys: EncryptedDataKey[]): Promise> { /* Precondition: material must be DecryptionMaterial. */ needs(isDecryptionMaterial(material), 'Unsupported material type.') @@ -81,7 +81,7 @@ export abstract class Keyring { /* Precondition: encryptedDataKeys must all be EncryptedDataKey. */ needs(encryptedDataKeys.every(edk => edk instanceof EncryptedDataKey), 'Unsupported EncryptedDataKey type') - const _material = await this._onDecrypt(material, encryptedDataKeys, context) + const _material = await this._onDecrypt(material, encryptedDataKeys) /* Postcondition: The DecryptionMaterial objects must be the same. * See cryptographic_materials.ts. The CryptographicMaterial objects @@ -101,7 +101,7 @@ export abstract class Keyring { return material } - abstract _onDecrypt(material: DecryptionMaterial, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext): Promise> + abstract _onDecrypt(material: DecryptionMaterial, encryptedDataKeys: EncryptedDataKey[]): Promise> } immutableBaseClass(Keyring) diff --git a/modules/material-management/src/multi_keyring.ts b/modules/material-management/src/multi_keyring.ts index 86a990533..8baccc484 100644 --- a/modules/material-management/src/multi_keyring.ts +++ b/modules/material-management/src/multi_keyring.ts @@ -19,7 +19,7 @@ import { KeyringNode, KeyringWebCrypto } from './keyring' -import { EncryptionContext, SupportedAlgorithmSuites, EncryptionMaterial, DecryptionMaterial } from './types' // eslint-disable-line no-unused-vars +import { SupportedAlgorithmSuites, EncryptionMaterial, DecryptionMaterial } from './types' // eslint-disable-line no-unused-vars import { needs } from './needs' import { EncryptedDataKey } from './encrypted_data_key' // eslint-disable-line no-unused-vars import { NodeAlgorithmSuite } from './node_algorithms' // eslint-disable-line no-unused-vars @@ -69,10 +69,10 @@ function decorateProperties ( function buildPrivateOnEncrypt () { return async function _onEncrypt ( this: IMultiKeyring, - material: EncryptionMaterial, context?: EncryptionContext + material: EncryptionMaterial ): Promise> { const generated = this.generator - ? await this.generator.onEncrypt(material, context) + ? await this.generator.onEncrypt(material) : material /* Precondition: A Generator Keyring *must* ensure generated material. */ @@ -87,7 +87,7 @@ function buildPrivateOnEncrypt () { * append based on already appended EDK's. */ for (const keyring of this.children) { - await keyring.onEncrypt(generated, context) + await keyring.onEncrypt(generated) } // Keyrings are required to not create new EncryptionMaterial instances, but @@ -101,8 +101,7 @@ function buildPrivateOnDecrypt () { return async function _onDecrypt ( this: IMultiKeyring, material: DecryptionMaterial, - encryptedDataKeys: EncryptedDataKey[], - context?: EncryptionContext + encryptedDataKeys: EncryptedDataKey[] ): Promise> { const children = this.children.slice() if (this.generator) children.unshift(this.generator) @@ -112,7 +111,7 @@ function buildPrivateOnDecrypt () { if (material.hasValidKey()) return material try { - await keyring.onDecrypt(material, encryptedDataKeys, context) + await keyring.onDecrypt(material, encryptedDataKeys) } catch (e) { // there should be some debug here? or wrap? // Failures onDecrypt should not short-circuit the process diff --git a/modules/material-management/src/types.ts b/modules/material-management/src/types.ts index aa1fadec7..bbf5e67a3 100644 --- a/modules/material-management/src/types.ts +++ b/modules/material-management/src/types.ts @@ -30,25 +30,23 @@ export type MixedBackendCryptoKey = { export interface EncryptionRequest { readonly suite?: S - readonly encryptionContext?: EncryptionContext + readonly encryptionContext: EncryptionContext readonly frameLength?: number readonly plaintextLength?: number } export interface EncryptionResponse { - material: EncryptionMaterial, - context: EncryptionContext + material: EncryptionMaterial } export interface DecryptionRequest { readonly suite: S - readonly encryptionContext?: EncryptionContext + readonly encryptionContext: EncryptionContext readonly encryptedDataKeys: ReadonlyArray } export interface DecryptionResponse { - material: DecryptionMaterial, - context: EncryptionContext + material: DecryptionMaterial } export type SupportedAlgorithmSuites = NodeAlgorithmSuite|WebCryptoAlgorithmSuite diff --git a/modules/material-management/test/cryptographic_material.test.ts b/modules/material-management/test/cryptographic_material.test.ts index ae94e915b..b2c7ee205 100644 --- a/modules/material-management/test/cryptographic_material.test.ts +++ b/modules/material-management/test/cryptographic_material.test.ts @@ -321,13 +321,13 @@ describe('decorateWebCryptoMaterial:Helpers', () => { describe('subtleFunctionForMaterial', () => { it('WebCryptoDecryptionMaterial is decrypt', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) expect(subtleFunctionForMaterial(material)).to.equal('decrypt') }) it('WebCryptoEncryptionMaterial is encrypt', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) expect(subtleFunctionForMaterial(material)).to.equal('encrypt') }) it('unsupported', () => { @@ -339,25 +339,25 @@ describe('decorateWebCryptoMaterial:Helpers', () => { describe('keyUsageForMaterial', () => { it('ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256 is deriveKey', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) expect(keyUsageForMaterial(material)).to.equal('deriveKey') }) it('ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256 is decrypt', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) expect(keyUsageForMaterial(material)).to.equal('deriveKey') }) it('WebCryptoDecryptionMaterial is decrypt', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) expect(keyUsageForMaterial(material)).to.equal('decrypt') }) it('WebCryptoEncryptionMaterial is encrypt', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) expect(keyUsageForMaterial(material)).to.equal('encrypt') }) @@ -375,7 +375,7 @@ describe('decorateWebCryptoMaterial:Helpers', () => { describe('isValidCryptoKey', () => { it('Suite with KDF is valid for both the derivable key and the derived key', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const keyKdf: any = { type: 'secret', algorithm: { name: suite.kdf }, usages: ['deriveKey'], extractable: false } const deriveKey: any = { type: 'secret', algorithm: { name: suite.encryption, length: suite.keyLength }, usages: ['encrypt'], extractable: false } expect(isValidCryptoKey(keyKdf, material)).to.equal(true) @@ -384,7 +384,7 @@ describe('decorateWebCryptoMaterial:Helpers', () => { it('Suite without the KDF is only derivable with the key', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const keyKdf: any = { type: 'secret', algorithm: { name: suite.kdf }, usages: ['deriveKey'], extractable: false } const key: any = { type: 'secret', algorithm: { name: suite.encryption, length: suite.keyLength }, usages: ['encrypt'], extractable: false } expect(isValidCryptoKey(keyKdf, material)).to.equal(false) @@ -392,28 +392,28 @@ describe('decorateWebCryptoMaterial:Helpers', () => { }) it('only type === secret is valid', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const key: any = { type: 'private', algorithm: { name: suite.encryption, length: suite.keyLength }, usages: ['encrypt'], extractable: false } expect(isValidCryptoKey(key, material)).to.equal(false) }) it('length must match', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const key: any = { type: 'secret', algorithm: { name: suite.encryption, length: suite.keyLength - 1 }, usages: ['encrypt'], extractable: false } expect(isValidCryptoKey(key, material)).to.equal(false) }) it('can not be extractable', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const key: any = { type: 'secret', algorithm: { name: suite.encryption, length: suite.keyLength }, usages: ['encrypt'], extractable: true } expect(isValidCryptoKey(key, material)).to.equal(false) }) it('usage must match', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const key: any = { type: 'secret', algorithm: { name: suite.encryption, length: suite.keyLength }, usages: ['decrypt'], extractable: false } expect(isValidCryptoKey(key, material)).to.equal(false) }) @@ -422,52 +422,68 @@ describe('decorateWebCryptoMaterial:Helpers', () => { describe('NodeEncryptionMaterial', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const test: any = new NodeEncryptionMaterial(suite) + const test: any = new NodeEncryptionMaterial(suite, {}) it('instance is frozen', () => expect(Object.isFrozen(test)).to.equal(true)) it('has a suite', () => expect(test.suite === suite).to.equal(true)) it('class is frozen', () => expect(Object.isFrozen(NodeAlgorithmSuite)).to.equal(true)) it('class prototype is frozen', () => expect(Object.isFrozen(NodeAlgorithmSuite.prototype)).to.equal(true)) it('Precondition: NodeEncryptionMaterial suite must be NodeAlgorithmSuite.', () => { const suite: any = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - expect(() => new NodeEncryptionMaterial(suite)).to.throw() + expect(() => new NodeEncryptionMaterial(suite, {})).to.throw() + }) + it('Precondition: NodeEncryptionMaterial encryptionContext must be an object, even if it is empty.', () => { + expect(() => new NodeEncryptionMaterial(suite, undefined as any)).to.throw() + expect(() => new NodeEncryptionMaterial(suite, true as any)).to.throw() }) }) describe('NodeDecryptionMaterial', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const test: any = new NodeDecryptionMaterial(suite) + const test: any = new NodeDecryptionMaterial(suite, {}) it('instance is frozen', () => expect(Object.isFrozen(test)).to.equal(true)) it('has a suite', () => expect(test.suite === suite).to.equal(true)) it('class is frozen', () => expect(Object.isFrozen(NodeAlgorithmSuite)).to.equal(true)) it('class prototype is frozen', () => expect(Object.isFrozen(NodeAlgorithmSuite.prototype)).to.equal(true)) it('Precondition: NodeDecryptionMaterial suite must be NodeAlgorithmSuite.', () => { const suite: any = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - expect(() => new NodeDecryptionMaterial(suite)).to.throw() + expect(() => new NodeDecryptionMaterial(suite, {})).to.throw() + }) + it('Precondition: NodeDecryptionMaterial encryptionContext must be an object, even if it is empty.', () => { + expect(() => new NodeDecryptionMaterial(suite, undefined as any)).to.throw() + expect(() => new NodeDecryptionMaterial(suite, true as any)).to.throw() }) }) describe('WebCryptoEncryptionMaterial', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const test: any = new WebCryptoEncryptionMaterial(suite) + const test: any = new WebCryptoEncryptionMaterial(suite, {}) it('instance is frozen', () => expect(Object.isFrozen(test)).to.equal(true)) it('has a suite', () => expect(test.suite === suite).to.equal(true)) it('class is frozen', () => expect(Object.isFrozen(WebCryptoAlgorithmSuite)).to.equal(true)) it('class prototype is frozen', () => expect(Object.isFrozen(WebCryptoAlgorithmSuite.prototype)).to.equal(true)) it('Precondition: WebCryptoEncryptionMaterial suite must be WebCryptoAlgorithmSuite.', () => { const suite: any = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - expect(() => new WebCryptoEncryptionMaterial(suite)).to.throw() + expect(() => new WebCryptoEncryptionMaterial(suite, {})).to.throw() + }) + it('Precondition: WebCryptoEncryptionMaterial encryptionContext must be an object, even if it is empty.', () => { + expect(() => new WebCryptoEncryptionMaterial(suite, undefined as any)).to.throw() + expect(() => new WebCryptoEncryptionMaterial(suite, true as any)).to.throw() }) }) describe('WebCryptoDecryptionMaterial', () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const test: any = new WebCryptoDecryptionMaterial(suite) + const test: any = new WebCryptoDecryptionMaterial(suite, {}) it('instance is frozen', () => expect(Object.isFrozen(test)).to.equal(true)) it('has a suite', () => expect(test.suite === suite).to.equal(true)) it('class is frozen', () => expect(Object.isFrozen(WebCryptoAlgorithmSuite)).to.equal(true)) it('class prototype is frozen', () => expect(Object.isFrozen(WebCryptoAlgorithmSuite.prototype)).to.equal(true)) it('Precondition: WebCryptoDecryptionMaterial suite must be WebCryptoAlgorithmSuite.', () => { const suite: any = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - expect(() => new WebCryptoDecryptionMaterial(suite)).to.throw() + expect(() => new WebCryptoDecryptionMaterial(suite, {})).to.throw() + }) + it('Precondition: WebCryptoDecryptionMaterial encryptionContext must be an object, even if it is empty.', () => { + expect(() => new WebCryptoDecryptionMaterial(suite, undefined as any)).to.throw() + expect(() => new WebCryptoDecryptionMaterial(suite, true as any)).to.throw() }) }) diff --git a/modules/material-management/test/keyring.test.ts b/modules/material-management/test/keyring.test.ts index 0ed2c93c6..0d1720f2b 100644 --- a/modules/material-management/test/keyring.test.ts +++ b/modules/material-management/test/keyring.test.ts @@ -23,7 +23,6 @@ import { AlgorithmSuiteIdentifier } from '../src/algorithm_suites' import { NodeAlgorithmSuite } from '../src/node_algorithms' import { EncryptedDataKey } from '../src/encrypted_data_key' import { Keyring } from '../src/keyring' -import { EncryptionContext } from '../src/types' // eslint-disable-line no-unused-vars import { KeyringTraceFlag } from '../src' chai.use(chaiAsPromised) const { expect } = chai @@ -46,7 +45,7 @@ describe('Keyring', () => { it('onEncrypt calls _onEncrypt', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const { keyLengthBytes } = suite - const m = new NodeEncryptionMaterial(suite) + const m = new NodeEncryptionMaterial(suite, {}) const unencryptedDataKey = new Uint8Array(keyLengthBytes).fill(1) let assertCount = 0 class TestKeyring extends Keyring { @@ -71,14 +70,15 @@ describe('Keyring', () => { it('onDecrypt calls _onDecrypt', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const edk = new EncryptedDataKey({ providerId: 'p', providerInfo: 'i', encryptedDataKey: new Uint8Array(3) }) - const material = new NodeDecryptionMaterial(suite) const encryptionContext = { some: 'context' } + const material = new NodeDecryptionMaterial(suite, encryptionContext) let assertCount = 0 + class TestKeyring extends Keyring { - async _onDecrypt (_material: NodeDecryptionMaterial, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext) { + async _onDecrypt (_material: NodeDecryptionMaterial, encryptedDataKeys: EncryptedDataKey[]) { expect(_material === material).to.equal(true) expect(encryptedDataKeys[0] === edk).to.equal(true) - expect(context === encryptionContext).to.equal(true) + expect(_material.encryptionContext).to.deep.equal(encryptionContext) assertCount += 1 return _material } @@ -87,7 +87,7 @@ describe('Keyring', () => { return material } } - const _material = await (new TestKeyring()).onDecrypt(material, [edk], encryptionContext) + const _material = await (new TestKeyring()).onDecrypt(material, [edk]) expect(material === _material).to.equal(true) expect(assertCount).to.equal(1) }) @@ -116,7 +116,7 @@ describe('Keyring: onEncrypt', () => { class TestKeyring extends Keyring { async _onEncrypt (material: NodeEncryptionMaterial) { assertCount += 1 - return new NodeEncryptionMaterial(material.suite) + return new NodeEncryptionMaterial(material.suite, {}) } async _onDecrypt (material: NodeDecryptionMaterial) { never() @@ -124,7 +124,7 @@ describe('Keyring: onEncrypt', () => { } } const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) await expect((new TestKeyring()).onEncrypt(material)).to.rejectedWith(Error) expect(assertCount).to.equal(1) }) @@ -136,7 +136,7 @@ describe('Keyring: onDecrypt', () => { const edk = new EncryptedDataKey({ providerId: 'p', providerInfo: 'i', encryptedDataKey: new Uint8Array(3) }) let assertCount = 0 class TestKeyring extends Keyring { - async _onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async _onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[] */) { assertCount += 1 return material } @@ -151,14 +151,14 @@ describe('Keyring: onDecrypt', () => { it('Precondition: Attempt to decrypt iif material does not have an unencrypted data key.', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const unencryptedDataKey = new Uint8Array(suite.keyLengthBytes).fill(1) const trace = { keyNamespace: 'k', keyName: 'k', flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY } material.setUnencryptedDataKey(unencryptedDataKey, trace) const edk = new EncryptedDataKey({ providerId: 'p', providerInfo: 'i', encryptedDataKey: new Uint8Array(3) }) let assertCount = 0 class TestKeyring extends Keyring { - async _onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async _onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[] */) { assertCount += 1 return material } @@ -174,11 +174,11 @@ describe('Keyring: onDecrypt', () => { it('Precondition: encryptedDataKeys must all be EncryptedDataKey.', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const edk: any = {} let assertCount = 0 class TestKeyring extends Keyring { - async _onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async _onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[] */) { assertCount += 1 return material } @@ -193,11 +193,11 @@ describe('Keyring: onDecrypt', () => { it('Postcondition: The DecryptionMaterial objects must be the same.', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const edk = new EncryptedDataKey({ providerId: 'p', providerInfo: 'i', encryptedDataKey: new Uint8Array(3) }) let assertCount = 0 class TestKeyring extends Keyring { - async _onDecrypt (/* material: NodeDecryptionMaterial , encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async _onDecrypt (/* material: NodeDecryptionMaterial , encryptedDataKeys: EncryptedDataKey[] */) { assertCount += 1 const _material: any = {} return _material diff --git a/modules/material-management/test/multi_keyring.test.ts b/modules/material-management/test/multi_keyring.test.ts index 90f95e040..15cb0b4c2 100644 --- a/modules/material-management/test/multi_keyring.test.ts +++ b/modules/material-management/test/multi_keyring.test.ts @@ -124,7 +124,7 @@ describe('MultiKeyring: onEncrypt', () => { }) const mkeyring = new MultiKeyringNode({ generator }) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const test: any = await mkeyring.onEncrypt(material) expect(test === material).to.equal(true) @@ -161,7 +161,7 @@ describe('MultiKeyring: onEncrypt', () => { ] const mkeyring = new MultiKeyringNode({ generator, children }) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const test: any = await mkeyring.onEncrypt(material) expect(test === material).to.equal(true) @@ -187,7 +187,7 @@ describe('MultiKeyring: onEncrypt', () => { }) const mkeyring = new MultiKeyringNode({ generator }) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) await expect(mkeyring.onEncrypt(material)).to.rejectedWith(Error) }) @@ -204,7 +204,7 @@ describe('MultiKeyring: onEncrypt', () => { }) const mkeyring = new MultiKeyringNode({ generator }) - const material = new NodeEncryptionMaterial(suite).setUnencryptedDataKey(unencryptedDataKey, keyringTrace0) + const material = new NodeEncryptionMaterial(suite, {}).setUnencryptedDataKey(unencryptedDataKey, keyringTrace0) await mkeyring.onEncrypt(material) }) @@ -215,10 +215,10 @@ describe('MultiKeyring: onDecrypt', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const unencryptedDataKey = new Uint8Array(suite.keyLengthBytes) const [edk0, keyringTrace0] = makeEDKandTrace(0) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const generator = keyRingFactory({ - async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[] */) { return material.setUnencryptedDataKey(unencryptedDataKey, keyringTrace0) }, onEncrypt: never @@ -239,10 +239,10 @@ describe('MultiKeyring: onDecrypt', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const unencryptedDataKey = new Uint8Array(suite.keyLengthBytes) const [edk0, keyringTrace0] = makeEDKandTrace(0) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const child = keyRingFactory({ - async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[] */) { return material.setUnencryptedDataKey(unencryptedDataKey, keyringTrace0) }, onEncrypt: never @@ -263,10 +263,10 @@ describe('MultiKeyring: onDecrypt', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const unencryptedDataKey = new Uint8Array(suite.keyLengthBytes) const [edk0, keyringTrace0] = makeEDKandTrace(0) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const child = keyRingFactory({ - async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[] */) { return material.setUnencryptedDataKey(unencryptedDataKey, keyringTrace0) }, onEncrypt: never @@ -297,10 +297,10 @@ describe('MultiKeyring: onDecrypt', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const unencryptedDataKey = new Uint8Array(suite.keyLengthBytes) const [edk0, keyringTrace0] = makeEDKandTrace(0) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const child = keyRingFactory({ - async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[], context?: EncryptionContext */) { + async onDecrypt (material: NodeDecryptionMaterial /*, encryptedDataKeys: EncryptedDataKey[] */) { return material.setUnencryptedDataKey(unencryptedDataKey, keyringTrace0) }, onEncrypt: never diff --git a/modules/raw-aes-keyring-browser/src/raw_aes_keyring_browser.ts b/modules/raw-aes-keyring-browser/src/raw_aes_keyring_browser.ts index cbaeaf3bc..70a37f6ae 100644 --- a/modules/raw-aes-keyring-browser/src/raw_aes_keyring_browser.ts +++ b/modules/raw-aes-keyring-browser/src/raw_aes_keyring_browser.ts @@ -23,7 +23,6 @@ import { immutableClass, readOnlyProperty, WebCryptoAlgorithmSuite, // eslint-disable-line no-unused-vars - EncryptionContext, // eslint-disable-line no-unused-vars getSubtleFunction, _importCryptoKey, importForWebCryptoEncryptionMaterial, @@ -78,25 +77,25 @@ export class RawAesKeyringWebCrypto extends KeyringWebCrypto { */ .setCryptoKey(masterKey, { keyNamespace, keyName, flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY }) - const _wrapKey = async (material: WebCryptoEncryptionMaterial, context?: EncryptionContext) => { + const _wrapKey = async (material: WebCryptoEncryptionMaterial) => { /* The AAD section is uInt16BE(length) + AAD * see: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-aad * However, the RAW Keyring wants _only_ the ADD. * So, I just slice off the length. */ - const aad = serializeEncryptionContext(context || {}).slice(2) + const aad = serializeEncryptionContext(material.encryptionContext).slice(2) const { keyNamespace, keyName } = this return aesGcmWrapKey(keyNamespace, keyName, material, aad, wrappingMaterial) } - const _unwrapKey = async (material: WebCryptoDecryptionMaterial, edk: EncryptedDataKey, context?: EncryptionContext) => { + const _unwrapKey = async (material: WebCryptoDecryptionMaterial, edk: EncryptedDataKey) => { /* The AAD section is uInt16BE(length) + AAD * see: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-aad * However, the RAW Keyring wants _only_ the ADD. * So, I just slice off the length. */ - const aad = serializeEncryptionContext(context || {}).slice(2) + const aad = serializeEncryptionContext(material.encryptionContext).slice(2) const { keyNamespace, keyName } = this return aesGcmUnwrapKey(keyNamespace, keyName, material, wrappingMaterial, edk, aad) @@ -114,8 +113,8 @@ export class RawAesKeyringWebCrypto extends KeyringWebCrypto { } _rawOnEncrypt = _onEncrypt(randomValuesOnly) - _onEncrypt = async (material: WebCryptoEncryptionMaterial, context?: EncryptionContext) => { - const _material = await this._rawOnEncrypt(material, context) + _onEncrypt = async (material: WebCryptoEncryptionMaterial) => { + const _material = await this._rawOnEncrypt(material) return importForWebCryptoEncryptionMaterial(_material) } diff --git a/modules/raw-aes-keyring-browser/test/raw_aes_keyring_browser.test.ts b/modules/raw-aes-keyring-browser/test/raw_aes_keyring_browser.test.ts index 85c93b5d6..41094baec 100644 --- a/modules/raw-aes-keyring-browser/test/raw_aes_keyring_browser.test.ts +++ b/modules/raw-aes-keyring-browser/test/raw_aes_keyring_browser.test.ts @@ -146,7 +146,7 @@ describe('RawAesKeyringWebCrypto encrypt/decrypt', () => { it('can encrypt and create unencrypted data key', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const test = await keyring.onEncrypt(material) expect(test.hasValidKey()).to.equal(true) const udk = test.getUnencryptedDataKey() @@ -159,7 +159,7 @@ describe('RawAesKeyringWebCrypto encrypt/decrypt', () => { it('can decrypt an EncryptedDataKey', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) const test = await keyring.onDecrypt(material, [encryptedDataKey]) expect(test.hasValidKey()).to.equal(true) // The UnencryptedDataKey should be zeroed, because the cryptoKey has been set diff --git a/modules/raw-aes-keyring-node/src/raw_aes_keyring_node.ts b/modules/raw-aes-keyring-node/src/raw_aes_keyring_node.ts index dd1d41950..50fcf4101 100644 --- a/modules/raw-aes-keyring-node/src/raw_aes_keyring_node.ts +++ b/modules/raw-aes-keyring-node/src/raw_aes_keyring_node.ts @@ -22,8 +22,7 @@ import { KeyringTraceFlag, immutableClass, readOnlyProperty, - NodeAlgorithmSuite, // eslint-disable-line no-unused-vars - EncryptionContext // eslint-disable-line no-unused-vars + NodeAlgorithmSuite // eslint-disable-line no-unused-vars } from '@aws-crypto/material-management-node' import { randomBytes, createCipheriv, createDecipheriv } from 'crypto' import { @@ -75,27 +74,27 @@ export class RawAesKeyringNode extends KeyringNode { */ .setUnencryptedDataKey(unencryptedMasterKey, { keyNamespace, keyName, flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY }) - const _wrapKey = async (material: NodeEncryptionMaterial, context?: EncryptionContext) => { + const _wrapKey = async (material: NodeEncryptionMaterial) => { /* The AAD section is uInt16BE(length) + AAD * see: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-aad * However, the RAW Keyring wants _only_ the ADD. * So, I just slice off the length. */ - const { buffer, byteOffset, byteLength } = serializeEncryptionContext(context || {}).slice(2) + const { buffer, byteOffset, byteLength } = serializeEncryptionContext(material.encryptionContext).slice(2) const aad = Buffer.from(buffer, byteOffset, byteLength) const { keyNamespace, keyName } = this return aesGcmWrapKey(keyNamespace, keyName, material, aad, wrappingMaterial) } - const _unwrapKey = async (material: NodeDecryptionMaterial, edk: EncryptedDataKey, context?: EncryptionContext) => { + const _unwrapKey = async (material: NodeDecryptionMaterial, edk: EncryptedDataKey) => { const { keyNamespace, keyName } = this /* The AAD section is uInt16BE(length) + AAD * see: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-aad * However, the RAW Keyring wants _only_ the ADD. * So, I just slice off the length. */ - const { buffer, byteOffset, byteLength } = serializeEncryptionContext(context || {}).slice(2) + const { buffer, byteOffset, byteLength } = serializeEncryptionContext(material.encryptionContext).slice(2) const aad = Buffer.from(buffer, byteOffset, byteLength) // const aad = Buffer.concat(encodeEncryptionContext(context || {})) diff --git a/modules/raw-aes-keyring-node/test/raw_aes_keyring_node.test.ts b/modules/raw-aes-keyring-node/test/raw_aes_keyring_node.test.ts index d00ed1beb..2c510e218 100644 --- a/modules/raw-aes-keyring-node/test/raw_aes_keyring_node.test.ts +++ b/modules/raw-aes-keyring-node/test/raw_aes_keyring_node.test.ts @@ -116,7 +116,7 @@ describe('RawAesKeyringNode encrypt/decrypt', () => { it('can encrypt and create unencrypted data key', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const test = await keyring.onEncrypt(material) expect(test.hasValidKey()).to.equal(true) const udk = test.getUnencryptedDataKey() @@ -129,7 +129,7 @@ describe('RawAesKeyringNode encrypt/decrypt', () => { it('can decrypt an EncryptedDataKey', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const test = await keyring.onDecrypt(material, [encryptedDataKey]) expect(test.hasValidKey()).to.equal(true) }) diff --git a/modules/raw-keyring/src/raw_aes_material.ts b/modules/raw-keyring/src/raw_aes_material.ts index 3ec2c1348..58088bba2 100644 --- a/modules/raw-keyring/src/raw_aes_material.ts +++ b/modules/raw-keyring/src/raw_aes_material.ts @@ -31,7 +31,8 @@ import { WebCryptoAlgorithmSuite, KeyringTrace, // eslint-disable-line no-unused-vars KeyringTraceFlag, - needs + needs, + EncryptionContext // eslint-disable-line no-unused-vars } from '@aws-crypto/material-management' import { @@ -48,6 +49,7 @@ export class NodeRawAesMaterial implements hasUnencryptedDataKey!: boolean unencryptedDataKeyLength!: number keyringTrace: KeyringTrace[] = [] + encryptionContext: EncryptionContext = Object.freeze({}) constructor (suiteId: WrappingSuiteIdentifier) { /* Precondition: NodeRawAesMaterial suiteId must be RawAesWrappingSuiteIdentifier. */ needs(RawAesWrappingSuiteIdentifier[suiteId], 'suiteId not supported.') @@ -81,6 +83,7 @@ export class WebCryptoRawAesMaterial implements getCryptoKey!: () => CryptoKey|MixedBackendCryptoKey hasCryptoKey!: boolean validUsages: ReadonlyArray + encryptionContext: EncryptionContext = Object.freeze({}) constructor (suiteId: WrappingSuiteIdentifier) { /* Precondition: WebCryptoAlgorithmSuite suiteId must be RawAesWrappingSuiteIdentifier. */ needs(RawAesWrappingSuiteIdentifier[suiteId], 'suiteId not supported.') diff --git a/modules/raw-keyring/src/raw_keyring_decorators.ts b/modules/raw-keyring/src/raw_keyring_decorators.ts index 06508fb5e..ad8a2c051 100644 --- a/modules/raw-keyring/src/raw_keyring_decorators.ts +++ b/modules/raw-keyring/src/raw_keyring_decorators.ts @@ -17,7 +17,6 @@ import { EncryptionMaterial, // eslint-disable-line no-unused-vars DecryptionMaterial, // eslint-disable-line no-unused-vars SupportedAlgorithmSuites, // eslint-disable-line no-unused-vars - EncryptionContext, // eslint-disable-line no-unused-vars KeyringTrace, // eslint-disable-line no-unused-vars KeyringTraceFlag, EncryptedDataKey // eslint-disable-line no-unused-vars @@ -36,8 +35,7 @@ export function _onEncrypt, - context?: EncryptionContext + material: EncryptionMaterial ): Promise> { if (!material.hasUnencryptedDataKey) { const trace: KeyringTrace = { @@ -48,7 +46,7 @@ export function _onEncrypt, - encryptedDataKeys: EncryptedDataKey[], - context?: EncryptionContext + encryptedDataKeys: EncryptedDataKey[] ): Promise> { /* Check for early return (Postcondition): If the material is already valid, attempting to decrypt is a bad idea. */ if (material.hasValidKey()) return material @@ -67,7 +64,7 @@ export function _onDecrypt { - (material: EncryptionMaterial, context?: EncryptionContext): Promise> + (material: EncryptionMaterial): Promise> } export interface UnwrapKey { - (material: DecryptionMaterial, edk: EncryptedDataKey, context?: EncryptionContext): Promise> + (material: DecryptionMaterial, edk: EncryptedDataKey): Promise> } export interface FilterEncryptedDataKey { diff --git a/modules/raw-keyring/test/raw_keyring_decorators.test.ts b/modules/raw-keyring/test/raw_keyring_decorators.test.ts index 3ce7e43bf..6a18ac048 100644 --- a/modules/raw-keyring/test/raw_keyring_decorators.test.ts +++ b/modules/raw-keyring/test/raw_keyring_decorators.test.ts @@ -23,7 +23,7 @@ import { AlgorithmSuiteIdentifier, NodeEncryptionMaterial, NodeAlgorithmSuite, K describe('_onEncrypt', () => { it('will create UnencryptedDataKey and call _wrapKey', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) let wrapCalled = 0 const notRandomBytes = async (bytes: number) => new Uint8Array(Array(bytes).fill(1)) const _wrapKey = (material: any) => { @@ -54,7 +54,7 @@ describe('_onEncrypt', () => { const udk = new Uint8Array(Array(suite.keyLengthBytes).fill(2)) const keyName = 'keyName' const keyNamespace = 'keyNamespace' - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) .setUnencryptedDataKey(udk, { keyName, keyNamespace, flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY }) let wrapCalled = 0 const notRandomBytes = async () => { throw new Error('never') } @@ -80,7 +80,7 @@ describe('_onDecrypt', () => { it('basic usage', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const udk = new Uint8Array(Array(suite.keyLengthBytes).fill(2)) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const keyName = 'keyName' const keyNamespace = 'keyNamespace' @@ -125,7 +125,7 @@ describe('_onDecrypt', () => { const udk = new Uint8Array(Array(suite.keyLengthBytes).fill(2)) const keyName = 'keyName' const keyNamespace = 'keyNamespace' - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) .setUnencryptedDataKey(udk, { keyName, keyNamespace, flags: KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY }) const edk = new EncryptedDataKey({ @@ -163,7 +163,7 @@ describe('_onDecrypt', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const keyName = 'keyName' const keyNamespace = 'keyNamespace' - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const edk = new EncryptedDataKey({ providerId: keyName, @@ -200,7 +200,7 @@ describe('_onDecrypt', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const keyName = 'keyName' const keyNamespace = 'keyNamespace' - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const edk = new EncryptedDataKey({ providerId: keyName, diff --git a/modules/raw-rsa-keyring-browser/src/raw_rsa_keyring_web_crypto.ts b/modules/raw-rsa-keyring-browser/src/raw_rsa_keyring_web_crypto.ts index 6ff402c13..943e97789 100644 --- a/modules/raw-rsa-keyring-browser/src/raw_rsa_keyring_web_crypto.ts +++ b/modules/raw-rsa-keyring-browser/src/raw_rsa_keyring_web_crypto.ts @@ -25,7 +25,6 @@ import { readOnlyProperty, bytes2JWK, keyUsageForMaterial, - EncryptionContext, // eslint-disable-line no-unused-vars importForWebCryptoEncryptionMaterial, MixedBackendCryptoKey, // eslint-disable-line no-unused-vars WebCryptoAlgorithmSuite // eslint-disable-line no-unused-vars @@ -157,8 +156,8 @@ export class RawRsaKeyringWebCrypto extends KeyringWebCrypto { } _rawOnEncrypt = _onEncrypt(randomValuesOnly) - _onEncrypt = async (material: WebCryptoEncryptionMaterial, context?: EncryptionContext) => { - const _material = await this._rawOnEncrypt(material, context) + _onEncrypt = async (material: WebCryptoEncryptionMaterial) => { + const _material = await this._rawOnEncrypt(material) return importForWebCryptoEncryptionMaterial(_material) } diff --git a/modules/raw-rsa-keyring-browser/test/raw_rsa_keyring_web_crypto.test.ts b/modules/raw-rsa-keyring-browser/test/raw_rsa_keyring_web_crypto.test.ts index bc3ccb801..57f4650b3 100644 --- a/modules/raw-rsa-keyring-browser/test/raw_rsa_keyring_web_crypto.test.ts +++ b/modules/raw-rsa-keyring-browser/test/raw_rsa_keyring_web_crypto.test.ts @@ -141,7 +141,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { it('can encrypt and create unencrypted data key', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) const test = await keyring.onEncrypt(material) expect(test.hasValidKey()).to.equal(true) const udk = test.getUnencryptedDataKey() @@ -154,7 +154,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { it('can decrypt an EncryptedDataKey', async () => { const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) const test = await keyring.onDecrypt(material, [encryptedDataKey]) expect(test.hasValidKey()).to.equal(true) // The UnencryptedDataKey should be zeroed, because the cryptoKey has been set @@ -166,7 +166,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { const keyring = new RawRsaKeyringWebCrypto({ privateKey, keyName, keyNamespace }) const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoEncryptionMaterial(suite) + const material = new WebCryptoEncryptionMaterial(suite, {}) expect(keyring.onEncrypt(material)).to.rejectedWith(Error) }) @@ -175,7 +175,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { const keyring = new RawRsaKeyringWebCrypto({ publicKey, keyName, keyNamespace }) const suite = new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new WebCryptoDecryptionMaterial(suite) + const material = new WebCryptoDecryptionMaterial(suite, {}) expect(keyring.onDecrypt(material, [encryptedDataKey])).to.rejectedWith(Error) }) }) diff --git a/modules/raw-rsa-keyring-node/test/raw_rsa_keyring_node.test.ts b/modules/raw-rsa-keyring-node/test/raw_rsa_keyring_node.test.ts index f87a5ed45..1e4bce61c 100644 --- a/modules/raw-rsa-keyring-node/test/raw_rsa_keyring_node.test.ts +++ b/modules/raw-rsa-keyring-node/test/raw_rsa_keyring_node.test.ts @@ -137,7 +137,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { it('can encrypt and create unencrypted data key', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) const test = await keyring.onEncrypt(material) expect(test.hasValidKey()).to.equal(true) const udk = test.getUnencryptedDataKey() @@ -150,7 +150,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { it('can decrypt an EncryptedDataKey', async () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) const test = await keyring.onDecrypt(material, [encryptedDataKey]) expect(test.hasValidKey()).to.equal(true) }) @@ -163,7 +163,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { }) const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeEncryptionMaterial(suite) + const material = new NodeEncryptionMaterial(suite, {}) expect(keyring.onEncrypt(material)).to.rejectedWith(Error) }) @@ -175,7 +175,7 @@ describe('RawRsaKeyringWebCrypto encrypt/decrypt', () => { }) const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256) - const material = new NodeDecryptionMaterial(suite) + const material = new NodeDecryptionMaterial(suite, {}) await keyring.onDecrypt(material, [encryptedDataKey]) expect(keyring.onDecrypt(material, [encryptedDataKey])).to.rejectedWith(Error) }) From dd2112854da5a5697f2da60ccae4fa78e98d2e4c Mon Sep 17 00:00:00 2001 From: seebees Date: Mon, 22 Jul 2019 15:42:53 -0700 Subject: [PATCH 02/10] Update modules/material-management/src/cryptographic_material.ts Co-Authored-By: Matt Bullock --- modules/material-management/src/cryptographic_material.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/material-management/src/cryptographic_material.ts b/modules/material-management/src/cryptographic_material.ts index c363b1bee..9a10f8b54 100644 --- a/modules/material-management/src/cryptographic_material.ts +++ b/modules/material-management/src/cryptographic_material.ts @@ -34,7 +34,7 @@ import { needs } from './needs' * be protected. The longer this data persists in memory the * greater the opportunity to be invalidated. Because * a Caching CMM exists is it important to insure that the - * unencrypted data key and it's meta data can not be manipulated, + * unencrypted data key and its meta data can not be manipulated, * and that the unencrypted data key can be zeroed when * it is no longer needed. */ From a9b625905382747cf93021ee84e8951014d16fe4 Mon Sep 17 00:00:00 2001 From: seebees Date: Mon, 22 Jul 2019 15:42:59 -0700 Subject: [PATCH 03/10] Update modules/material-management-node/src/node_cryptographic_materials_manager.ts Co-Authored-By: Matt Bullock --- .../src/node_cryptographic_materials_manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/material-management-node/src/node_cryptographic_materials_manager.ts b/modules/material-management-node/src/node_cryptographic_materials_manager.ts index a6574fe68..41cb48109 100644 --- a/modules/material-management-node/src/node_cryptographic_materials_manager.ts +++ b/modules/material-management-node/src/node_cryptographic_materials_manager.ts @@ -106,7 +106,7 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa if (!namedCurve) return new NodeDecryptionMaterial(suite, encryptionContext) /* Precondition: NodeDefaultCryptographicMaterialsManager If the algorithm suite specification requires a signatureCurve a context must exist. */ - if (!encryptionContext) throw new Error('Context does not contain required public key.') + if (!encryptionContext) throw new Error('Encryption context does not contain required public key.') const { [ENCODED_SIGNER_KEY]: compressPoint } = encryptionContext From 2d3d294ac0fb3a72147000f26cd94071fecd347b Mon Sep 17 00:00:00 2001 From: seebees Date: Mon, 22 Jul 2019 15:43:05 -0700 Subject: [PATCH 04/10] Update modules/material-management-browser/src/browser_cryptographic_materials_manager.ts Co-Authored-By: Matt Bullock --- .../src/browser_cryptographic_materials_manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts index 9eae4a07e..b83b7e715 100644 --- a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts +++ b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts @@ -105,7 +105,7 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM if (!namedCurve) return new WebCryptoDecryptionMaterial(suite, encryptionContext) /* Precondition: WebCryptoDefaultCryptographicMaterialsManager If the algorithm suite specification requires a signatureCurve a context must exist. */ - if (!encryptionContext) throw new Error('Context does not contain required public key.') + if (!encryptionContext) throw new Error('Encryption context does not contain required public key.') const { [ENCODED_SIGNER_KEY]: compressPoint } = encryptionContext From b4cca218e3e81f3dbcbd7243b652b387ff41bce9 Mon Sep 17 00:00:00 2001 From: seebees Date: Mon, 22 Jul 2019 16:11:45 -0700 Subject: [PATCH 05/10] change interface to return material,not nested material --- ...hing_cryptographic_materials_decorators.ts | 21 +++++++-------- .../src/cryptographic_materials_cache.ts | 14 +++++----- ...get_local_cryptographic_materials_cache.ts | 26 +++++++++---------- modules/decrypt-browser/src/decrypt.ts | 2 +- .../decrypt-node/src/parse_header_stream.ts | 2 +- modules/encrypt-browser/src/encrypt.ts | 2 +- modules/encrypt-node/src/encrypt_stream.ts | 2 +- ...browser_cryptographic_materials_manager.ts | 14 +++++----- ...er_cryptographic_materials_manager.test.ts | 6 ++--- .../node_cryptographic_materials_manager.ts | 14 +++++----- ...de_cryptographic_materials_manager.test.ts | 2 +- .../src/materials_manager.ts | 6 ++--- modules/material-management/src/types.ts | 8 ------ 13 files changed, 55 insertions(+), 64 deletions(-) diff --git a/modules/cache-material/src/caching_cryptographic_materials_decorators.ts b/modules/cache-material/src/caching_cryptographic_materials_decorators.ts index e4a7f48a7..e3875e304 100644 --- a/modules/cache-material/src/caching_cryptographic_materials_decorators.ts +++ b/modules/cache-material/src/caching_cryptographic_materials_decorators.ts @@ -16,10 +16,10 @@ import { GetEncryptionMaterials, // eslint-disable-line no-unused-vars GetDecryptMaterials, // eslint-disable-line no-unused-vars - DecryptionResponse, // eslint-disable-line no-unused-vars + DecryptionMaterial, // eslint-disable-line no-unused-vars SupportedAlgorithmSuites, // eslint-disable-line no-unused-vars EncryptionRequest, // eslint-disable-line no-unused-vars - EncryptionResponse, // eslint-disable-line no-unused-vars + EncryptionMaterial, // eslint-disable-line no-unused-vars MaterialsManager, // eslint-disable-line no-unused-vars DecryptionRequest, // eslint-disable-line no-unused-vars needs, @@ -69,7 +69,7 @@ export function getEncryptionMaterials ( return async function getEncryptionMaterials ( this: CachingMaterialsManager, request: EncryptionRequest - ): Promise> { + ): Promise> { const { suite, encryptionContext, frameLength, plaintextLength } = request /* Check for early return (Postcondition): If I can not cache the EncryptionResponse, do not even look. */ if ((suite && !suite.cacheSafe) || typeof plaintextLength !== 'number' || plaintextLength < 0) { @@ -95,7 +95,7 @@ export function getEncryptionMaterials ( .getEncryptionMaterials({ suite, encryptionContext, frameLength }) /* Check for early return (Postcondition): If I can not cache the EncryptionResponse, just return it. */ - if (!response.material.suite.cacheSafe) return response + if (!response.suite.cacheSafe) return response /* It is possible for an entry to exceed limits immediately. * The simplest case is to need to encrypt more than then maxBytesEncrypted. @@ -122,7 +122,7 @@ export function decryptMaterials ( return async function decryptMaterials ( this: CachingMaterialsManager, request: DecryptionRequest - ): Promise> { + ): Promise> { const { suite } = request /* Check for early return (Postcondition): If I can not cache the DecryptionResponse, do not even look. */ if (!suite.cacheSafe) { @@ -166,14 +166,13 @@ export function cacheEntryHasExceededLimits * Because when the Encryption SDK is done with material, it will zero it out. * Plucking off the material and cloning just that and then returning the rest of the response * can just be handled in one place. - * @param response EncryptionResponse|DecryptionResponse + * @param material EncryptionResponse|DecryptionResponse * @return EncryptionResponse|DecryptionResponse */ -function cloneResponse|DecryptionResponse> ( - response: R -): R { - const { material } = response - return { ...response, material: cloneMaterial(material) } +function cloneResponse|DecryptionMaterial> ( + material: M +): M { + return cloneMaterial(material) } export interface CachingMaterialsManagerInput extends Readonly<{ diff --git a/modules/cache-material/src/cryptographic_materials_cache.ts b/modules/cache-material/src/cryptographic_materials_cache.ts index 37d8b66d0..dddc7cce8 100644 --- a/modules/cache-material/src/cryptographic_materials_cache.ts +++ b/modules/cache-material/src/cryptographic_materials_cache.ts @@ -14,21 +14,21 @@ */ import { - EncryptionResponse, // eslint-disable-line no-unused-vars - DecryptionResponse, // eslint-disable-line no-unused-vars + EncryptionMaterial, // eslint-disable-line no-unused-vars + DecryptionMaterial, // eslint-disable-line no-unused-vars SupportedAlgorithmSuites // eslint-disable-line no-unused-vars } from '@aws-crypto/material-management' export interface CryptographicMaterialsCache { putEncryptionResponse( key: string, - response: EncryptionResponse, + response: EncryptionMaterial, plaintextLength: number, maxAge?: number ): void putDecryptionResponse( key: string, - response: DecryptionResponse, + response: DecryptionMaterial, maxAge?: number ): void getEncryptionResponse(key: string, plaintextLength: number): EncryptionResponseEntry|false @@ -37,16 +37,16 @@ export interface CryptographicMaterialsCache } export interface Entry { - readonly response: EncryptionResponse|DecryptionResponse + response: EncryptionMaterial|DecryptionMaterial bytesEncrypted: number messagesEncrypted: number readonly now: number } export interface EncryptionResponseEntry extends Entry { - readonly response: EncryptionResponse + readonly response: EncryptionMaterial } export interface DecryptionResponseEntry extends Entry { - readonly response: DecryptionResponse + readonly response: DecryptionMaterial } diff --git a/modules/cache-material/src/get_local_cryptographic_materials_cache.ts b/modules/cache-material/src/get_local_cryptographic_materials_cache.ts index ff818816d..0d74a63e5 100644 --- a/modules/cache-material/src/get_local_cryptographic_materials_cache.ts +++ b/modules/cache-material/src/get_local_cryptographic_materials_cache.ts @@ -15,8 +15,8 @@ import LRU from 'lru-cache' import { - EncryptionResponse, // eslint-disable-line no-unused-vars - DecryptionResponse, // eslint-disable-line no-unused-vars + EncryptionMaterial, // eslint-disable-line no-unused-vars + DecryptionMaterial, // eslint-disable-line no-unused-vars SupportedAlgorithmSuites, // eslint-disable-line no-unused-vars needs, isEncryptionMaterial, @@ -38,7 +38,7 @@ export function getLocalCryptographicMaterialsCache, + material: EncryptionMaterial, plaintextLength: number, maxAge?: number ) { /* Precondition: putEncryptionResponse plaintextLength can not be negative. */ needs(plaintextLength >= 0, 'Malformed plaintextLength') /* Precondition: Only cache EncryptionMaterial. */ - needs(isEncryptionMaterial(response.material), 'Malformed response.') + needs(isEncryptionMaterial(material), 'Malformed response.') /* Precondition: Only cache EncryptionMaterial that is cacheSafe. */ - needs(response.material.suite.cacheSafe, 'Can not cache non-cache safe material') + needs(material.suite.cacheSafe, 'Can not cache non-cache safe material') const entry = Object.seal({ - response: Object.freeze(response), + response: material, bytesEncrypted: plaintextLength, messagesEncrypted: 1, now: Date.now() @@ -94,15 +94,15 @@ export function getLocalCryptographicMaterialsCache, + material: DecryptionMaterial, maxAge?: number ) { /* Precondition: Only cache DecryptionMaterial. */ - needs(isDecryptionMaterial(response.material), 'Malformed response.') + needs(isDecryptionMaterial(material), 'Malformed response.') /* Precondition: Only cache DecryptionMaterial that is cacheSafe. */ - needs(response.material.suite.cacheSafe, 'Can not cache non-cache safe material') + needs(material.suite.cacheSafe, 'Can not cache non-cache safe material') const entry = Object.seal({ - response: Object.freeze(response), + response: material, bytesEncrypted: 0, messagesEncrypted: 0, now: Date.now() @@ -117,7 +117,7 @@ export function getLocalCryptographicMaterialsCache>entry }, diff --git a/modules/decrypt-browser/src/decrypt.ts b/modules/decrypt-browser/src/decrypt.ts index 1e90ef44a..0ea9883ba 100644 --- a/modules/decrypt-browser/src/decrypt.ts +++ b/modules/decrypt-browser/src/decrypt.ts @@ -59,7 +59,7 @@ export async function decrypt ( const { encryptionContext, encryptedDataKeys, suiteId, messageId } = messageHeader const suite = new WebCryptoAlgorithmSuite(suiteId) - const { material } = await cmm.decryptMaterials({ suite, encryptionContext, encryptedDataKeys }) + const material = await cmm.decryptMaterials({ suite, encryptionContext, encryptedDataKeys }) const { kdfGetSubtleDecrypt, subtleVerify, dispose } = await getDecryptionHelper(material) const info = kdfInfo(suiteId, messageId) const getSubtleDecrypt = kdfGetSubtleDecrypt(info) diff --git a/modules/decrypt-node/src/parse_header_stream.ts b/modules/decrypt-node/src/parse_header_stream.ts index 6087f13ab..4785e80a1 100644 --- a/modules/decrypt-node/src/parse_header_stream.ts +++ b/modules/decrypt-node/src/parse_header_stream.ts @@ -86,7 +86,7 @@ export class ParseHeaderStream extends PortableTransformWithType { this.materialsManager .decryptMaterials({ suite, encryptionContext, encryptedDataKeys }) - .then(({ material }) => { + .then((material) => { this._headerState.buffer = Buffer.alloc(0) // clear the Buffer... const { kdfGetDecipher, getVerify, dispose } = getDecryptionHelper(material) diff --git a/modules/encrypt-browser/src/encrypt.ts b/modules/encrypt-browser/src/encrypt.ts index b0a8c6a9d..02b3b63bd 100644 --- a/modules/encrypt-browser/src/encrypt.ts +++ b/modules/encrypt-browser/src/encrypt.ts @@ -84,7 +84,7 @@ export async function encrypt ( plaintextLength } - const { material } = await cmm.getEncryptionMaterials(encryptionRequest) + const material = await cmm.getEncryptionMaterials(encryptionRequest) const { kdfGetSubtleEncrypt, subtleSign, dispose } = await getEncryptHelper(material) const messageId = await backend.randomValues(MESSAGE_ID_LENGTH) diff --git a/modules/encrypt-node/src/encrypt_stream.ts b/modules/encrypt-node/src/encrypt_stream.ts index 00c8fca97..aadb83523 100644 --- a/modules/encrypt-node/src/encrypt_stream.ts +++ b/modules/encrypt-node/src/encrypt_stream.ts @@ -71,7 +71,7 @@ export function encryptStream ( const wrappingStream = new Duplexify() cmm.getEncryptionMaterials({ suite, encryptionContext, frameLength }) - .then(async ({ material }) => { + .then(async (material) => { const { dispose, getSigner } = getEncryptHelper(material) const { getCipher, messageHeader, rawHeader } = getEncryptionInfo(material, frameLength) diff --git a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts index b83b7e715..72f7cdfd5 100644 --- a/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts +++ b/modules/material-management-browser/src/browser_cryptographic_materials_manager.ts @@ -16,7 +16,7 @@ import { WebCryptoMaterialsManager, EncryptionRequest, // eslint-disable-line no-unused-vars DecryptionRequest, EncryptionContext, // eslint-disable-line no-unused-vars - EncryptionResponse, DecryptionResponse, // eslint-disable-line no-unused-vars + EncryptionMaterial, DecryptionMaterial, // eslint-disable-line no-unused-vars WebCryptoAlgorithmSuite, WebCryptoEncryptionMaterial, WebCryptoDecryptionMaterial, SignatureKey, needs, readOnlyProperty, VerificationKey, AlgorithmSuiteIdentifier, immutableBaseClass, @@ -29,8 +29,8 @@ import { fromBase64, toBase64 } from '@aws-sdk/util-base64-browser' export type WebCryptoEncryptionRequest = EncryptionRequest export type WebCryptoDecryptionRequest = DecryptionRequest -export type WebCryptoEncryptionResponse = EncryptionResponse -export type WebCryptoDecryptionResponse = DecryptionResponse +export type WebCryptoEncryptionMaterial = EncryptionMaterial +export type WebCryptoDecryptionMaterial = DecryptionMaterial export type WebCryptoGetEncryptionMaterials = GetEncryptionMaterials export type WebCryptoGetDecryptMaterials = GetDecryptMaterials @@ -46,7 +46,7 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM needs(keyring instanceof KeyringWebCrypto, 'Unsupported type.') readOnlyProperty(this, 'keyring', keyring) } - async getEncryptionMaterials ({ suite, encryptionContext }: WebCryptoEncryptionRequest): Promise { + async getEncryptionMaterials ({ suite, encryptionContext }: WebCryptoEncryptionRequest): Promise { suite = suite || new WebCryptoAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) const material = await this @@ -59,10 +59,10 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM /* Postcondition: The WebCryptoEncryptionMaterial must contain at least 1 EncryptedDataKey. */ needs(material.encryptedDataKeys.length, 'No EncryptedDataKeys: the ciphertext can never be decrypted.') - return { material } + return material } - async decryptMaterials ({ suite, encryptedDataKeys, encryptionContext }: WebCryptoDecryptionRequest): Promise { + async decryptMaterials ({ suite, encryptedDataKeys, encryptionContext }: WebCryptoDecryptionRequest): Promise { const material = await this .keyring .onDecrypt(await this._initializeDecryptionMaterial(suite, encryptionContext), encryptedDataKeys.slice()) @@ -70,7 +70,7 @@ export class WebCryptoDefaultCryptographicMaterialsManager implements WebCryptoM /* Postcondition: The WebCryptoDecryptionMaterial must contain a valid dataKey. */ needs(material.hasValidKey(), 'Unencrypted data key is invalid.') - return { material } + return material } async _initializeEncryptionMaterial (suite: WebCryptoAlgorithmSuite, encryptionContext: EncryptionContext) { diff --git a/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts b/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts index d5527a936..89506633d 100644 --- a/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts +++ b/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts @@ -203,7 +203,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { some: 'context' } - const { material } = await cmm.getEncryptionMaterials({ suite, encryptionContext }) + const material = await cmm.getEncryptionMaterials({ suite, encryptionContext }) expect(Object.keys(material.encryptionContext)).lengthOf(2) if (!material.signatureKey) throw new Error('I should never see this error') expect(material.encryptionContext).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(material.signatureKey.compressPoint)) @@ -233,7 +233,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { some: 'context' } - const { material } = await cmm.getEncryptionMaterials({ encryptionContext }) + const material = await cmm.getEncryptionMaterials({ encryptionContext }) expect(Object.keys(material.encryptionContext)).lengthOf(2) if (!material.signatureKey) throw new Error('I should never see this error') expect(material.encryptionContext).to.have.haveOwnProperty(ENCODED_SIGNER_KEY).and.to.equal(toBase64(material.signatureKey.compressPoint)) @@ -309,7 +309,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { const encryptionContext = { some: 'context', [ENCODED_SIGNER_KEY]: 'A29gmBT/NscB90u6npOulZQwAAiKVtoShudOm2J2sCgC' } const edk = new EncryptedDataKey({ providerId: ' keyNamespace', providerInfo: 'keyName', encryptedDataKey: new Uint8Array(5) }) - const { material } = await cmm.decryptMaterials({ suite, encryptionContext, encryptedDataKeys: [edk] }) + const material = await cmm.decryptMaterials({ suite, encryptionContext, encryptedDataKeys: [edk] }) if (!material.verificationKey) throw new Error('I should never see this error') expect(material.encryptionContext).to.deep.equal(encryptionContext) expect(material.verificationKey.signatureCurve).to.equal(suite.signatureCurve) diff --git a/modules/material-management-node/src/node_cryptographic_materials_manager.ts b/modules/material-management-node/src/node_cryptographic_materials_manager.ts index 41cb48109..bc9bbe384 100644 --- a/modules/material-management-node/src/node_cryptographic_materials_manager.ts +++ b/modules/material-management-node/src/node_cryptographic_materials_manager.ts @@ -15,7 +15,7 @@ import { NodeMaterialsManager, EncryptionRequest, DecryptionRequest, EncryptionContext, // eslint-disable-line no-unused-vars - EncryptionResponse, DecryptionResponse, // eslint-disable-line no-unused-vars + EncryptionMaterial, DecryptionMaterial, // eslint-disable-line no-unused-vars NodeAlgorithmSuite, NodeEncryptionMaterial, NodeDecryptionMaterial, SignatureKey, needs, VerificationKey, AlgorithmSuiteIdentifier, immutableClass, readOnlyProperty, KeyringNode, @@ -28,8 +28,8 @@ import { createECDH } from 'crypto' export type NodeEncryptionRequest = EncryptionRequest export type NodeDecryptionRequest = DecryptionRequest -export type NodeEncryptionResponse = EncryptionResponse -export type NodeDecryptionResponse = DecryptionResponse +export type NodeEncryptionMaterial = EncryptionMaterial +export type NodeDecryptionMaterial = DecryptionMaterial export type NodeGetEncryptionMaterials = GetEncryptionMaterials export type NodeGetDecryptMaterials = GetDecryptMaterials @@ -46,7 +46,7 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa readOnlyProperty(this, 'keyring', keyring) } - async getEncryptionMaterials ({ suite, encryptionContext }: NodeEncryptionRequest): Promise { + async getEncryptionMaterials ({ suite, encryptionContext }: NodeEncryptionRequest): Promise { suite = suite || new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384) const material = await this @@ -59,10 +59,10 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa /* Postcondition: The NodeEncryptionMaterial must contain at least 1 EncryptedDataKey. */ needs(material.encryptedDataKeys.length, 'No EncryptedDataKeys: the ciphertext can never be decrypted.') - return { material } + return material } - async decryptMaterials ({ suite, encryptedDataKeys, encryptionContext }: NodeDecryptionRequest): Promise { + async decryptMaterials ({ suite, encryptedDataKeys, encryptionContext }: NodeDecryptionRequest): Promise { const material = await this .keyring .onDecrypt(this._initializeDecryptionMaterial(suite, encryptionContext), encryptedDataKeys.slice()) @@ -73,7 +73,7 @@ export class NodeDefaultCryptographicMaterialsManager implements NodeMaterialsMa */ needs(material.getUnencryptedDataKey(), 'Unencrypted data key is invalid.') - return { material } + return material } _initializeEncryptionMaterial (suite: NodeAlgorithmSuite, encryptionContext: EncryptionContext) { diff --git a/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts b/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts index 79aeceb4c..172f2f79d 100644 --- a/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts +++ b/modules/material-management-node/test/node_cryptographic_materials_manager.test.ts @@ -258,7 +258,7 @@ describe('NodeDefaultCryptographicMaterialsManager', () => { providerId: 'p', providerInfo: 'p', encryptedDataKey: new Uint8Array(5) })] - const { material } = await cmm.decryptMaterials({ suite, encryptedDataKeys, encryptionContext: {} }) + const material = await cmm.decryptMaterials({ suite, encryptedDataKeys, encryptionContext: {} }) expect(material.hasUnencryptedDataKey).to.equal(true) }) }) diff --git a/modules/material-management/src/materials_manager.ts b/modules/material-management/src/materials_manager.ts index fc022873f..284715f31 100644 --- a/modules/material-management/src/materials_manager.ts +++ b/modules/material-management/src/materials_manager.ts @@ -14,7 +14,7 @@ */ import { EncryptionRequest, DecryptionRequest } from '.' // eslint-disable-line no-unused-vars -import { EncryptionResponse, DecryptionResponse, SupportedAlgorithmSuites } from './types' // eslint-disable-line no-unused-vars +import { EncryptionMaterial, DecryptionMaterial, SupportedAlgorithmSuites } from './types' // eslint-disable-line no-unused-vars import { NodeAlgorithmSuite } from './node_algorithms' // eslint-disable-line no-unused-vars import { WebCryptoAlgorithmSuite } from './web_crypto_algorithms' // eslint-disable-line no-unused-vars @@ -26,11 +26,11 @@ import { WebCryptoAlgorithmSuite } from './web_crypto_algorithms' // eslint-disa */ export interface GetEncryptionMaterials { - (request: EncryptionRequest): Promise> + (request: EncryptionRequest): Promise> } export interface GetDecryptMaterials { - (request: DecryptionRequest): Promise> + (request: DecryptionRequest): Promise> } export interface MaterialsManager { diff --git a/modules/material-management/src/types.ts b/modules/material-management/src/types.ts index 64ec0965f..db58db1e8 100644 --- a/modules/material-management/src/types.ts +++ b/modules/material-management/src/types.ts @@ -49,20 +49,12 @@ export interface EncryptionRequest { - material: EncryptionMaterial -} - export interface DecryptionRequest { readonly suite: S readonly encryptionContext: EncryptionContext readonly encryptedDataKeys: ReadonlyArray } -export interface DecryptionResponse { - material: DecryptionMaterial -} - export type SupportedAlgorithmSuites = NodeAlgorithmSuite|WebCryptoAlgorithmSuite export type EncryptionMaterial = From 3468cb5b10d174ff69b9311a80a4ed6a1f1694bd Mon Sep 17 00:00:00 2001 From: seebees Date: Mon, 22 Jul 2019 16:37:27 -0700 Subject: [PATCH 06/10] test pass --- ...hing_cryptographic_materials_decorators.ts | 16 ++--- ...cryptographic_materials_decorators.test.ts | 28 +++----- ...ocal_cryptographic_materials_cache.test.ts | 64 +++++-------------- ...er_cryptographic_materials_manager.test.ts | 6 +- 4 files changed, 35 insertions(+), 79 deletions(-) diff --git a/modules/cache-material/src/caching_cryptographic_materials_decorators.ts b/modules/cache-material/src/caching_cryptographic_materials_decorators.ts index e3875e304..572be2e05 100644 --- a/modules/cache-material/src/caching_cryptographic_materials_decorators.ts +++ b/modules/cache-material/src/caching_cryptographic_materials_decorators.ts @@ -87,7 +87,7 @@ export function getEncryptionMaterials ( this._cache.del(cacheKey) } - const response = await this + const material = await this ._backingMaterialsManager /* Strip any information about the plaintext from the backing request, * because the resulting response may be used to encrypt multiple plaintexts. @@ -95,7 +95,7 @@ export function getEncryptionMaterials ( .getEncryptionMaterials({ suite, encryptionContext, frameLength }) /* Check for early return (Postcondition): If I can not cache the EncryptionResponse, just return it. */ - if (!response.suite.cacheSafe) return response + if (!material.suite.cacheSafe) return material /* It is possible for an entry to exceed limits immediately. * The simplest case is to need to encrypt more than then maxBytesEncrypted. @@ -103,16 +103,16 @@ export function getEncryptionMaterials ( * but do not put a know invalid item into the cache. */ const testEntry = { - response, + response: material, now: Date.now(), messagesEncrypted: 1, bytesEncrypted: plaintextLength } if (!this._cacheEntryHasExceededLimits(testEntry)) { - this._cache.putEncryptionResponse(cacheKey, response, plaintextLength, this._maxAge) + this._cache.putEncryptionResponse(cacheKey, material, plaintextLength, this._maxAge) } - return cloneResponse(response) + return cloneResponse(material) } } @@ -140,12 +140,12 @@ export function decryptMaterials ( this._cache.del(cacheKey) } - const response = await this + const material = await this ._backingMaterialsManager .decryptMaterials(request) - this._cache.putDecryptionResponse(cacheKey, response, this._maxAge) - return cloneResponse(response) + this._cache.putDecryptionResponse(cacheKey, material, this._maxAge) + return cloneResponse(material) } } diff --git a/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts b/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts index 80170c064..abcfbc379 100644 --- a/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts +++ b/modules/cache-material/test/caching_cryptographic_materials_decorators.test.ts @@ -216,14 +216,6 @@ describe('Cryptographic Material Functions', () => { .setUnencryptedDataKey(udk128, trace) const context = {} - const encryptionResponse = { - material: encryptionMaterial, - context - } - const decryptionResponse = { - material: decryptionMaterial, - context - } const _maxAge = 10 const _maxBytesEncrypted = 10 @@ -231,10 +223,10 @@ describe('Cryptographic Material Functions', () => { const _cache = getLocalCryptographicMaterialsCache(100) const _backingMaterialsManager = { getEncryptionMaterials () { - return encryptionResponse + return encryptionMaterial }, decryptMaterials () { - return decryptionResponse + return decryptionMaterial } } as any const _partition = 'partition' @@ -268,11 +260,9 @@ describe('Cryptographic Material Functions', () => { plaintextLength: 10 }) // The response must be cloned... i.e. not the same. - expect(test === encryptionResponse).to.equal(false) - // the material must be cloned... because after use it will be zeroed - expect(test.material === encryptionResponse.material).to.equal(false) - expect(test.context === encryptionResponse.context).to.equal(true) - expect(test.material.getUnencryptedDataKey()).to.deep.equal(encryptionMaterial.getUnencryptedDataKey()) + expect(test === encryptionMaterial).to.equal(false) + expect(test.encryptionContext).to.deep.equal(encryptionMaterial.encryptionContext) + expect(test.getUnencryptedDataKey()).to.deep.equal(encryptionMaterial.getUnencryptedDataKey()) }) }) @@ -284,11 +274,9 @@ describe('Cryptographic Material Functions', () => { encryptedDataKeys: [edk1] }) // The response must be cloned... i.e. not the same. - expect(test === decryptionResponse).to.equal(false) - // the material must be cloned... because after use it will be zeroed - expect(test.material === decryptionResponse.material).to.equal(false) - expect(test.context === decryptionResponse.context).to.equal(true) - expect(test.material.getUnencryptedDataKey()).to.deep.equal(decryptionMaterial.getUnencryptedDataKey()) + expect(test === decryptionMaterial).to.equal(false) + expect(test.encryptionContext).to.deep.equal(decryptionMaterial.encryptionContext) + expect(test.getUnencryptedDataKey()).to.deep.equal(decryptionMaterial.getUnencryptedDataKey()) }) }) }) diff --git a/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts b/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts index 8a1a5a3a4..ebf2547a9 100644 --- a/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts +++ b/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts @@ -40,9 +40,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('putEncryptionResponse', () => { const key = 'some encryption key' - const response: any = { - material: encryptionMaterial - } + const response: any = encryptionMaterial putEncryptionResponse(key, response, 1) const test = getEncryptionResponse(key, 1) @@ -54,9 +52,7 @@ describe('getLocalCryptographicMaterialsCache', () => { }) it('Precondition: putEncryptionResponse plaintextLength can not be negative.', () => { - const response: any = { - material: encryptionMaterial - } + const response: any = encryptionMaterial const u: any = undefined const s: any = 'not-number' const n = -1 @@ -67,9 +63,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Postcondition: Only return EncryptionMaterial.', () => { const key = 'some decryption key' - const response: any = { - material: decryptionMaterial - } + const response: any = decryptionMaterial putDecryptionResponse(key, response) expect(() => getEncryptionResponse(key, 1)).to.throw() @@ -78,18 +72,14 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Precondition: Only cache EncryptionMaterial that is cacheSafe.', () => { const key = 'some encryption key' const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const response: any = { - material: new NodeEncryptionMaterial(suite, {}) - } + const response: any = new NodeEncryptionMaterial(suite, {}) expect(() => putEncryptionResponse(key, response, 1)).to.throw() }) it('putDecryptionResponse', () => { const key = 'some decryption key' - const response: any = { - material: decryptionMaterial - } + const response: any = decryptionMaterial putDecryptionResponse(key, response) const test = getDecryptionResponse(key) @@ -102,9 +92,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Precondition: Only cache DecryptionMaterial.', () => { const key = 'some decryption key' - const response: any = { - material: 'not material' - } + const response: any = 'not material' expect(() => putDecryptionResponse(key, response)).to.throw() }) @@ -112,9 +100,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Precondition: Only cache DecryptionMaterial that is cacheSafe.', () => { const key = 'some decryption key' const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) - const response: any = { - material: new NodeEncryptionMaterial(suite, {}) - } + const response: any = new NodeEncryptionMaterial(suite, {}) expect(() => putDecryptionResponse(key, response)).to.throw() }) @@ -135,9 +121,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Precondition: Only cache EncryptionMaterial.', () => { const key = 'some encryption key' - const response: any = { - material: 'not material' - } + const response: any = 'not material' expect(() => putEncryptionResponse(key, response, 1)).to.throw() }) @@ -149,9 +133,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('Postcondition: Only return DecryptionMaterial.', () => { const key = 'some encryption key' - const response: any = { - material: encryptionMaterial - } + const response: any = encryptionMaterial putEncryptionResponse(key, response, 1) expect(() => getDecryptionResponse(key)) @@ -163,9 +145,7 @@ describe('getLocalCryptographicMaterialsCache', () => { it('zero is an acceptable plaintextLength', () => { const key = 'some encryption key' - const response: any = { - material: encryptionMaterial - } + const response: any = encryptionMaterial putEncryptionResponse(key, response, 0) const test = getEncryptionResponse(key, 0) @@ -186,9 +166,7 @@ describe('cache eviction', () => { const key1 = 'key lost' const key2 = 'key replace' - const response: any = { - material: decryptionMaterial - } + const response: any = decryptionMaterial putDecryptionResponse(key1, response) putDecryptionResponse(key2, response) @@ -206,9 +184,7 @@ describe('cache eviction', () => { } = getLocalCryptographicMaterialsCache(1) const key = 'key deleted' - const response: any = { - material: decryptionMaterial - } + const response: any = decryptionMaterial putDecryptionResponse(key, response) del(key) @@ -223,9 +199,7 @@ describe('cache eviction', () => { } = getLocalCryptographicMaterialsCache(1, 10) const key = 'key lost' - const response: any = { - material: decryptionMaterial - } + const response: any = decryptionMaterial putDecryptionResponse(key, response, 1) await new Promise(resolve => setTimeout(resolve, 20)) @@ -241,9 +215,7 @@ describe('cache eviction', () => { const key1 = 'key lost' const key2 = 'key replace' - const response: any = { - material: encryptionMaterial - } + const response: any = encryptionMaterial putEncryptionResponse(key1, response, 0) putEncryptionResponse(key2, response, 0) @@ -261,9 +233,7 @@ describe('cache eviction', () => { } = getLocalCryptographicMaterialsCache(1, 10) const key = 'key lost' - const response: any = { - material: encryptionMaterial - } + const response: any = encryptionMaterial putEncryptionResponse(key, response, 1, 1) del(key) @@ -278,9 +248,7 @@ describe('cache eviction', () => { } = getLocalCryptographicMaterialsCache(1, 10) const key = 'key lost' - const response: any = { - material: encryptionMaterial - } + const response: any = encryptionMaterial putEncryptionResponse(key, response, 1, 1) await new Promise(resolve => setTimeout(resolve, 20)) diff --git a/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts b/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts index 89506633d..d450f557b 100644 --- a/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts +++ b/modules/material-management-browser/test/browser_cryptographic_materials_manager.test.ts @@ -103,7 +103,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { expect(encryptionContext).to.have.haveOwnProperty('some').and.to.equal('context') }) - it('set a verificationKey from context', async () => { + it('set a verificationKey from encryption context', async () => { class TestKeyring extends KeyringWebCrypto { async _onEncrypt (): Promise { throw new Error('I should never see this error') @@ -179,7 +179,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { expect(cmm._initializeDecryptionMaterial(suite, context)).to.rejectedWith(Error) }) - it('can return an encryption response', async () => { + it('can return a encryption material', async () => { class TestKeyring extends KeyringWebCrypto { async _onEncrypt (material: WebCryptoEncryptionMaterial): Promise { const udk = synchronousRandomValues(suite.keyLengthBytes) @@ -288,7 +288,7 @@ describe('WebCryptoDefaultCryptographicMaterialsManager', () => { expect(cmm.getEncryptionMaterials({ encryptionContext })).to.rejectedWith(Error) }) - it('can return a decryption response', async () => { + it('can return decryption material', async () => { class TestKeyring extends KeyringWebCrypto { async _onEncrypt (): Promise { throw new Error('I should never see this error') From 9d3283e03eec150ead970b325786182efd1b6e90 Mon Sep 17 00:00:00 2001 From: seebees Date: Mon, 22 Jul 2019 16:40:33 -0700 Subject: [PATCH 07/10] no .context --- ...tographic_materials_cache_key_helpers.test.ts | 2 +- modules/cache-material/test/fixtures.ts | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts b/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts index dc888f4a8..2a0aaf4d3 100644 --- a/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts +++ b/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts @@ -38,7 +38,7 @@ const { describe('buildCryptographicMaterialsCacheKeyHelpers::encryptionContextHash', () => { for (const vector of encryptionContextVectors) { it(`${vector.name}`, async () => { - const test = await encryptionContextHash(vector.context) + const test = await encryptionContextHash(vector.encryptionContext) expect(test).to.deep.equal(vector.hash) }) } diff --git a/modules/cache-material/test/fixtures.ts b/modules/cache-material/test/fixtures.ts index ba71aeed8..d7c8cd808 100644 --- a/modules/cache-material/test/fixtures.ts +++ b/modules/cache-material/test/fixtures.ts @@ -20,13 +20,13 @@ import { EncryptedDataKey, AlgorithmSuiteIdentifier } from '@aws-crypto/material const partitionName = 'c15b9079-6d0e-42b6-8784-5e804b025692' const encryptionContextEmpty = { name: 'encryptionContextEmpty', - context: {}, + encryptionContext: {}, hash: new Uint8Array([ 207, 131, 225, 53, 126, 239, 184, 189, 241, 84, 40, 80, 214, 109, 128, 7, 214, 32, 228, 5, 11, 87, 21, 220, 131, 244, 169, 33, 211, 108, 233, 206, 71, 208, 209, 60, 93, 133, 242, 176, 255, 131, 24, 210, 135, 126, 236, 47, 99, 185, 49, 189, 71, 65, 122, 129, 165, 56, 50, 122, 249, 39, 218, 62 ]) } const encryptionContextFull = { name: 'encryptionContextFull', - context: { 'this': 'is', 'a': 'non-empty', 'encryption': 'context' }, + encryptionContext: { 'this': 'is', 'a': 'non-empty', 'encryption': 'context' }, hash: new Uint8Array([ 4, 250, 62, 217, 137, 103, 44, 245, 231, 15, 24, 164, 62, 35, 99, 8, 4, 29, 75, 147, 51, 243, 111, 68, 2, 126, 189, 113, 20, 150, 243, 92, 188, 56, 128, 79, 167, 9, 114, 93, 83, 189, 146, 168, 7, 189, 229, 174, 231, 68, 184, 217, 66, 18, 60, 223, 54, 127, 13, 7, 230, 79, 129, 73 ]) } @@ -60,7 +60,7 @@ export const encryptCacheKeyVectors: VectorHack[] = [ partitionName, { suite: undefined, - encryptionContext: encryptionContextEmpty.context + encryptionContext: encryptionContextEmpty.encryptionContext } ], id: 'rkrFAso1YyPbOJbmwVMjrPw+wwLJT7xusn8tA8zMe9e3+OqbtfDueB7bvoKLU3fsmdUvZ6eMt7mBp1ThMMB25Q==' @@ -70,7 +70,7 @@ export const encryptCacheKeyVectors: VectorHack[] = [ partitionName, { suite: { id: AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 }, - encryptionContext: encryptionContextEmpty.context + encryptionContext: encryptionContextEmpty.encryptionContext } ], id: '3icBIkLK4V3fVwbm3zSxUdUQV6ZvZYUOLl8buN36g6gDMqAkghcGryxX7QiVABkW1JhB6GRp5z+bzbiuciBcKQ==' @@ -80,7 +80,7 @@ export const encryptCacheKeyVectors: VectorHack[] = [ partitionName, { suite: undefined, - encryptionContext: encryptionContextFull.context + encryptionContext: encryptionContextFull.encryptionContext } ], id: 'IHiUHYOUVUEFTc3BcZPJDlsWct2Qy1A7JdfQl9sQoV/ILIbRpoz9q7RtGd/MlibaGl5ihE66cN8ygM8A5rtYbg==' @@ -90,7 +90,7 @@ export const encryptCacheKeyVectors: VectorHack[] = [ partitionName, { suite: { id: AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 }, - encryptionContext: encryptionContextFull.context + encryptionContext: encryptionContextFull.encryptionContext } ], id: 'mRNK7qhTb/kJiiyGPgAevp0gwFRcET4KeeNYwZHhoEDvSUzQiDgl8Of+YRDaVzKxAqpNBgcAuFXde9JlaRRsmw==' @@ -104,7 +104,7 @@ export const decryptCacheKeyVectors: VectorHack[] = [ { suite: { id: AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16_HKDF_SHA256 }, encryptedDataKeys: [encryptedDataKey1.edk], - encryptionContext: encryptionContextEmpty.context + encryptionContext: encryptionContextEmpty.encryptionContext } ], id: 'n0zVzk9QIVxhz6ET+aJIKKOJNxtpGtSe1yAbu7WU5l272Iw/jmhlER4psDHJs9Mr8KYiIvLGSXzggNDCc23+9w==' @@ -115,7 +115,7 @@ export const decryptCacheKeyVectors: VectorHack[] = [ { suite: { id: AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 }, encryptedDataKeys: [encryptedDataKey1.edk, encryptedDataKey2.edk], - encryptionContext: encryptionContextFull.context + encryptionContext: encryptionContextFull.encryptionContext } ], id: '+rtwUe38CGnczGmYu12iqGWHIyDyZ44EvYQ4S6ACmsgS8VaEpiw0RTGpDk6Z/7YYN/jVHOAcNKDyCNP8EmstFg==' From d8220e376e60b89872d104211131887143c869be Mon Sep 17 00:00:00 2001 From: seebees Date: Mon, 22 Jul 2019 16:44:30 -0700 Subject: [PATCH 08/10] even better name --- ...yptographic_materials_cache_key_helpers.ts | 12 +- ...hing_cryptographic_materials_decorators.ts | 30 ++--- .../src/cryptographic_materials_cache.ts | 12 +- ...get_local_cryptographic_materials_cache.ts | 18 +-- ...raphic_materials_cache_key_helpers.test.ts | 12 +- ...ocal_cryptographic_materials_cache.test.ts | 126 +++++++++--------- 6 files changed, 105 insertions(+), 105 deletions(-) diff --git a/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts b/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts index 9351a0a88..e2b1d37e1 100644 --- a/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts +++ b/modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts @@ -37,13 +37,13 @@ export function buildCryptographicMaterialsCacheKeyHelpers ) { @@ -59,7 +59,7 @@ export function buildCryptographicMaterialsCacheKeyHelpers ) { @@ -96,11 +96,11 @@ export function buildCryptographicMaterialsCacheKeyHelpers { - buildEncryptionResponseCacheKey( + buildEncryptionMaterialCacheKey( partition: string, { suite, encryptionContext }: EncryptionRequest ): Promise - buildDecryptionResponseCacheKey( + buildDecryptionMaterialCacheKey( partition: string, { suite, encryptedDataKeys, encryptionContext }: DecryptionRequest ): Promise diff --git a/modules/cache-material/src/caching_cryptographic_materials_decorators.ts b/modules/cache-material/src/caching_cryptographic_materials_decorators.ts index 572be2e05..501cb6a7a 100644 --- a/modules/cache-material/src/caching_cryptographic_materials_decorators.ts +++ b/modules/cache-material/src/caching_cryptographic_materials_decorators.ts @@ -64,23 +64,23 @@ export function decorateProperties ( } export function getEncryptionMaterials ( - { buildEncryptionResponseCacheKey }: CryptographicMaterialsCacheKeyHelpersInterface + { buildEncryptionMaterialCacheKey }: CryptographicMaterialsCacheKeyHelpersInterface ): GetEncryptionMaterials { return async function getEncryptionMaterials ( this: CachingMaterialsManager, request: EncryptionRequest ): Promise> { const { suite, encryptionContext, frameLength, plaintextLength } = request - /* Check for early return (Postcondition): If I can not cache the EncryptionResponse, do not even look. */ + /* Check for early return (Postcondition): If I can not cache the EncryptionMaterial, do not even look. */ if ((suite && !suite.cacheSafe) || typeof plaintextLength !== 'number' || plaintextLength < 0) { return this ._backingMaterialsManager .getEncryptionMaterials(request) } - const cacheKey = await buildEncryptionResponseCacheKey(this._partition, { suite, encryptionContext }) - const entry = this._cache.getEncryptionResponse(cacheKey, plaintextLength) - /* Check for early return (Postcondition): If I have a valid EncryptionResponse, return it. */ + const cacheKey = await buildEncryptionMaterialCacheKey(this._partition, { suite, encryptionContext }) + const entry = this._cache.getEncryptionMaterial(cacheKey, plaintextLength) + /* Check for early return (Postcondition): If I have a valid EncryptionMaterial, return it. */ if (entry && !this._cacheEntryHasExceededLimits(entry)) { return cloneResponse(entry.response) } else { @@ -94,7 +94,7 @@ export function getEncryptionMaterials ( */ .getEncryptionMaterials({ suite, encryptionContext, frameLength }) - /* Check for early return (Postcondition): If I can not cache the EncryptionResponse, just return it. */ + /* Check for early return (Postcondition): If I can not cache the EncryptionMaterial, just return it. */ if (!material.suite.cacheSafe) return material /* It is possible for an entry to exceed limits immediately. @@ -109,7 +109,7 @@ export function getEncryptionMaterials ( bytesEncrypted: plaintextLength } if (!this._cacheEntryHasExceededLimits(testEntry)) { - this._cache.putEncryptionResponse(cacheKey, material, plaintextLength, this._maxAge) + this._cache.putEncryptionMaterial(cacheKey, material, plaintextLength, this._maxAge) } return cloneResponse(material) @@ -117,23 +117,23 @@ export function getEncryptionMaterials ( } export function decryptMaterials ( - { buildDecryptionResponseCacheKey }: CryptographicMaterialsCacheKeyHelpersInterface + { buildDecryptionMaterialCacheKey }: CryptographicMaterialsCacheKeyHelpersInterface ): GetDecryptMaterials { return async function decryptMaterials ( this: CachingMaterialsManager, request: DecryptionRequest ): Promise> { const { suite } = request - /* Check for early return (Postcondition): If I can not cache the DecryptionResponse, do not even look. */ + /* Check for early return (Postcondition): If I can not cache the DecryptionMaterial, do not even look. */ if (!suite.cacheSafe) { return this ._backingMaterialsManager .decryptMaterials(request) } - const cacheKey = await buildDecryptionResponseCacheKey(this._partition, request) - const entry = this._cache.getDecryptionResponse(cacheKey) - /* Check for early return (Postcondition): If I have a valid DecryptionResponse, return it. */ + const cacheKey = await buildDecryptionMaterialCacheKey(this._partition, request) + const entry = this._cache.getDecryptionMaterial(cacheKey) + /* Check for early return (Postcondition): If I have a valid DecryptionMaterial, return it. */ if (entry && !this._cacheEntryHasExceededLimits(entry)) { return cloneResponse(entry.response) } else { @@ -144,7 +144,7 @@ export function decryptMaterials ( ._backingMaterialsManager .decryptMaterials(request) - this._cache.putDecryptionResponse(cacheKey, material, this._maxAge) + this._cache.putDecryptionMaterial(cacheKey, material, this._maxAge) return cloneResponse(material) } } @@ -166,8 +166,8 @@ export function cacheEntryHasExceededLimits * Because when the Encryption SDK is done with material, it will zero it out. * Plucking off the material and cloning just that and then returning the rest of the response * can just be handled in one place. - * @param material EncryptionResponse|DecryptionResponse - * @return EncryptionResponse|DecryptionResponse + * @param material EncryptionMaterial|DecryptionMaterial + * @return EncryptionMaterial|DecryptionMaterial */ function cloneResponse|DecryptionMaterial> ( material: M diff --git a/modules/cache-material/src/cryptographic_materials_cache.ts b/modules/cache-material/src/cryptographic_materials_cache.ts index dddc7cce8..58eb29c54 100644 --- a/modules/cache-material/src/cryptographic_materials_cache.ts +++ b/modules/cache-material/src/cryptographic_materials_cache.ts @@ -20,19 +20,19 @@ import { } from '@aws-crypto/material-management' export interface CryptographicMaterialsCache { - putEncryptionResponse( + putEncryptionMaterial( key: string, response: EncryptionMaterial, plaintextLength: number, maxAge?: number ): void - putDecryptionResponse( + putDecryptionMaterial( key: string, response: DecryptionMaterial, maxAge?: number ): void - getEncryptionResponse(key: string, plaintextLength: number): EncryptionResponseEntry|false - getDecryptionResponse(key: string): DecryptionResponseEntry|false + getEncryptionMaterial(key: string, plaintextLength: number): EncryptionMaterialEntry|false + getDecryptionMaterial(key: string): DecryptionMaterialEntry|false del(key: string): void } @@ -43,10 +43,10 @@ export interface Entry { readonly now: number } -export interface EncryptionResponseEntry extends Entry { +export interface EncryptionMaterialEntry extends Entry { readonly response: EncryptionMaterial } -export interface DecryptionResponseEntry extends Entry { +export interface DecryptionMaterialEntry extends Entry { readonly response: DecryptionMaterial } diff --git a/modules/cache-material/src/get_local_cryptographic_materials_cache.ts b/modules/cache-material/src/get_local_cryptographic_materials_cache.ts index 0d74a63e5..d2dff1bb0 100644 --- a/modules/cache-material/src/get_local_cryptographic_materials_cache.ts +++ b/modules/cache-material/src/get_local_cryptographic_materials_cache.ts @@ -26,8 +26,8 @@ import { import { CryptographicMaterialsCache, // eslint-disable-line no-unused-vars Entry, // eslint-disable-line no-unused-vars - EncryptionResponseEntry, // eslint-disable-line no-unused-vars - DecryptionResponseEntry // eslint-disable-line no-unused-vars + EncryptionMaterialEntry, // eslint-disable-line no-unused-vars + DecryptionMaterialEntry // eslint-disable-line no-unused-vars } from './cryptographic_materials_cache' export function getLocalCryptographicMaterialsCache ( @@ -71,13 +71,13 @@ export function getLocalCryptographicMaterialsCache, plaintextLength: number, maxAge?: number ) { - /* Precondition: putEncryptionResponse plaintextLength can not be negative. */ + /* Precondition: putEncryptionMaterial plaintextLength can not be negative. */ needs(plaintextLength >= 0, 'Malformed plaintextLength') /* Precondition: Only cache EncryptionMaterial. */ needs(isEncryptionMaterial(material), 'Malformed response.') @@ -92,7 +92,7 @@ export function getLocalCryptographicMaterialsCache, maxAge?: number @@ -110,7 +110,7 @@ export function getLocalCryptographicMaterialsCache= 0, 'Malformed plaintextLength') const entry = cache.get(key) @@ -122,16 +122,16 @@ export function getLocalCryptographicMaterialsCache>entry + return >entry }, - getDecryptionResponse (key: string) { + getDecryptionMaterial (key: string) { const entry = cache.get(key) /* Check for early return (Postcondition): If this key does not have a DecryptionMaterial, return false. */ if (!entry) return false /* Postcondition: Only return DecryptionMaterial. */ needs(isDecryptionMaterial(entry.response), 'Malformed response.') - return >entry + return >entry }, del (key: string) { cache.del(key) diff --git a/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts b/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts index 2a0aaf4d3..5037087a0 100644 --- a/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts +++ b/modules/cache-material/test/build_cryptographic_materials_cache_key_helpers.test.ts @@ -31,8 +31,8 @@ const sha512 = async (...data: (Uint8Array|string)[]) => data const { encryptionContextHash, encryptedDataKeysHash, - buildEncryptionResponseCacheKey, - buildDecryptionResponseCacheKey + buildEncryptionMaterialCacheKey, + buildDecryptionMaterialCacheKey } = buildCryptographicMaterialsCacheKeyHelpers(fromUtf8, toUtf8, sha512) describe('buildCryptographicMaterialsCacheKeyHelpers::encryptionContextHash', () => { @@ -54,19 +54,19 @@ describe('buildCryptographicMaterialsCacheKeyHelpers::encryptedDataKeysHash', () } }) -describe('buildCryptographicMaterialsCacheKeyHelpers::buildEncryptionResponseCacheKey', () => { +describe('buildCryptographicMaterialsCacheKeyHelpers::buildEncryptionMaterialCacheKey', () => { for (const vector of encryptCacheKeyVectors) { it(`${vector.id}`, async () => { - const test = await buildEncryptionResponseCacheKey(...vector.arguments) + const test = await buildEncryptionMaterialCacheKey(...vector.arguments) expect(test).to.equal(Buffer.from(vector.id, 'base64').toString()) }) } }) -describe('buildCryptographicMaterialsCacheKeyHelpers::buildEncryptionResponseCacheKey', () => { +describe('buildCryptographicMaterialsCacheKeyHelpers::buildEncryptionMaterialCacheKey', () => { for (const vector of decryptCacheKeyVectors) { it(`${vector.id}`, async () => { - const test = await buildDecryptionResponseCacheKey(...vector.arguments) + const test = await buildDecryptionMaterialCacheKey(...vector.arguments) expect(test).to.equal(Buffer.from(vector.id, 'base64').toString()) }) } diff --git a/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts b/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts index ebf2547a9..fec9c60bd 100644 --- a/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts +++ b/modules/cache-material/test/get_local_cryptographic_materials_cache.test.ts @@ -31,19 +31,19 @@ const decryptionMaterial = new NodeDecryptionMaterial(nodeSuite, {}) describe('getLocalCryptographicMaterialsCache', () => { const { - getEncryptionResponse, - getDecryptionResponse, + getEncryptionMaterial, + getDecryptionMaterial, del, - putEncryptionResponse, - putDecryptionResponse + putEncryptionMaterial, + putDecryptionMaterial } = getLocalCryptographicMaterialsCache(100) - it('putEncryptionResponse', () => { + it('putEncryptionMaterial', () => { const key = 'some encryption key' const response: any = encryptionMaterial - putEncryptionResponse(key, response, 1) - const test = getEncryptionResponse(key, 1) + putEncryptionMaterial(key, response, 1) + const test = getEncryptionMaterial(key, 1) if (!test) throw new Error('never') expect(test.bytesEncrypted).to.equal(2) expect(test.messagesEncrypted).to.equal(2) @@ -51,22 +51,22 @@ describe('getLocalCryptographicMaterialsCache', () => { expect(Object.isFrozen(test.response)).to.equal(true) }) - it('Precondition: putEncryptionResponse plaintextLength can not be negative.', () => { + it('Precondition: putEncryptionMaterial plaintextLength can not be negative.', () => { const response: any = encryptionMaterial const u: any = undefined const s: any = 'not-number' const n = -1 - expect(() => putEncryptionResponse('key', response, u)).to.throw() - expect(() => putEncryptionResponse('key', response, s)).to.throw() - expect(() => putEncryptionResponse('key', response, n)).to.throw() + expect(() => putEncryptionMaterial('key', response, u)).to.throw() + expect(() => putEncryptionMaterial('key', response, s)).to.throw() + expect(() => putEncryptionMaterial('key', response, n)).to.throw() }) it('Postcondition: Only return EncryptionMaterial.', () => { const key = 'some decryption key' const response: any = decryptionMaterial - putDecryptionResponse(key, response) - expect(() => getEncryptionResponse(key, 1)).to.throw() + putDecryptionMaterial(key, response) + expect(() => getEncryptionMaterial(key, 1)).to.throw() }) it('Precondition: Only cache EncryptionMaterial that is cacheSafe.', () => { @@ -74,15 +74,15 @@ describe('getLocalCryptographicMaterialsCache', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const response: any = new NodeEncryptionMaterial(suite, {}) - expect(() => putEncryptionResponse(key, response, 1)).to.throw() + expect(() => putEncryptionMaterial(key, response, 1)).to.throw() }) - it('putDecryptionResponse', () => { + it('putDecryptionMaterial', () => { const key = 'some decryption key' const response: any = decryptionMaterial - putDecryptionResponse(key, response) - const test = getDecryptionResponse(key) + putDecryptionMaterial(key, response) + const test = getDecryptionMaterial(key) if (!test) throw new Error('never') expect(test.bytesEncrypted).to.equal(0) expect(test.messagesEncrypted).to.equal(0) @@ -94,7 +94,7 @@ describe('getLocalCryptographicMaterialsCache', () => { const key = 'some decryption key' const response: any = 'not material' - expect(() => putDecryptionResponse(key, response)).to.throw() + expect(() => putDecryptionMaterial(key, response)).to.throw() }) it('Precondition: Only cache DecryptionMaterial that is cacheSafe.', () => { @@ -102,20 +102,20 @@ describe('getLocalCryptographicMaterialsCache', () => { const suite = new NodeAlgorithmSuite(AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16) const response: any = new NodeEncryptionMaterial(suite, {}) - expect(() => putDecryptionResponse(key, response)).to.throw() + expect(() => putDecryptionMaterial(key, response)).to.throw() }) it('Precondition: plaintextLength can not be negative.', () => { const u: any = undefined const s: any = 'not-number' const n = -1 - expect(() => getEncryptionResponse('key', u)).to.throw() - expect(() => getEncryptionResponse('key', s)).to.throw() - expect(() => getEncryptionResponse('key', n)).to.throw() + expect(() => getEncryptionMaterial('key', u)).to.throw() + expect(() => getEncryptionMaterial('key', s)).to.throw() + expect(() => getEncryptionMaterial('key', n)).to.throw() }) it('Check for early return (Postcondition): If this key does not have an EncryptionMaterial, return false.', () => { - const test = getEncryptionResponse('does-not-exist', 1) + const test = getEncryptionMaterial('does-not-exist', 1) expect(test).to.equal(false) }) @@ -123,11 +123,11 @@ describe('getLocalCryptographicMaterialsCache', () => { const key = 'some encryption key' const response: any = 'not material' - expect(() => putEncryptionResponse(key, response, 1)).to.throw() + expect(() => putEncryptionMaterial(key, response, 1)).to.throw() }) it('Check for early return (Postcondition): If this key does not have a DecryptionMaterial, return false.', () => { - const test = getDecryptionResponse('does-not-exist') + const test = getDecryptionMaterial('does-not-exist') expect(test).to.equal(false) }) @@ -135,8 +135,8 @@ describe('getLocalCryptographicMaterialsCache', () => { const key = 'some encryption key' const response: any = encryptionMaterial - putEncryptionResponse(key, response, 1) - expect(() => getDecryptionResponse(key)) + putEncryptionMaterial(key, response, 1) + expect(() => getDecryptionMaterial(key)) }) it('delete non-existent key', () => { @@ -147,8 +147,8 @@ describe('getLocalCryptographicMaterialsCache', () => { const key = 'some encryption key' const response: any = encryptionMaterial - putEncryptionResponse(key, response, 0) - const test = getEncryptionResponse(key, 0) + putEncryptionMaterial(key, response, 0) + const test = getEncryptionMaterial(key, 0) if (!test) throw new Error('never') expect(test.bytesEncrypted).to.equal(0) expect(test.messagesEncrypted).to.equal(2) @@ -158,101 +158,101 @@ describe('getLocalCryptographicMaterialsCache', () => { }) describe('cache eviction', () => { - it('putDecryptionResponse can exceed maxSize', () => { + it('putDecryptionMaterial can exceed maxSize', () => { const { - getDecryptionResponse, - putDecryptionResponse + getDecryptionMaterial, + putDecryptionMaterial } = getLocalCryptographicMaterialsCache(1) const key1 = 'key lost' const key2 = 'key replace' const response: any = decryptionMaterial - putDecryptionResponse(key1, response) - putDecryptionResponse(key2, response) - const lost = getDecryptionResponse(key1) - const found = getDecryptionResponse(key2) + putDecryptionMaterial(key1, response) + putDecryptionMaterial(key2, response) + const lost = getDecryptionMaterial(key1) + const found = getDecryptionMaterial(key2) expect(lost).to.equal(false) expect(found).to.not.equal(false) }) - it('putDecryptionResponse can be deleted', () => { + it('putDecryptionMaterial can be deleted', () => { const { - getDecryptionResponse, - putDecryptionResponse, + getDecryptionMaterial, + putDecryptionMaterial, del } = getLocalCryptographicMaterialsCache(1) const key = 'key deleted' const response: any = decryptionMaterial - putDecryptionResponse(key, response) + putDecryptionMaterial(key, response) del(key) - const lost = getDecryptionResponse(key) + const lost = getDecryptionMaterial(key) expect(lost).to.equal(false) }) - it('putDecryptionResponse can be garbage collected', async () => { + it('putDecryptionMaterial can be garbage collected', async () => { const { - getDecryptionResponse, - putDecryptionResponse + getDecryptionMaterial, + putDecryptionMaterial } = getLocalCryptographicMaterialsCache(1, 10) const key = 'key lost' const response: any = decryptionMaterial - putDecryptionResponse(key, response, 1) + putDecryptionMaterial(key, response, 1) await new Promise(resolve => setTimeout(resolve, 20)) - const lost = getDecryptionResponse(key) + const lost = getDecryptionMaterial(key) expect(lost).to.equal(false) }) - it('putEncryptionResponse can exceed maxSize', () => { + it('putEncryptionMaterial can exceed maxSize', () => { const { - getEncryptionResponse, - putEncryptionResponse + getEncryptionMaterial, + putEncryptionMaterial } = getLocalCryptographicMaterialsCache(1) const key1 = 'key lost' const key2 = 'key replace' const response: any = encryptionMaterial - putEncryptionResponse(key1, response, 0) - putEncryptionResponse(key2, response, 0) - const lost = getEncryptionResponse(key1, 0) - const found = getEncryptionResponse(key2, 0) + putEncryptionMaterial(key1, response, 0) + putEncryptionMaterial(key2, response, 0) + const lost = getEncryptionMaterial(key1, 0) + const found = getEncryptionMaterial(key2, 0) expect(lost).to.equal(false) expect(found).to.not.equal(false) }) - it('putEncryptionResponse can be deleted', async () => { + it('putEncryptionMaterial can be deleted', async () => { const { - getEncryptionResponse, - putEncryptionResponse, + getEncryptionMaterial, + putEncryptionMaterial, del } = getLocalCryptographicMaterialsCache(1, 10) const key = 'key lost' const response: any = encryptionMaterial - putEncryptionResponse(key, response, 1, 1) + putEncryptionMaterial(key, response, 1, 1) del(key) - const lost = getEncryptionResponse(key, 1) + const lost = getEncryptionMaterial(key, 1) expect(lost).to.equal(false) }) - it('putEncryptionResponse can be garbage collected', async () => { + it('putEncryptionMaterial can be garbage collected', async () => { const { - getEncryptionResponse, - putEncryptionResponse + getEncryptionMaterial, + putEncryptionMaterial } = getLocalCryptographicMaterialsCache(1, 10) const key = 'key lost' const response: any = encryptionMaterial - putEncryptionResponse(key, response, 1, 1) + putEncryptionMaterial(key, response, 1, 1) await new Promise(resolve => setTimeout(resolve, 20)) - const lost = getEncryptionResponse(key, 1) + const lost = getEncryptionMaterial(key, 1) expect(lost).to.equal(false) }) }) From 1acb20b711afce00700a14121872ca74564cb817 Mon Sep 17 00:00:00 2001 From: seebees Date: Wed, 24 Jul 2019 11:25:42 -0700 Subject: [PATCH 09/10] insure is not a word --- modules/material-management/src/cryptographic_material.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/material-management/src/cryptographic_material.ts b/modules/material-management/src/cryptographic_material.ts index 9a10f8b54..4bb2cb527 100644 --- a/modules/material-management/src/cryptographic_material.ts +++ b/modules/material-management/src/cryptographic_material.ts @@ -33,7 +33,7 @@ import { needs } from './needs' * The functional data key (unencrypted or CryptoKey) is the most sensitive data and needs to * be protected. The longer this data persists in memory the * greater the opportunity to be invalidated. Because - * a Caching CMM exists is it important to insure that the + * a Caching CMM exists is it important to ensure that the * unencrypted data key and its meta data can not be manipulated, * and that the unencrypted data key can be zeroed when * it is no longer needed. From 47afaf2b0ef6c4eb22e690acc7e754f285a22281 Mon Sep 17 00:00:00 2001 From: seebees Date: Wed, 24 Jul 2019 11:27:51 -0700 Subject: [PATCH 10/10] more --- modules/material-management/src/cryptographic_material.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/material-management/src/cryptographic_material.ts b/modules/material-management/src/cryptographic_material.ts index 4bb2cb527..3ed6faaa5 100644 --- a/modules/material-management/src/cryptographic_material.ts +++ b/modules/material-management/src/cryptographic_material.ts @@ -33,7 +33,7 @@ import { needs } from './needs' * The functional data key (unencrypted or CryptoKey) is the most sensitive data and needs to * be protected. The longer this data persists in memory the * greater the opportunity to be invalidated. Because - * a Caching CMM exists is it important to ensure that the + * a Caching CMM exists it is important to ensure that the * unencrypted data key and its meta data can not be manipulated, * and that the unencrypted data key can be zeroed when * it is no longer needed.