Skip to content

Commit 66e63b5

Browse files
texastonyseebees
andauthoredNov 5, 2021
feat(node): support node v16 (#741)
Regenerated the Package lock with Node 16, NPM 8. Added CI testing for Node 16. Encapsulated Crypto's Sign(er) and Verify to prevent breaking changes. Implemented and used Catchable to catch unkown. TS upgrade introduced TS bug when recognizing arguments to SubtleCrypto's ImportKey. Introduced function and note to help it resolve the issue. Co-authored-by: seebees <[email protected]>
1 parent 6ba9add commit 66e63b5

File tree

30 files changed

+19466
-7207
lines changed

30 files changed

+19466
-7207
lines changed
 

‎buildspec.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,24 @@ batch:
99
image: aws/codebuild/standard:5.0
1010
- identifier: testNodejs12
1111
buildspec: codebuild/nodejs12.yml
12+
env:
13+
image: aws/codebuild/standard:5.0
1214
- identifier: testNodejs14
1315
buildspec: codebuild/nodejs14.yml
1416
env:
1517
image: aws/codebuild/standard:5.0
18+
- identifier: testNodejs16
19+
buildspec: codebuild/nodejs16.yml
20+
env:
21+
image: aws/codebuild/standard:5.0
1622
- identifier: testBrowser
1723
buildspec: codebuild/browser.yml
24+
env:
25+
image: aws/codebuild/standard:5.0
1826
- identifier: compliance
1927
buildspec: codebuild/compliance.yml
28+
env:
29+
image: aws/codebuild/standard:5.0
2030
- identifier: testVectorsNodejsLatest
2131
buildspec: codebuild/test_vectors/nodejs_latest.yml
2232
env:
@@ -25,10 +35,16 @@ batch:
2535
image: aws/codebuild/standard:5.0
2636
- identifier: testVectorsNodejs12
2737
buildspec: codebuild/test_vectors/nodejs12.yml
38+
env:
39+
image: aws/codebuild/standard:5.0
2840
- identifier: testVectorsNodejs14
2941
buildspec: codebuild/test_vectors/nodejs14.yml
3042
env:
3143
image: aws/codebuild/standard:5.0
44+
- identifier: testVectorsNodejs16
45+
buildspec: codebuild/test_vectors/nodejs16.yml
46+
env:
47+
image: aws/codebuild/standard:5.0
3248
- identifier: testVectorsBrowser
3349
buildspec: codebuild/test_vectors/browser.yml
3450
env:

‎codebuild/nodejs16.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
version: 0.2
2+
3+
env:
4+
variables:
5+
NODE_OPTIONS: "--max-old-space-size=4096"
6+
7+
phases:
8+
install:
9+
commands:
10+
- n 16
11+
- node -v
12+
- npm -v
13+
- npm ci --unsafe-perm
14+
- npm run build
15+
build:
16+
commands:
17+
- npm -v
18+
- node -v
19+
- npm run coverage-node

‎codebuild/test_vectors/nodejs16.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
version: 0.2
2+
3+
env:
4+
variables:
5+
NODE_OPTIONS: "--max-old-space-size=4096"
6+
NPM_CONFIG_UNSAFE_PERM: true
7+
8+
phases:
9+
install:
10+
commands:
11+
- n 16
12+
- node -v
13+
- npm -v
14+
- npm ci --unsafe-perm
15+
- npm run build
16+
build:
17+
commands:
18+
- npm -v
19+
- node -v
20+
- npm run verdaccio-publish
21+
- npm run verdaccio-node-decrypt
22+
- npm run verdaccio-node-encrypt

‎modules/decrypt-node/src/verify_stream.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ export class VerifyStream extends PortableTransformWithType {
8080
if (verify) {
8181
const { rawHeader, headerAuth, messageHeader } = headerInfo
8282
const { headerIv, headerAuthTag } = headerAuth
83-
verify.update(rawHeader)
83+
verify.update(<Buffer>rawHeader)
8484
verify.update(
85-
serializeMessageHeaderAuth({
85+
<Buffer>serializeMessageHeaderAuth({
8686
headerIv,
8787
headerAuthTag,
8888
messageHeader,
@@ -263,7 +263,7 @@ export class VerifyStream extends PortableTransformWithType {
263263
return super.push(chunk, encoding)
264264
}
265265

266-
_flush(callback: (err?: Error) => void) {
266+
_flush(callback: (err?: Error | any | unknown) => void) {
267267
const { finalAuthTagReceived } = this._verifyState
268268
/* Precondition: All ciphertext MUST have been received.
269269
* The verify stream has ended,

‎modules/example-browser/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
"karma-chrome-launcher": "^3.1.0",
3535
"karma-coverage-istanbul-reporter": "^3.0.3",
3636
"karma-mocha": "2.0.1",
37-
"karma-webpack": "^4.0.2",
37+
"karma-webpack": "^5.0.0",
3838
"ts-loader": "9.2.5",
3939
"ts-node": "^10.2.1",
4040
"tslib": "^2.2.0",
4141
"typescript": "^4.0.2",
42-
"webpack": "^4.42.1",
42+
"webpack": "^5.42.0",
4343
"webpack-cli": "4.6.0"
4444
},
4545
"main": "./build/main/src/index.js",

‎modules/integration-browser/src/integration.encrypt.test.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ function aTest(testName: string, decryptOracle: string) {
5959
const body = await response.arrayBuffer()
6060
needs(response.ok, `Failed to decrypt: ${toUtf8(body)}`)
6161
expect(plainText).toEqual(new Uint8Array(body))
62-
} catch (e) {
63-
if (!notSupportedMessages.includes(e.message)) throw e
62+
} catch (err) {
63+
needs(
64+
err instanceof Error,
65+
`Thrown object must be an error but was ${typeof err}`
66+
)
67+
needs(
68+
notSupportedMessages.includes(err.message),
69+
`Error message should be in notSupportedMessages but was ${err.message}`
70+
)
6471
}
6572
})
6673
}

‎modules/integration-browser/src/testDecryptFixture.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
MultiKeyringWebCrypto,
77
WebCryptoMaterialsManager,
88
DecryptResult,
9+
needs,
910
} from '@aws-crypto/client-browser'
1011
import {
1112
DecryptionFixture,
@@ -69,14 +70,17 @@ export async function testPositiveDecryptFixture(
6970
) {
7071
return { result: true, name }
7172
}
72-
// noinspection ExceptionCaughtLocallyJS
73+
/* If the actual plaintext does not match the expected plaintext,*/
7374
throw new Error(
7475
expectedNotActualPlaintextMessage +
7576
`\n expected plaintext: ${expectedPlainText}` +
7677
`\n actual plaintext: ${decryptResult.plaintext}`
7778
)
7879
} catch (err) {
80+
/* it FAILED with err.message as expectedNotActualPlaintextMessage */
7981
return { result: false, name, err }
82+
//By catching the err and returning it above, we also satisfy:
83+
/* If the decryption is NOT supported, FAILED with err.message in notSupportedDecryptMessages */
8084
}
8185
}
8286

@@ -96,10 +100,18 @@ export async function testNegativeDecryptFixture(
96100
const cmm = await _getCmm(keyInfos)
97101
decryptResult = await _decrypt(cmm, cipher)
98102
} catch (err) {
99-
if (notSupportedDecryptMessages.includes(err.message))
103+
needs(
104+
err instanceof Error,
105+
`Thrown object must be an error but was ${typeof err}`
106+
)
107+
if (notSupportedDecryptMessages.includes(err.message)) {
108+
/* If the decryption is NOT supported, FAILED with err.message in notSupportedDecryptMessages */
100109
return { result: false, name, err: err }
110+
}
111+
/* If it is a negative test, and it throws an error outside of notSupportedDecryptMessages, it PASSED.*/
101112
return { result: true, name }
102113
}
114+
/* If it is a negative test, and it does not throw an error, it FAILED */
103115
return {
104116
result: false,
105117
name,

‎modules/integration-node/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
"@aws-crypto/integration-vectors": "file:../integration-vectors",
2121
"@types/got": "^9.6.9",
2222
"@types/stream-to-promise": "^2.2.0",
23-
"@types/yargs": "^15.0.3",
23+
"@types/yargs": "^17.0.1",
2424
"got": "^11.8.0",
2525
"stream-to-promise": "^3.0.0",
2626
"tslib": "^2.3.0",
27-
"yargs": "^17.1.0"
27+
"yargs": "^17.0.1"
2828
},
2929
"sideEffects": false,
3030
"main": "./build/main/src/index.js",

‎modules/integration-node/src/cli.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const cli = yargs
8080
tolerateFailures,
8181
testName,
8282
concurrency,
83-
} = argv
83+
} = await argv
8484
/* I set the result to 1 so that if I fall through the exit condition is a failure */
8585
let result = 1
8686
if (command === 'decrypt') {

‎modules/integration-node/src/decrypt_materials_manager_node.ts

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,29 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
import {
5-
needs,
5+
buildAwsKmsMrkAwareDiscoveryMultiKeyringNode,
6+
buildAwsKmsMrkAwareStrictMultiKeyringNode,
67
KeyringNode,
7-
MultiKeyringNode,
88
KmsKeyringNode,
9+
MultiKeyringNode,
10+
needs,
11+
oaepHashSupported,
912
RawAesKeyringNode,
10-
WrappingSuiteIdentifier,
1113
RawAesWrappingSuiteIdentifier,
1214
RawRsaKeyringNode,
13-
oaepHashSupported,
14-
buildAwsKmsMrkAwareStrictMultiKeyringNode,
15-
buildAwsKmsMrkAwareDiscoveryMultiKeyringNode,
15+
WrappingSuiteIdentifier,
1616
} from '@aws-crypto/client-node'
1717
import {
18-
RsaKeyInfo,
18+
AESKey,
1919
AesKeyInfo,
20+
buildGetKeyring,
21+
KeyInfoTuple,
22+
KMSKey,
2023
KmsKeyInfo,
21-
KmsMrkAwareKeyInfo,
2224
KmsMrkAwareDiscoveryKeyInfo,
25+
KmsMrkAwareKeyInfo,
2326
RSAKey,
24-
AESKey,
25-
KMSKey,
26-
KeyInfoTuple,
27-
buildGetKeyring,
27+
RsaKeyInfo,
2828
} from '@aws-crypto/integration-vectors'
2929
import { constants } from 'crypto'
3030

@@ -117,12 +117,3 @@ export function rsaPadding(keyInfo: RsaKeyInfo) {
117117
needs(oaepHashSupported || oaepHash === 'sha1', 'Not supported at this time.')
118118
return { padding, oaepHash }
119119
}
120-
121-
export class NotSupported extends Error {
122-
code: string
123-
constructor(message?: string) {
124-
super(message)
125-
Object.setPrototypeOf(this, NotSupported.prototype)
126-
this.code = 'NOT_SUPPORTED'
127-
}
128-
}

‎modules/integration-vectors/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export interface TestVectorResult {
6161
name: string
6262
result: boolean
6363
description?: string
64-
err?: Error
64+
err?: Error | string | any
6565
}
6666

6767
export interface StreamEntry extends Entry {

‎modules/kms-keyring/src/kms_keyring.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
readOnlyProperty,
1717
unwrapDataKey,
1818
Newable,
19+
Catchable,
1920
} from '@aws-crypto/material-management'
2021
import {
2122
KMS_PROVIDER_ID,
@@ -243,7 +244,7 @@ export function KmsKeyringClass<
243244
*/
244245
const decryptableEDKs = encryptedDataKeys.filter(filterEDKs(keyIds, this))
245246

246-
const cmkErrors: Error[] = []
247+
const cmkErrors: Catchable[] = []
247248

248249
for (const edk of decryptableEDKs) {
249250
let dataKey: RequiredDecryptResponse | false = false
@@ -259,7 +260,7 @@ export function KmsKeyringClass<
259260
* If the caller does not have access they may have access
260261
* through another Keyring.
261262
*/
262-
cmkErrors.push(e)
263+
cmkErrors.push({ errPlus: e })
263264
}
264265

265266
/* Check for early return (Postcondition): clientProvider may not return a client. */
@@ -300,7 +301,7 @@ export function KmsKeyringClass<
300301
material.hasValidKey() ||
301302
(!material.hasValidKey() && !cmkErrors.length),
302303
cmkErrors.reduce(
303-
(m, e, i) => `${m} Error #${i + 1} \n ${e.stack} \n`,
304+
(m, e, i) => `${m} Error #${i + 1} \n ${e.errPlus.stack} \n`,
304305
'Unable to decrypt data key and one or more KMS CMKs had an error. \n '
305306
)
306307
)

‎modules/kms-keyring/src/kms_mrk_discovery_keyring.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
readOnlyProperty,
1414
SupportedAlgorithmSuites,
1515
Newable,
16+
Catchable,
1617
} from '@aws-crypto/material-management'
1718
import {
1819
constructArnInOtherRegion,
@@ -170,7 +171,7 @@ export function AwsKmsMrkAwareSymmetricDiscoveryKeyringClass<
170171
//# The set of encrypted data keys MUST first be filtered to match this
171172
//# keyring's configuration.
172173
const decryptableEDKs = encryptedDataKeys.filter(filterEDKs(this))
173-
const cmkErrors: Error[] = []
174+
const cmkErrors: Catchable[] = []
174175

175176
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-region-discovery-keyring.txt#2.8
176177
//# For each encrypted data key in the filtered set, one at a time, the
@@ -253,7 +254,7 @@ export function AwsKmsMrkAwareSymmetricDiscoveryKeyringClass<
253254
//# If the response does not satisfies these requirements then an error
254255
//# is collected and the next encrypted data key in the filtered set MUST
255256
//# be attempted.
256-
cmkErrors.push(e)
257+
cmkErrors.push({ errPlus: e })
257258
}
258259
}
259260
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-region-discovery-keyring.txt#2.8
@@ -266,7 +267,7 @@ export function AwsKmsMrkAwareSymmetricDiscoveryKeyringClass<
266267
`Unable to decrypt data key${
267268
!decryptableEDKs.length ? ': No EDKs supplied' : ''
268269
}.`,
269-
...cmkErrors.map((e, i) => `Error #${i + 1} \n${e.stack}`),
270+
...cmkErrors.map((e, i) => `Error #${i + 1} \n${e.errPlus.stack}`),
270271
].join('\n')
271272
)
272273
return material

‎modules/kms-keyring/src/kms_mrk_keyring.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
readOnlyProperty,
1616
unwrapDataKey,
1717
Newable,
18+
Catchable,
1819
} from '@aws-crypto/material-management'
1920
import {
2021
KMS_PROVIDER_ID,
@@ -274,7 +275,7 @@ export function AwsKmsMrkAwareSymmetricKeyringClass<
274275
//# keyring's configuration.
275276
const decryptableEDKs = encryptedDataKeys.filter(filterEDKs(keyId))
276277

277-
const cmkErrors: Error[] = []
278+
const cmkErrors: Catchable[] = []
278279

279280
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
280281
//# For each encrypted data key in the filtered set, one at a time, the
@@ -344,7 +345,7 @@ export function AwsKmsMrkAwareSymmetricKeyringClass<
344345
//# If the response does not satisfies these requirements then an error
345346
//# MUST be collected and the next encrypted data key in the filtered set
346347
//# MUST be attempted.
347-
cmkErrors.push(e)
348+
cmkErrors.push({ errPlus: e })
348349
}
349350
}
350351

@@ -358,7 +359,7 @@ export function AwsKmsMrkAwareSymmetricKeyringClass<
358359
`Unable to decrypt data key${
359360
!decryptableEDKs.length ? ': No EDKs supplied' : ''
360361
}.`,
361-
...cmkErrors.map((e, i) => `Error #${i + 1} \n${e.stack}`),
362+
...cmkErrors.map((e, i) => `Error #${i + 1} \n${e.errPlus.stack}`),
362363
].join('\n')
363364
)
364365

