Skip to content

Commit 24784ad

Browse files
committed
refactor and some tests
1 parent 997fb94 commit 24784ad

File tree

10 files changed

+288
-91
lines changed

10 files changed

+288
-91
lines changed

modules/cache-material/src/build_cryptographic_materials_cache_key_helpers.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import {
88
EncryptedDataKey,
99
EncryptionContext,
1010
} from '@aws-crypto/material-management'
11-
import { serializeFactory, uInt16BE } from '@aws-crypto/serialize'
11+
import {
12+
serializeFactory,
13+
uInt16BE,
14+
SerializeOptions,
15+
} from '@aws-crypto/serialize'
1216
import { compare } from './portable_compare'
1317

1418
// 512 bits of 0 for padding between hashes in decryption materials cache ID generation.
@@ -21,8 +25,9 @@ export function buildCryptographicMaterialsCacheKeyHelpers<
2125
toUtf8: (input: Uint8Array) => string,
2226
sha512: (...data: (Uint8Array | string)[]) => Promise<Uint8Array>
2327
): CryptographicMaterialsCacheKeyHelpersInterface<S> {
28+
const sorting: SerializeOptions = { utf8Sorting: true }
2429
const { serializeEncryptionContext, serializeEncryptedDataKey } =
25-
serializeFactory(fromUtf8, { utf8Sorting: false })
30+
serializeFactory(fromUtf8, sorting)
2631

2732
return {
2833
buildEncryptionMaterialCacheKey,
@@ -80,9 +85,7 @@ export function buildCryptographicMaterialsCacheKeyHelpers<
8085
* However, the RAW Keyring wants _only_ the ADD.
8186
* So, I just slice off the length.
8287
*/
83-
const serializedContext = serializeEncryptionContext(context, {
84-
utf8Sorting: false,
85-
}).slice(2)
88+
const serializedContext = serializeEncryptionContext(context).slice(2)
8689
return sha512(serializedContext)
8790
}
8891
}

modules/kms-keyring-node/src/kms_hkeyring_node.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export interface KmsHierarchicalKeyRingNodeInput {
7474
//= type=implication
7575
//# - MAY provide a [Partition ID](#partition-id)
7676
partitionId?: string
77+
utf8Sorting?: boolean | true
7778
}
7879

