diff --git a/modules/integration-node/src/decrypt_materials_manager_node.ts b/modules/integration-node/src/decrypt_materials_manager_node.ts index 42eadd969..334838f0b 100644 --- a/modules/integration-node/src/decrypt_materials_manager_node.ts +++ b/modules/integration-node/src/decrypt_materials_manager_node.ts @@ -49,7 +49,7 @@ export function decryptMaterialsManagerNode (keyInfos: KeyInfoTuple[]) { return new MultiKeyringNode({ children }) } -function keyringNode ([ info, key ]: KeyInfoTuple) { +export function keyringNode ([ info, key ]: KeyInfoTuple) { if (info.type === 'aws-kms' && key.type === 'aws-kms') { return kmsKeyring(info, key) } @@ -62,12 +62,12 @@ function keyringNode ([ info, key ]: KeyInfoTuple) { throw new Error('Unsupported keyring type') } -function kmsKeyring (_keyInfo: KmsKeyInfo, key: KMSKey) { +export function kmsKeyring (_keyInfo: KmsKeyInfo, key: KMSKey) { const generatorKeyId = key['key-id'] return new KmsKeyringNode({ generatorKeyId }) } -function aesKeyring (keyInfo:AesKeyInfo, key: AESKey) { +export function aesKeyring (keyInfo:AesKeyInfo, key: AESKey) { const keyName = key['key-id'] const keyNamespace = keyInfo['provider-id'] const { encoding, material } = key @@ -76,7 +76,7 @@ function aesKeyring (keyInfo:AesKeyInfo, key: AESKey) { return new RawAesKeyringNode({ keyName, keyNamespace, unencryptedMasterKey, wrappingSuite }) } -function rsaKeyring (keyInfo: RsaKeyInfo, key: RSAKey) { +export function rsaKeyring (keyInfo: RsaKeyInfo, key: RSAKey) { const keyName = key['key-id'] const keyNamespace = keyInfo['provider-id'] const rsaKey = key.type === 'private' @@ -86,7 +86,7 @@ function rsaKeyring (keyInfo: RsaKeyInfo, key: RSAKey) { return new RawRsaKeyringNode({ keyName, keyNamespace, rsaKey, padding }) } -function rsaPadding (keyInfo: RsaKeyInfo) { +export function rsaPadding (keyInfo: RsaKeyInfo) { const paddingAlgorithm = keyInfo['padding-algorithm'] const paddingHash = keyInfo['padding-hash'] diff --git a/modules/integration-node/src/get_decrypt_test_iterator.ts b/modules/integration-node/src/get_decrypt_test_iterator.ts index 33a2a699f..b0e242c28 100644 --- a/modules/integration-node/src/get_decrypt_test_iterator.ts +++ b/modules/integration-node/src/get_decrypt_test_iterator.ts @@ -13,7 +13,10 @@ * limitations under the License. */ -import { Open } from 'unzipper' +import { + Open, + File // eslint-disable-line no-unused-vars +} from 'unzipper' import { DecryptManifestList, // eslint-disable-line no-unused-vars KeyList, // eslint-disable-line no-unused-vars @@ -26,6 +29,11 @@ export async function getDecryptTestVectorIterator (vectorFile: string) { // @ts-ignore const filesMap = new Map(centralDirectory.files.map(file => [file.path, file])) + return _getDecryptTestVectorIterator(filesMap) +} + +/* Just a simple more testable function */ +export async function _getDecryptTestVectorIterator (filesMap: Map) { const readUriOnce = (() => { const cache: Map = new Map() return async (uri: string) => { @@ -49,7 +57,7 @@ export async function getDecryptTestVectorIterator (vectorFile: string) { const { plaintext: plaintextFile, ciphertext, 'master-keys': masterKeys } = testInfo const plainTextInfo = filesMap.get(testUri2Path(plaintextFile)) const cipherInfo = filesMap.get(testUri2Path(ciphertext)) - if (!cipherInfo || !plainTextInfo) throw new Error(`no file for ${name}: ${ciphertext} | ${plaintextFile}`) + if (!cipherInfo || !plainTextInfo) throw new Error(`no file for ${name}: ${testUri2Path(ciphertext)} | ${testUri2Path(plaintextFile)}`) const cipherStream = cipherInfo.stream() const plainTextStream = plainTextInfo.stream() const keysInfo = masterKeys.map(keyInfo => { diff --git a/modules/integration-node/src/get_encrypt_test_iterator.ts b/modules/integration-node/src/get_encrypt_test_iterator.ts index ca9ee7217..637ac2797 100644 --- a/modules/integration-node/src/get_encrypt_test_iterator.ts +++ b/modules/integration-node/src/get_encrypt_test_iterator.ts @@ -28,9 +28,16 @@ import { readFileSync } from 'fs' import got from 'got' export async function getEncryptTestVectorIterator (manifestFile: string, keyFile: string) { - const { tests, plaintexts }: EncryptManifestList = await getParsedJSON(manifestFile) - const { keys }: KeyList = await getParsedJSON(keyFile) + const [manifest, keys]: [EncryptManifestList, KeyList] = await Promise.all([ + getParsedJSON(manifestFile), + getParsedJSON(keyFile) + ]) + return _getEncryptTestVectorIterator(manifest, keys) +} + +/* Just a simple more testable function */ +export function _getEncryptTestVectorIterator ({ tests, plaintexts }: EncryptManifestList, { keys }: KeyList) { const plaintextBytes: {[name: string]: Buffer} = {} Object diff --git a/modules/integration-node/src/types.ts b/modules/integration-node/src/types.ts index d2e3f7346..755a9da8e 100644 --- a/modules/integration-node/src/types.ts +++ b/modules/integration-node/src/types.ts @@ -24,7 +24,6 @@ export interface DecryptManifestList { export interface EncryptManifestList { manifest: EncryptManifest - client: Client keys: string plaintexts: {[name: string]: number} tests: {[testName: string]: EncryptTest} @@ -68,7 +67,7 @@ interface RawKeyInfo extends KeyInfo { export interface RsaKeyInfo extends RawKeyInfo { 'encryption-algorithm': 'rsa', 'padding-algorithm': 'pkcs1'|'oaep-mgf1' - 'padding-hash': 'sha1'|'sha256'|'sha384'|'sha512' + 'padding-hash'?: 'sha1'|'sha256'|'sha384'|'sha512' } export interface AesKeyInfo extends RawKeyInfo { diff --git a/modules/integration-node/test/decrypt_materials_manager_node.test.ts b/modules/integration-node/test/decrypt_materials_manager_node.test.ts new file mode 100644 index 000000000..19bcafe1f --- /dev/null +++ b/modules/integration-node/test/decrypt_materials_manager_node.test.ts @@ -0,0 +1,103 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use + * this file except in compliance with the License. A copy of the License is + * located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-env mocha */ + +import { expect } from 'chai' +import 'mocha' +import { + kmsKeyring, + aesKeyring, + rsaKeyring, + keyringNode +} from '../src/index' +import { KMSKey, KmsKeyInfo, AESKey, AesKeyInfo, RSAKey, RsaKeyInfo } from '../src/types' // eslint-disable-line no-unused-vars + +const kmsKey: KMSKey = { + 'encrypt': true, + 'decrypt': true, + 'type': 'aws-kms', + 'key-id': 'arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f' +} +const kmsInfo: KmsKeyInfo = { + 'type': 'aws-kms', + 'key': 'us-west-2-decryptable' +} +const aesKey: AESKey = { + 'encrypt': true, + 'decrypt': true, + 'algorithm': 'aes', + 'type': 'symmetric', + 'bits': 128, + 'encoding': 'base64', + 'material': 'AAECAwQFBgcICRAREhMUFQ==', + 'key-id': 'aes-128' +} +const aesInfo: AesKeyInfo = { + 'type': 'raw', + 'key': 'aes-128', + 'provider-id': 'aws-raw-vectors-persistant', + 'encryption-algorithm': 'aes', + 'padding-algorithm': null +} +const rsaKey: RSAKey = { + 'encrypt': true, + 'decrypt': true, + 'algorithm': 'rsa', + 'type': 'private', + 'bits': 4096, + 'encoding': 'pem', + 'material': '-----BEGIN PRIVATE KEY-----\n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\ndzxtGxpeTBi+KhKlca8SlCdCqYwG6Q==\n-----END PRIVATE KEY-----', + 'key-id': 'rsa-4096-private' +} +const rsaInfo: RsaKeyInfo = { + 'type': 'raw', + 'key': 'rsa-4096-private', + 'provider-id': 'aws-raw-vectors-persistant', + 'encryption-algorithm': 'rsa', + 'padding-algorithm': 'pkcs1' +} + +describe('how to build keyrings', () => { + it('kmsKeyring', () => { + const test = kmsKeyring(kmsInfo, kmsKey) + expect(test.generatorKeyId).to.equal(kmsKey['key-id']) + }) + + it('aesKeyring', () => { + const test = aesKeyring(aesInfo, aesKey) + expect(test.keyName).to.equal(aesInfo.key) + }) + + it('rsaKeyring', () => { + const test = rsaKeyring(rsaInfo, rsaKey) + expect(test.keyName).to.equal(rsaInfo.key) + }) + + it('keyringNode: kmsKeyring', () => { + const test: any = keyringNode([kmsInfo, kmsKey]) + expect(test.generatorKeyId).to.equal(kmsKey['key-id']) + }) + + it('keyringNode: aesKeyring', () => { + const test: any = keyringNode([aesInfo, aesKey]) + expect(test.keyName).to.equal(aesInfo.key) + }) + + it('keyringNode: rsaKeyring', () => { + const test: any = keyringNode([rsaInfo, rsaKey]) + expect(test.keyName).to.equal(rsaInfo.key) + }) +}) diff --git a/modules/integration-node/test/get_decrypt_test_iterator.test.ts b/modules/integration-node/test/get_decrypt_test_iterator.test.ts new file mode 100644 index 000000000..f8787ebcf --- /dev/null +++ b/modules/integration-node/test/get_decrypt_test_iterator.test.ts @@ -0,0 +1,102 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use + * this file except in compliance with the License. A copy of the License is + * located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-env mocha */ + +import { expect } from 'chai' +import 'mocha' +import { + _getDecryptTestVectorIterator +} from '../src/index' +import { DecryptManifestList, KeyList } from '../src/types' // eslint-disable-line no-unused-vars + +const keyList: KeyList = { + 'manifest': { + 'type': 'keys', + 'version': 3 + }, + 'keys': { + 'us-west-2-decryptable': { + 'type': 'aws-kms', + 'key-id': 'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt', + 'encrypt': true, + 'decrypt': true + } + } +} + +const manifest:DecryptManifestList = { + 'manifest': { + 'type': 'awses-decrypt', + 'version': 1 + }, + 'client': { + 'name': 'aws/aws-encryption-sdk-python', + 'version': '1.3.8' + }, + 'keys': 'file://keys.json', + 'tests': { + 'c17b05d0-915e-44cc-98a3-cc29b71aa42b': { + 'plaintext': 'file://plaintexts/small', + 'ciphertext': 'file://ciphertexts/460bd892-c137-4178-8201-4ab5ee5d3041', + 'master-keys': [ + { + 'type': 'aws-kms', + 'key': 'us-west-2-decryptable' + } + ] + } + } +} + +const filesMap = new Map([ + [ + 'manifest.json', { + async buffer () { + return Buffer.from(JSON.stringify(manifest)) + } + } as any + ], + [ + 'keys.json', { + async buffer () { + return Buffer.from(JSON.stringify(keyList)) + } + } as any + ], + [ + 'ciphertexts/460bd892-c137-4178-8201-4ab5ee5d3041', { + stream () { + return {} as any + } + } as any + ], + [ + 'plaintexts/small', { + stream () { + return {} as any + } + } as any + ] +]) + +describe('_getDecryptTestVectorIterator', () => { + it('returns a iterator that has a test', async () => { + const testIterator = await _getDecryptTestVectorIterator(filesMap) + const test = testIterator.next() + expect(test.done).to.equal(false) + expect(test.value.name).to.equal('c17b05d0-915e-44cc-98a3-cc29b71aa42b') + }) +}) diff --git a/modules/integration-node/test/get_encrypt_test_iterator.test.ts b/modules/integration-node/test/get_encrypt_test_iterator.test.ts new file mode 100644 index 000000000..78ad9fd56 --- /dev/null +++ b/modules/integration-node/test/get_encrypt_test_iterator.test.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use + * this file except in compliance with the License. A copy of the License is + * located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-env mocha */ + +import { expect } from 'chai' +import 'mocha' +import { + _getEncryptTestVectorIterator +} from '../src/index' +import { EncryptManifestList, KeyList } from '../src/types' // eslint-disable-line no-unused-vars + +const manifiest: EncryptManifestList = { + 'manifest': { + 'type': 'awses-encrypt', + 'version': 1 + }, + 'keys': 'file://0002-keys.v1.json', + 'plaintexts': { + 'small': 10240 + }, + 'tests': { + '0c9c3222-b8f6-4b5f-97bc-c2a97f5255b1': { + 'plaintext': 'small', + 'algorithm': '0014', + 'frame-size': 0, + 'encryption-context': {}, + 'master-keys': [ + { + 'type': 'aws-kms', + 'key': 'us-west-2-decryptable' + } + ] + } + } +} + +const keyList: KeyList = { + 'manifest': { + 'type': 'keys', + 'version': 3 + }, + 'keys': { 'us-west-2-decryptable': { + 'type': 'aws-kms', + 'key-id': 'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt', + 'encrypt': true, + 'decrypt': true + } + } +} + +describe('_getEncryptTestVectorIterator', () => { + it('returns a iterator that has a test', () => { + const testIterator = _getEncryptTestVectorIterator(manifiest, keyList) + const test = testIterator.next() + expect(test.done).to.equal(false) + expect(test.value.name).to.equal('0c9c3222-b8f6-4b5f-97bc-c2a97f5255b1') + }) +})