‎modules/material-management-node/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export {
2222
KeyringTrace,
2323
KeyringTraceFlag,
2424
needs,
25+
NotSupported,
2526
KeyringNode,
2627
MultiKeyringNode,
2728
immutableBaseClass,

‎modules/material-management-node/src/material_helpers.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import {
1111
NodeHash,
1212
} from '@aws-crypto/material-management'
1313
import {
14-
Signer,
15-
Verify,
1614
createCipheriv,
1715
createDecipheriv,
1816
createSign,
@@ -21,6 +19,7 @@ import {
2119
} from 'crypto'
2220
import { HKDF } from '@aws-crypto/hkdf-node'
2321
import { kdfInfo, kdfCommitKeyInfo } from '@aws-crypto/serialize'
22+
import { AwsESDKSigner, AwsESDKVerify } from './types'
2423

2524
export interface AwsEsdkJsCipherGCM {
2625
update(data: Buffer): Buffer
@@ -55,7 +54,7 @@ export interface GetCipherInfo {
5554
}
5655

5756
export interface GetSigner {
58-
(): Signer & { awsCryptoSign: () => Buffer }
57+
(): AwsESDKSigner & { awsCryptoSign: () => Buffer }
5958
}
6059

6160
export interface NodeEncryptionMaterialHelper {
@@ -128,7 +127,7 @@ export interface GetDecipherInfo {
128127
}
129128

130129
export interface GetVerify {
131-
(): Verify & { awsCryptoVerify: (signature: Buffer) => boolean }
130+
(): AwsESDKVerify & { awsCryptoVerify: (signature: Buffer) => boolean }
132131
}
133132

134133
export interface NodeDecryptionMaterialHelper {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import * as stream from 'stream'
5+
6+
// noinspection JSAnnotator
7+
export interface AwsESDKSigner extends stream.Writable {
8+
update(data: Buffer): AwsESDKSigner
9+
sign(privateKey: string): Buffer
10+
}
11+
12+
// noinspection JSAnnotator
13+
export interface AwsESDKVerify extends stream.Writable {
14+
update(data: Buffer): AwsESDKVerify
15+
verify(publicKey: string, signature: Buffer): boolean
16+
}

‎modules/material-management-node/test/material_helpers.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ describe('getEncryptHelper', () => {
429429

430430
const signer = helper.getSigner()
431431
expect(signer).to.haveOwnProperty('awsCryptoSign').and.to.be.a('function')
432-
signer.update('data')
432+
signer.update(Buffer.from('data'))
433433
const sig = signer.awsCryptoSign()
434434
expect(sig).instanceOf(Buffer)
435435
})
@@ -564,7 +564,7 @@ describe('getDecryptionHelper', () => {
564564

565565
const verify = helper.getVerify()
566566
expect(verify).to.haveOwnProperty('awsCryptoVerify').and.to.be.a('function')
567-
verify.update('data')
567+
verify.update(Buffer.from('data'))
568568
const isValid = verify.awsCryptoVerify(Buffer.alloc(5))
569569
expect(isValid).to.equal(false)
570570
})
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
export class NotSupported extends Error {
4+
code: string
5+
6+
constructor(message?: string) {
7+
super(message)
8+
Object.setPrototypeOf(this, NotSupported.prototype)
9+
this.code = 'NOT_SUPPORTED'
10+
}
11+
}

‎modules/material-management/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,4 @@ export { needs } from './needs'
8080
export { cloneMaterial } from './clone_cryptographic_material'
8181

8282
export * from './types'
83+
export { NotSupported } from './error'

‎modules/material-management/src/multi_keyring.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
SupportedAlgorithmSuites,
88
EncryptionMaterial,
99
DecryptionMaterial,
10+
Catchable,
1011
} from './types'
1112
import { needs } from './needs'
1213
import { EncryptedDataKey } from './encrypted_data_key'
@@ -119,7 +120,7 @@ function buildPrivateOnDecrypt<S extends SupportedAlgorithmSuites>() {
119120
const children = this.children.slice()
120121
if (this.generator) children.unshift(this.generator)
121122

122-
const childKeyringErrors: Error[] = []
123+
const childKeyringErrors: Catchable[] = []
123124

124125
for (const keyring of children) {
125126
/* Check for early return (Postcondition): Do not attempt to decrypt once I have a valid key. */
@@ -132,7 +133,7 @@ function buildPrivateOnDecrypt<S extends SupportedAlgorithmSuites>() {
132133
* If the caller does not have access they may have access
133134
* through another Keyring.
134135
*/
135-
childKeyringErrors.push(e)
136+
childKeyringErrors.push({ errPlus: e })
136137
}
137138
}
138139

@@ -149,7 +150,7 @@ function buildPrivateOnDecrypt<S extends SupportedAlgorithmSuites>() {
149150
material.hasValidKey() ||
150151
(!material.hasValidKey() && !childKeyringErrors.length),
151152
childKeyringErrors.reduce(
152-
(m, e, i) => `${m} Error #${i + 1} \n ${e.stack} \n`,
153+
(m, e, i) => `${m} Error #${i + 1} \n ${e.errPlus.stack} \n`,
153154
'Unable to decrypt data key and one or more child keyrings had an error. \n '
154155
)
155156
)

‎modules/material-management/src/node_algorithms.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ const nodeAlgAes256GcmHkdfSha512CommittingEcdsaP384: NodeAlgCommittedSigned = {
226226
saltLengthBytes: 32,
227227
}
228228

229-
type NodeAlgorithms = Readonly<
230-
{ [id in AlgorithmSuiteIdentifier]: NodeAlgUnion }
231-
>
229+
type NodeAlgorithms = Readonly<{
230+
[id in AlgorithmSuiteIdentifier]: NodeAlgUnion
231+
}>
232232
const nodeAlgorithms: NodeAlgorithms = Object.freeze({
233233
[AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16]: Object.freeze(
234234
nodeAlgAes128GcmIv12Tag16

‎modules/material-management/src/types.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import { NodeAlgorithmSuite } from './node_algorithms'
55
import { WebCryptoAlgorithmSuite } from './web_crypto_algorithms'
66
import { EncryptedDataKey } from './encrypted_data_key'
77
import {
8-
NodeEncryptionMaterial,
9-
WebCryptoEncryptionMaterial,
108
NodeDecryptionMaterial,
9+
NodeEncryptionMaterial,
1110
WebCryptoDecryptionMaterial,
11+
WebCryptoEncryptionMaterial,
1212
} from './cryptographic_material'
1313
import { CommitmentPolicy } from './algorithm_suites'
1414

@@ -156,3 +156,7 @@ export interface AwsEsdkAsymmetricKeyDetails {
156156
*/
157157
namedCurve?: string
158158
}
159+
160+
export interface Catchable {
161+
errPlus?: Error | string | any
162+
}

‎modules/material-management/src/web_crypto_algorithms.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,9 @@ const webCryptoAlgAes256GcmHkdfSha512CommittingEcdsaP384: WebCryptoAlgCommittedS
233233
saltLengthBytes: 32,
234234
}
235235

236-
type WebCryptoAlgorithms = Readonly<
237-
{ [id in AlgorithmSuiteIdentifier]: WebCryptoAlgUnion }
238-
>
236+
type WebCryptoAlgorithms = Readonly<{
237+
[id in AlgorithmSuiteIdentifier]: WebCryptoAlgUnion
238+
}>
239239
const webCryptoAlgorithms: WebCryptoAlgorithms = Object.freeze({
240240
[AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16]: Object.freeze(
241241
webCryptoAlgAes128GcmIv12Tag16
@@ -279,9 +279,9 @@ type WebCryptoAlgorithmSuiteIdentifier = Exclude<
279279
>,
280280
AlgorithmSuiteIdentifier.ALG_AES192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384
281281
>
282-
type SupportedWebCryptoAlgorithms = Readonly<
283-
{ [id in WebCryptoAlgorithmSuiteIdentifier]: WebCryptoAlgUnion }
284-
>
282+
type SupportedWebCryptoAlgorithms = Readonly<{
283+
[id in WebCryptoAlgorithmSuiteIdentifier]: WebCryptoAlgUnion
284+
}>
285285
const supportedWebCryptoAlgorithms: SupportedWebCryptoAlgorithms =
286286
Object.freeze({
287287
[AlgorithmSuiteIdentifier.ALG_AES128_GCM_IV12_TAG16]: Object.freeze(

‎modules/raw-rsa-keyring-browser/src/get_import_options.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,17 @@ const RsaPaddingMap: {
6464
[RsaPadding.OAEP_SHA512_MFG1]: OAEP_SHA512_MFG1,
6565
})
6666

67-
export function getImportOptions(keyInfo: RsaImportableKey) {
67+
export function getImportOptions(keyInfo: RsaImportableKey):
68+
| {
69+
format: 'jwk'
70+
wrappingAlgorithm: RsaWrappingKeyAlgorithm
71+
key: RsaJsonWebKey
72+
}
73+
| {
74+
format: 'raw' | 'pkcs8' | 'spki'
75+
wrappingAlgorithm: RsaWrappingKeyAlgorithm
76+
key: Uint8Array
77+
} {
6878
const { alg } = keyInfo as RsaJsonWebKey
6979
const { padding } = keyInfo as BinaryKey
7080
if (JsonWebKeyMap[alg]) {

‎modules/raw-rsa-keyring-browser/src/raw_rsa_keyring_web_crypto.ts

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
flattenMixedCryptoKey,
4040
} from './get_import_options'
4141

42+
// noinspection TypeScriptValidateTypes
4243
export class RawRsaKeyringWebCrypto extends KeyringWebCrypto {
4344
public declare keyNamespace: string
4445
public declare keyName: string
@@ -190,38 +191,25 @@ export class RawRsaKeyringWebCrypto extends KeyringWebCrypto {
190191
static async importPublicKey(
191192
publicKey: RsaImportableKey
192193
): Promise<AwsEsdkJsCryptoKey> {
193-
const { wrappingAlgorithm, format, key } = getImportOptions(publicKey)
194+
const op = getImportOptions(publicKey)
194195
const backend = await getWebCryptoBackend()
195196
const subtle = getNonZeroByteBackend(backend)
196-
return subtle.importKey(format, key, wrappingAlgorithm, false, ['wrapKey'])
197+
198+
return ImportKeyTypeOverload(op, subtle, ['wrapKey'])
197199
}
198200

199201
static async importPrivateKey(
200202
privateKey: RsaImportableKey
201203
): Promise<AwsEsdkJsCryptoKey | MixedBackendCryptoKey> {
202-
const { wrappingAlgorithm, format, key } = getImportOptions(privateKey)
204+
const op = getImportOptions(privateKey)
203205
const backend = await getWebCryptoBackend()
204206

205207
if (isFullSupportWebCryptoBackend(backend)) {
206-
return backend.subtle.importKey(format, key, wrappingAlgorithm, false, [
207-
'unwrapKey',
208-
])
208+
return ImportKeyTypeOverload(op, backend.subtle, ['unwrapKey'])
209209
} else {
210210
return Promise.all([
211-
backend.nonZeroByteSubtle.importKey(
212-
format,
213-
key,
214-
wrappingAlgorithm,
215-
false,
216-
['unwrapKey']
217-
),
218-
backend.zeroByteSubtle.importKey(
219-
format,
220-
key,
221-
wrappingAlgorithm,
222-
false,
223-
['unwrapKey']
224-
),
211+
ImportKeyTypeOverload(op, backend.nonZeroByteSubtle, ['unwrapKey']),
212+
ImportKeyTypeOverload(op, backend.zeroByteSubtle, ['unwrapKey']),
225213
]).then(([nonZeroByteCryptoKey, zeroByteCryptoKey]) => ({
226214
nonZeroByteCryptoKey,
227215
zeroByteCryptoKey,
@@ -230,3 +218,47 @@ export class RawRsaKeyringWebCrypto extends KeyringWebCrypto {
230218
}
231219
}
232220
immutableClass(RawRsaKeyringWebCrypto)
221+
222+
// TS2769 Note:
223+
// TS2769 is "No overload matches this call".
224+
// Above and below, TS is incorrect.
225+
// `importKey` has two overrides,
226+
// They are abbreviated below:
227+
// ```
228+
// importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | ... , extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
229+
// importKey(format: "raw" | "pkcs8" | "spki", keyData: BufferSource, algorithm: AlgorithmIdentifier | ..., extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
230+
// ```
231+
// The method getImportOptions explicitly
232+
// returns format & key that match
233+
// these overrides.
234+
// However, TS is unable to recognize this easily.
235+
// The following ugly function does the disambiguation.
236+
// There are 2 problems that TS is having.
237+
// First when format key and wrappingAlgorithm are independent,
238+
// TS does not _remember_ the relationship between format and key.
239+
// The second issue is related,
240+
// when trying to select the proper overload,
241+
// it is collapsing the definition of format.
242+
// Thus discriminating the union by `format`
243+
// helps TS understand all the arguments.
244+
async function ImportKeyTypeOverload(
245+
op: ReturnType<typeof getImportOptions>,
246+
subtle: SubtleCrypto,
247+
keyUsages: KeyUsage[]
248+
): Promise<AwsEsdkJsCryptoKey> {
249+
return op.format == 'jwk'
250+
? subtle.importKey(
251+
op.format,
252+
op.key,
253+
op.wrappingAlgorithm,
254+
false,
255+
keyUsages
256+
)
257+
: subtle.importKey(
258+
op.format,
259+
op.key,
260+
op.wrappingAlgorithm,
261+
false,
262+
keyUsages
263+
)
264+
}

‎modules/raw-rsa-keyring-node/src/oaep_hash_supported.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* But sending an invalid hash to a version that does not support oaepHash will be ignored.
1212
*/
1313

14-
import { needs } from '@aws-crypto/material-management-node'
14+
import { needs, NotSupported } from '@aws-crypto/material-management-node'
1515

1616
import { constants, publicEncrypt } from 'crypto'
1717

@@ -32,10 +32,13 @@ export const oaepHashSupported = (function () {
3232
*/
3333
return false
3434
} catch (ex) {
35-
needs(
36-
ex.code === 'ERR_OSSL_EVP_INVALID_DIGEST',
37-
'Unexpected error testing oaepHash.'
38-
)
39-
return true
35+
if (ex instanceof NotSupported) {
36+
needs(
37+
ex.code === 'ERR_OSSL_EVP_INVALID_DIGEST',
38+
'Unexpected error testing oaepHash.'
39+
)
40+
return true
41+
}
42+
return Error('Unexpected error testing oaepHash.')
4043
}
4144
})()

‎modules/web-crypto-backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"dependencies": {
2222
"@aws-crypto/ie11-detection": "1.0.0",
2323
"@aws-crypto/supports-web-crypto": "1.0.0",
24-
"@aws-sdk/util-locate-window": "3.23.0",
24+
"@aws-sdk/util-locate-window": "3.29.0",
2525
"tslib": "^2.2.0"
2626
},
2727
"sideEffects": false,

‎package-lock.json

Lines changed: 19222 additions & 7111 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,17 @@
105105
"@types/chai-as-promised": "^7.1.3",
106106
"@types/from2": "^2.3.0",
107107
"@types/mocha": "^9.0.0",
108-
"@types/node": "^15.12.5",
109-
"@typescript-eslint/eslint-plugin": "^4.1.0",
110-
"@typescript-eslint/parser": "^4.1.0",
108+
"@types/node": "^16.9.1",
109+
"@typescript-eslint/eslint-plugin": "^4.31.1",
110+
"@typescript-eslint/parser": "^4.31.1",
111111
"buffer": "^6.0.3",
112112
"chai": "^4.2.0",
113113
"chai-as-promised": "^7.1.1",
114114
"eslint": "^7.8.1",
115115
"eslint-config-prettier": "^8.3.0",
116116
"from2": "^2.3.0",
117117
"genversion": "^3.0.0",
118-
"husky": "^7.0.0",
118+
"husky": "^7.0.2",
119119
"karma": "^6.3.4",
120120
"karma-chai": "^0.1.0",
121121
"karma-chrome-launcher": "^3.1.0",
@@ -133,7 +133,7 @@
133133
"rimraf": "^3.0.2",
134134
"source-map-support": "^0.5.19",
135135
"tslib": "^2.3.0",
136-
"typescript": "^4.0.2",
136+
"typescript": "^4.4.3",
137137
"verdaccio": "^5.1.1",
138138
"webpack": "^5.41.1",
139139
"webpack-cli": "^4.7.2"

0 commit comments

Comments
 (0)
Please sign in to comment.