7980
export interface IKmsHierarchicalKeyRingNode extends KeyringNode {
@@ -104,6 +105,7 @@ export class KmsHierarchicalKeyRingNode
104105
public declare maxCacheSize?: number
105106
public declare _cmc: CryptographicMaterialsCache<NodeAlgorithmSuite>
106107
declare readonly _partition: Buffer
108+
public declare utf8Sorting: boolean | true
107109

108110
constructor({
109111
branchKeyId,
@@ -113,6 +115,7 @@ export class KmsHierarchicalKeyRingNode
113115
cache,
114116
maxCacheSize,
115117
partitionId,
118+
utf8Sorting,
116119
}: KmsHierarchicalKeyRingNodeInput) {
117120
super()
118121

@@ -256,6 +259,17 @@ export class KmsHierarchicalKeyRingNode
256259
readOnlyProperty(this, 'maxCacheSize', maxCacheSize)
257260
readOnlyProperty(this, '_cmc', cache)
258261

262+
if (utf8Sorting) {
263+
needs(
264+
typeof utf8Sorting === 'boolean',
265+
'The branch key id must be a string'
266+
)
267+
} else {
268+
utf8Sorting = true
269+
}
270+
271+
readOnlyProperty(this, 'utf8Sorting', utf8Sorting)
272+
259273
Object.freeze(this)
260274
/* Postcondition: The HKR object must be frozen */
261275
}
@@ -299,7 +313,8 @@ export class KmsHierarchicalKeyRingNode
299313
const edk = wrapPlaintextDataKey(
300314
pdk,
301315
branchKeyMaterials,
302-
encryptionMaterial
316+
encryptionMaterial,
317+
this.utf8Sorting
303318
)
304319

305320
// return the modified encryption material with the new edk and newly
@@ -428,7 +443,8 @@ export class KmsHierarchicalKeyRingNode
428443
udk = unwrapEncryptedDataKey(
429444
ciphertext,
430445
branchKeyMaterials,
431-
decryptionMaterial
446+
decryptionMaterial,
447+
this.utf8Sorting
432448
)
433449
} catch (e) {
434450
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#ondecrypt

modules/kms-keyring-node/src/kms_hkeyring_node_helpers.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,7 @@ import {
3333
PROVIDER_ID_HIERARCHY_AS_BYTES,
3434
} from './constants'
3535
import { BranchKeyIdSupplier } from '@aws-crypto/kms-keyring'
36-
import {
37-
serializeFactory,
38-
SerializeOptions,
39-
uuidv4Factory,
40-
} from '@aws-crypto/serialize'
36+
import { serializeFactory, uuidv4Factory } from '@aws-crypto/serialize'
4137

4238
export const stringToUtf8Bytes = (input: string): Buffer =>
4339
Buffer.from(input, 'utf-8')
@@ -49,11 +45,6 @@ const hexBytesToString = (input: Uint8Array): string =>
4945
Buffer.from(input).toString('hex')
5046
export const { uuidv4ToCompressedBytes, decompressBytesToUuidv4 } =
5147
uuidv4Factory(stringToHexBytes, hexBytesToString)
52-
export const utf8Sorting: SerializeOptions = { utf8Sorting: false }
53-
export const { serializeEncryptionContext } = serializeFactory(
54-
stringToUtf8Bytes,
55-
utf8Sorting
56-
)
5748

5849
export function getBranchKeyId(
5950
{ branchKeyId, branchKeyIdSupplier }: IKmsHierarchicalKeyRingNode,
@@ -297,7 +288,8 @@ export function getPlaintextDataKey(material: NodeEncryptionMaterial) {
297288
export function wrapPlaintextDataKey(
298289
pdk: Uint8Array,
299290
branchKeyMaterials: NodeBranchKeyMaterial,
300-
{ encryptionContext }: NodeEncryptionMaterial
291+
{ encryptionContext }: NodeEncryptionMaterial,
292+
utf8Sorting: boolean
301293
): Uint8Array {
302294
// get what we need from branch key material to wrap the pdk
303295
const branchKey = branchKeyMaterials.branchKey()
@@ -326,7 +318,8 @@ export function wrapPlaintextDataKey(
326318
const wrappedAad = wrapAad(
327319
branchKeyIdAsBytes,
328320
branchKeyVersionAsBytesCompressed,
329-
encryptionContext
321+
encryptionContext,
322+
utf8Sorting
330323
)
331324

332325
// encrypt the pdk into an edk
@@ -368,18 +361,22 @@ export function wrapPlaintextDataKey(
368361
export function wrapAad(
369362
branchKeyIdAsBytes: Buffer,
370363
version: Buffer,
371-
encryptionContext: EncryptionContext
364+
encryptionContext: EncryptionContext,
365+
utf8Sorting: boolean
372366
) {
373367
/* Precondition: Branch key version must be 16 bytes */
374368
needs(version.length === 16, 'Branch key version must be 16 bytes')
369+
const { serializeEncryptionContext } = serializeFactory(stringToUtf8Bytes, {
370+
utf8Sorting: utf8Sorting,
371+
})
375372

376373
/* The AAD section is uInt16BE(length) + AAD
377374
* see: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/message-format.html#header-aad
378375
* However, we _only_ need the ADD.
379376
* So, I just slice off the length.
380377
*/
381378
const aad = Buffer.from(
382-
serializeEncryptionContext(encryptionContext, utf8Sorting).slice(2)
379+
serializeEncryptionContext(encryptionContext).slice(2)
383380
)
384381

385382
return Buffer.concat([
@@ -535,7 +532,8 @@ export function destructureCiphertext(
535532
export function unwrapEncryptedDataKey(
536533
ciphertext: Uint8Array,
537534
branchKeyMaterials: NodeBranchKeyMaterial,
538-
{ encryptionContext, suite }: NodeDecryptionMaterial
535+
{ encryptionContext, suite }: NodeDecryptionMaterial,
536+
utf8Sorting: boolean
539537
) {
540538
// get what we need from the branch key materials to unwrap the edk
541539
const branchKey = branchKeyMaterials.branchKey()
@@ -564,7 +562,8 @@ export function unwrapEncryptedDataKey(
564562
const wrappedAad = wrapAad(
565563
branchKeyIdAsBytes,
566564
branchKeyVersionAsBytesCompressed,
567-
encryptionContext
565+
encryptionContext,
566+
utf8Sorting
568567
)
569568

570569
// decipher the edk to get the udk/pdk

modules/kms-keyring-node/test/kms_hkeyring_node.helpers.test.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import { randomBytes } from 'crypto'
55
import {
66
wrapAad,
77
destructureCiphertext,
8-
serializeEncryptionContext,
9-
utf8Sorting,
108
unwrapEncryptedDataKey,
119
wrapPlaintextDataKey,
1210
} from '../src/kms_hkeyring_node_helpers'
@@ -18,6 +16,7 @@ import {
1816
NodeDecryptionMaterial,
1917
NodeEncryptionMaterial,
2018
} from '@aws-crypto/material-management'
19+
import { serializeFactory, SerializeOptions } from '@aws-crypto/serialize'
2120
import { v4 } from 'uuid'
2221

2322
describe('KmsHierarchicalKeyRingNode: helpers', () => {
@@ -110,11 +109,23 @@ describe('KmsHierarchicalKeyRingNode: helpers', () => {
110109
const encryptionContext = {
111110
key: 'value',
112111
}
112+
const utf8Sorting: SerializeOptions = { utf8Sorting: false }
113+
const stringToUtf8Bytes = (input: string): Buffer =>
114+
Buffer.from(input, 'utf-8')
115+
const { serializeEncryptionContext } = serializeFactory(
116+
stringToUtf8Bytes,
117+
utf8Sorting
118+
)
113119

114120
it('Precondition: Branch key version must be 16 bytes ', () => {
115121
const badVersion = randomBytes(15)
116122
expect(() =>
117-
wrapAad(branchKeyIdAsBytes, badVersion, encryptionContext)
123+
wrapAad(
124+
branchKeyIdAsBytes,
125+
badVersion,
126+
encryptionContext,
127+
utf8Sorting.utf8Sorting
128+
)
118129
).to.throw('Branch key version must be 16 bytes')
119130
})
120131

@@ -129,7 +140,8 @@ describe('KmsHierarchicalKeyRingNode: helpers', () => {
129140
wrapAad(
130141
branchKeyIdAsBytes,
131142
branchKeyVersionAsBytes,
132-
unserializeableEc as any
143+
unserializeableEc as any,
144+
utf8Sorting.utf8Sorting
133145
)
134146
).to.throw()
135147
})
@@ -138,7 +150,8 @@ describe('KmsHierarchicalKeyRingNode: helpers', () => {
138150
const wrappedAad = wrapAad(
139151
branchKeyIdAsBytes,
140152
branchKeyVersionAsBytes,
141-
encryptionContext
153+
encryptionContext,
154+
utf8Sorting.utf8Sorting
142155
)
143156

144157
let startIdx = 0
@@ -157,10 +170,7 @@ describe('KmsHierarchicalKeyRingNode: helpers', () => {
157170
).to.deep.equal(branchKeyVersionAsBytes)
158171

159172
startIdx += branchKeyVersionAsBytes.length
160-
const expectedAad = serializeEncryptionContext(
161-
encryptionContext,
162-
utf8Sorting
163-
).slice(2)
173+
const expectedAad = serializeEncryptionContext(encryptionContext).slice(2)
164174
expect(wrappedAad.subarray(startIdx)).to.deep.equal(expectedAad)
165175
})
166176
})
@@ -204,15 +214,18 @@ describe('KmsHierarchicalKeyRingNode: helpers', () => {
204214
algSuite,
205215
encryptionContext
206216
)
217+
const utf8Sorting: SerializeOptions = { utf8Sorting: false }
207218

208219
const actualPdk = unwrapEncryptedDataKey(
209220
wrapPlaintextDataKey(
210221
expectedPdk,
211222
branchKeyMaterial,
212-
encryptionMaterial
223+
encryptionMaterial,
224+
utf8Sorting.utf8Sorting
213225
),
214226
branchKeyMaterial,
215-
decryptionMaterial
227+
decryptionMaterial,
228+
utf8Sorting.utf8Sorting
216229
)
217230
expect(actualPdk).to.deep.equal(expectedPdk)
218231
}
@@ -259,12 +272,14 @@ describe('KmsHierarchicalKeyRingNode: helpers', () => {
259272
algSuite,
260273
encryptionContext
261274
)
275+
const utf8Sorting: SerializeOptions = { utf8Sorting: false }
262276

263277
expect(() =>
264278
unwrapEncryptedDataKey(
265279
ciphertext,
266280
branchKeyMaterial,
267-
decryptionMaterial
281+
decryptionMaterial,
282+
utf8Sorting.utf8Sorting
268283
)
269284
).to.throw('Unsupported state or unable to authenticate data')
270285
}

modules/raw-aes-keyring-browser/src/raw_aes_keyring_browser.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export type RawAesKeyringWebCryptoInput = {
5656
keyName: string
5757
masterKey: AwsEsdkJsCryptoKey
5858
wrappingSuite: WrappingSuiteIdentifier
59+
utf8Sorting?: boolean | true
5960
}
6061

6162
export class RawAesKeyringWebCrypto extends KeyringWebCrypto {
@@ -66,7 +67,8 @@ export class RawAesKeyringWebCrypto extends KeyringWebCrypto {
6667

6768
constructor(input: RawAesKeyringWebCryptoInput) {
6869
super()
69-
const { keyName, keyNamespace, masterKey, wrappingSuite } = input
70+
const { keyName, keyNamespace, masterKey, wrappingSuite, utf8Sorting } =
71+
input
7072
/* Precondition: AesKeyringWebCrypto needs identifying information for encrypt and decrypt. */
7173
needs(keyName && keyNamespace, 'Identifying information must be defined.')
7274
/* Precondition: RawAesKeyringWebCrypto requires a wrappingSuite to be a valid RawAesWrappingSuite. */
@@ -81,7 +83,8 @@ export class RawAesKeyringWebCrypto extends KeyringWebCrypto {
8183
flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY,
8284
})
8385

84-
const serializeOptions: SerializeOptions = { utf8Sorting: false }
86+
const maybeUtf8Sorting = utf8Sorting ?? true
87+
const serializeOptions: SerializeOptions = { utf8Sorting: maybeUtf8Sorting }
8588
const { serializeEncryptionContext } = serializeFactory(
8689
fromUtf8,
8790
serializeOptions
@@ -92,10 +95,9 @@ export class RawAesKeyringWebCrypto extends KeyringWebCrypto {
9295
* However, the RAW Keyring wants _only_ the ADD.
9396
* So, I just slice off the length.
9497
*/
95-
const aad = serializeEncryptionContext(
96-
material.encryptionContext,
97-
serializeOptions
98-
).slice(2)
98+
const aad = serializeEncryptionContext(material.encryptionContext).slice(
99+
2
100+
)
99101
const { keyNamespace, keyName } = this
100102

101103
return aesGcmWrapKey(
@@ -116,10 +118,9 @@ export class RawAesKeyringWebCrypto extends KeyringWebCrypto {
116118
* However, the RAW Keyring wants _only_ the ADD.
117119
* So, I just slice off the length.
118120
*/
119-
const aad = serializeEncryptionContext(
120-
material.encryptionContext,
121-
serializeOptions
122-
).slice(2)
121+
const aad = serializeEncryptionContext(material.encryptionContext).slice(
122+
2
123+
)
123124
const { keyNamespace, keyName } = this
124125

125126
return aesGcmUnwrapKey(

0 commit comments

Comments
 (0)