From f9d7a6cd6502de57b0ff0792699b2970e4f1f070 Mon Sep 17 00:00:00 2001 From: seebees Date: Thu, 11 Jul 2019 07:45:28 -0700 Subject: [PATCH] feat: Node.js Typescript version dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit resolves #135 The AWS Encryption SDK should track the Node.js LTS policy. For developers using Typescript and @types/node@8 the ESDK should “just work”. Because some packages export Node.js types like `CipherGCM` developers would be forced to install an unwanted type version. This pulls in the needed parts of the needed types into the packages. It is only the types that differ in this case. Regarding KeyObjects, rsa support is removed, but will be added back in when #74 is addressed. --- modules/decrypt-node/src/decipher_stream.ts | 11 ++++-- modules/decrypt-node/src/verify_stream.ts | 6 +-- .../encrypt-node/src/framed_encrypt_stream.ts | 11 +++--- modules/material-management-node/src/index.ts | 6 ++- .../src/material_helpers.ts | 37 +++++++++++++++---- .../src/raw_rsa_keyring_node.ts | 7 ++-- 6 files changed, 53 insertions(+), 25 deletions(-) diff --git a/modules/decrypt-node/src/decipher_stream.ts b/modules/decrypt-node/src/decipher_stream.ts index 6624d643d..187468c54 100644 --- a/modules/decrypt-node/src/decipher_stream.ts +++ b/modules/decrypt-node/src/decipher_stream.ts @@ -16,8 +16,11 @@ // @ts-ignore import { Transform as PortableTransform } from 'readable-stream' import { Transform } from 'stream' // eslint-disable-line no-unused-vars -import { DecipherGCM } from 'crypto' // eslint-disable-line no-unused-vars -import { needs } from '@aws-crypto/material-management-node' +import { + needs, + GetDecipher, // eslint-disable-line no-unused-vars + AwsEsdkJsDecipherGCM // eslint-disable-line no-unused-vars +} from '@aws-crypto/material-management-node' import { aadFactory, ContentType // eslint-disable-line no-unused-vars @@ -31,12 +34,12 @@ const PortableTransformWithType = ( Transform>PortableTr export interface DecipherInfo { messageId: Buffer contentType: ContentType - getDecipher: (iv: Uint8Array) => DecipherGCM + getDecipher: GetDecipher dispose: () => void } interface DecipherState { - decipher: DecipherGCM + decipher: AwsEsdkJsDecipherGCM content: Buffer[] contentLength: number } diff --git a/modules/decrypt-node/src/verify_stream.ts b/modules/decrypt-node/src/verify_stream.ts index 784b91e56..c3d8dc7c1 100644 --- a/modules/decrypt-node/src/verify_stream.ts +++ b/modules/decrypt-node/src/verify_stream.ts @@ -16,10 +16,10 @@ // @ts-ignore import { Transform as PortableTransform } from 'readable-stream' import { Transform } from 'stream' // eslint-disable-line no-unused-vars -import { DecipherGCM } from 'crypto' // eslint-disable-line no-unused-vars import { needs, - GetVerify // eslint-disable-line no-unused-vars + GetVerify, // eslint-disable-line no-unused-vars + GetDecipher // eslint-disable-line no-unused-vars } from '@aws-crypto/material-management-node' import { deserializeSignature, @@ -35,7 +35,7 @@ const PortableTransformWithType = ( Transform>PortableTr export interface VerifyInfo { headerInfo: HeaderInfo - getDecipher: (iv: Uint8Array) => DecipherGCM + getDecipher: GetDecipher dispose: () => void verify?: AWSVerify } diff --git a/modules/encrypt-node/src/framed_encrypt_stream.ts b/modules/encrypt-node/src/framed_encrypt_stream.ts index d16e79f2d..1321bcf69 100644 --- a/modules/encrypt-node/src/framed_encrypt_stream.ts +++ b/modules/encrypt-node/src/framed_encrypt_stream.ts @@ -19,9 +19,12 @@ import { } from '@aws-crypto/serialize' // @ts-ignore import { Transform as PortableTransform } from 'readable-stream' -import { CipherGCM } from 'crypto' // eslint-disable-line no-unused-vars import { Transform } from 'stream' // eslint-disable-line no-unused-vars -import { needs } from '@aws-crypto/material-management-node' +import { + GetCipher, // eslint-disable-line no-unused-vars + AwsEsdkJsCipherGCM, // eslint-disable-line no-unused-vars + needs +} from '@aws-crypto/material-management-node' const fromUtf8 = (input: string) => Buffer.from(input, 'utf8') const serialize = serializeFactory(fromUtf8) @@ -38,7 +41,7 @@ interface EncryptFrame { content: Buffer[] bodyHeader: Buffer headerSent?: boolean - cipher: CipherGCM, + cipher: AwsEsdkJsCipherGCM, isFinalFrame: boolean } @@ -165,8 +168,6 @@ export function getFramedEncryptStream (getCipher: GetCipher, messageHeader: Mes })() } -type GetCipher = (iv: Uint8Array) => CipherGCM - type EncryptFrameInput = { pendingFrame: AccumulatingFrame, messageHeader: MessageHeader, diff --git a/modules/material-management-node/src/index.ts b/modules/material-management-node/src/index.ts index c630f3821..43fe641e7 100644 --- a/modules/material-management-node/src/index.ts +++ b/modules/material-management-node/src/index.ts @@ -18,7 +18,11 @@ export { getEncryptHelper, getDecryptionHelper, GetSigner, - GetVerify + GetVerify, + GetCipher, + GetDecipher, + AwsEsdkJsCipherGCM, + AwsEsdkJsDecipherGCM } from './material_helpers' export { NodeDecryptionMaterial, NodeEncryptionMaterial, NodeAlgorithmSuite, diff --git a/modules/material-management-node/src/material_helpers.ts b/modules/material-management-node/src/material_helpers.ts index 566d67b20..30ac54eba 100644 --- a/modules/material-management-node/src/material_helpers.ts +++ b/modules/material-management-node/src/material_helpers.ts @@ -18,11 +18,25 @@ import { NodeHash // eslint-disable-line no-unused-vars } from '@aws-crypto/material-management' import { - CipherGCM, DecipherGCM, Signer, Verify, // eslint-disable-line no-unused-vars + Signer, Verify, // eslint-disable-line no-unused-vars createCipheriv, createDecipheriv, createSign, createVerify } from 'crypto' import { HKDF } from '@aws-crypto/hkdf-node' +export interface AwsEsdkJsCipherGCM { + update(data: Buffer): Buffer + final(): Buffer + getAuthTag(): Buffer + setAAD(aad: Buffer): this +} + +export interface AwsEsdkJsDecipherGCM { + update(data: Buffer): Buffer + final(): Buffer + setAuthTag(buffer: Buffer): this + setAAD(aad: Buffer): this +} + type KDFIndex = Readonly<{[K in NodeHash]: ReturnType}> const kdfIndex: KDFIndex = Object.freeze({ sha256: HKDF('sha256' as NodeHash), @@ -30,7 +44,11 @@ const kdfIndex: KDFIndex = Object.freeze({ }) export interface GetCipher { - (info?: Uint8Array) : (iv: Uint8Array) => CipherGCM + (iv: Uint8Array): AwsEsdkJsCipherGCM +} + +export interface CurryGetCipher { + (info?: Uint8Array): GetCipher } export interface GetSigner { @@ -38,7 +56,7 @@ export interface GetSigner { } export interface NodeEncryptionMaterialHelper { - kdfGetCipher: GetCipher + kdfGetCipher: CurryGetCipher getSigner?: GetSigner dispose: () => void } @@ -56,7 +74,7 @@ export const getEncryptHelper: GetEncryptHelper = (material: NodeEncryptionMater * Function overloads "works" but then I can not export * the function and have eslint be happy (Multiple exports of name) */ - const kdfGetCipher = getCryptoStream(material) + const kdfGetCipher = getCryptoStream(material) return Object.freeze({ kdfGetCipher, getSigner: signatureHash ? getSigner : undefined, @@ -93,14 +111,17 @@ export const getEncryptHelper: GetEncryptHelper = (material: NodeEncryptionMater } export interface GetDecipher { - (info?: Uint8Array) : (iv: Uint8Array) => DecipherGCM + (iv: Uint8Array): AwsEsdkJsDecipherGCM +} +export interface CurryGetDecipher { + (info?: Uint8Array) : GetDecipher } export interface GetVerify { () : Verify & {awsCryptoVerify: (signature: Buffer) => boolean} } export interface NodeDecryptionMaterialHelper { - kdfGetDecipher: GetDecipher + kdfGetDecipher: CurryGetDecipher getVerify?: GetVerify dispose: () => void } @@ -119,7 +140,7 @@ export const getDecryptionHelper: GetDecryptionHelper = (material: NodeDecryptio * Function overloads "works" but then I can not export * the function and have eslint be happy (Multiple exports of name) */ - const kdfGetDecipher = getCryptoStream(material) + const kdfGetDecipher = getCryptoStream(material) return Object.freeze({ kdfGetDecipher, getVerify: signatureHash ? getVerify : undefined, @@ -158,7 +179,7 @@ export function getCryptoStream (material: NodeEncryptionMaterial|NodeDecryption return (info?: Uint8Array) => { const derivedKey = nodeKdf(material, info) - return (iv: Uint8Array) => { + return (iv: Uint8Array): AwsEsdkJsCipherGCM|AwsEsdkJsDecipherGCM => { /* Precondition: The length of the IV must match the algorithm suite specification. */ needs(iv.byteLength === ivLength, 'Iv length does not match algorithm suite specification') /* Precondition: The material must have not been zeroed. diff --git a/modules/raw-rsa-keyring-node/src/raw_rsa_keyring_node.ts b/modules/raw-rsa-keyring-node/src/raw_rsa_keyring_node.ts index 95962d4dc..c5e3736a8 100644 --- a/modules/raw-rsa-keyring-node/src/raw_rsa_keyring_node.ts +++ b/modules/raw-rsa-keyring-node/src/raw_rsa_keyring_node.ts @@ -30,8 +30,7 @@ import { constants, publicEncrypt, privateDecrypt, - randomBytes, - KeyObject // eslint-disable-line no-unused-vars + randomBytes } from 'crypto' import { @@ -52,8 +51,8 @@ import { * or more complicated options... Thoughts? */ interface RsaKey { - publicKey?: string | Buffer | KeyObject - privateKey?: string | Buffer | KeyObject + publicKey?: string | Buffer + privateKey?: string | Buffer } export type RawRsaKeyringNodeInput = {