Skip to content

Commit 7ec6a04

Browse files
committed
Updates to H-Keyring
1 parent c07c5c5 commit 7ec6a04

File tree

9 files changed

+102
-48
lines changed

9 files changed

+102
-48
lines changed

modules/branch-keystore-node/src/branch_keystore.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,23 @@ interface IBranchKeyStoreNode {
2626
branchKeyId: string,
2727
branchKeyVersion: string
2828
): Promise<NodeBranchKeyMaterial>
29+
getKeyStoreInfo(): KeyStoreInfoOutput
30+
}
31+
32+
export interface KeyStoreInfoOutput {
33+
keystoreId: string
34+
keystoreTableName: string
35+
logicalKeyStoreName: string
36+
grantTokens: string[]
37+
kmsConfiguration: KmsConfig
2938
}
3039

3140
export class BranchKeyStoreNode implements IBranchKeyStoreNode {
32-
// public declare ddbTableName: string
3341
public declare logicalKeyStoreName: string
3442
public declare kmsConfiguration: Readonly<KmsConfig>
3543
public declare kmsClient: KMSClient
36-
// public declare ddbClient: DynamoDBClient
3744
public declare keyStoreId: string
3845
public declare grantTokens?: ReadonlyArray<string>
39-
4046
public declare storage: IBranchKeyStorage
4147

4248
constructor({
@@ -87,6 +93,8 @@ export class BranchKeyStoreNode implements IBranchKeyStoreNode {
8793
}
8894
readOnlyProperty(this, 'storage', this.storage)
8995

96+
needs(logicalKeyStoreName == this.storage.getKeyStorageInfo().logicalName, 'TODO Error')
97+
9098
/* Precondition: Keystore id must be a string */
9199
if (keyStoreId) {
92100
needs(typeof keyStoreId === 'string', 'Keystore id must be a string')
@@ -267,6 +275,17 @@ export class BranchKeyStoreNode implements IBranchKeyStoreNode {
267275
)
268276
return branchKeyMaterials
269277
}
278+
279+
getKeyStoreInfo(): KeyStoreInfoOutput
280+
{
281+
return {
282+
keystoreId: this.keyStoreId,
283+
keystoreTableName: this.storage.getKeyStorageInfo().name,
284+
logicalKeyStoreName: this.logicalKeyStoreName,
285+
grantTokens: !!this.grantTokens ? this.grantTokens.slice() : [],
286+
kmsConfiguration: this.kmsConfiguration
287+
}
288+
}
270289
}
271290

272291
immutableClass(BranchKeyStoreNode)

modules/branch-keystore-node/src/dynamodb_key_storage.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ export class DynamoDBKeyStorage implements IBranchKeyStorage {
109109
ddbBranchKeyRecord[BRANCH_KEY_FIELD]
110110
)
111111
}
112+
113+
getKeyStorageInfo() {
114+
return {
115+
name: this.ddbTableName,
116+
logicalName: this.logicalKeyStoreName
117+
}
118+
}
112119
}
113120

114121
immutableClass(DynamoDBKeyStorage)

modules/branch-keystore-node/src/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ export interface IBranchKeyStorage {
181181
branchKeyId: string,
182182
branchKeyVersion: string
183183
): Promise<EncryptedHierarchicalKey>
184+
185+
//= aws-encryption-sdk-specification/framework/key-store/key-storage.md#interface
186+
//= type=implication
187+
//# - [GetKeyStorageInfo](#getkeystorageinfo)
188+
189+
getKeyStorageInfo(): { name: string, logicalName: string }
184190
}
185191

186192
//= aws-encryption-sdk-specification/framework/key-store/key-storage.md#type
@@ -247,5 +253,4 @@ export interface BranchKeyStoreNodeInput {
247253

248254
//= aws-encryption-sdk-specification/framework/key-store/key-storage.md#interface
249255
//= type=exception
250-
//# - [GetEncryptedBeaconKey](#getencryptedbeaconkey)
251-
//# - [GetKeyStorageInfo](#getkeystorageinfo)
256+
//# - [GetEncryptedBeaconKey](#getencryptedbeaconkey)

modules/caching-materials-manager-node/src/caching_materials_manager_node.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,7 @@ export class NodeCachingMaterialsManager
6767
_cacheEntryHasExceededLimits =
6868
cacheEntryHasExceededLimits<NodeAlgorithmSuite>()
6969
}
70+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#appendix-a-cache-entry-identifier-formulas
71+
//# When accessing the underlying cryptographic materials cache,
72+
//# the hierarchical keyring MUST use the formulas specified in this appendix
73+
//# in order to compute the [cache entry identifier](../cryptographic-materials-cache.md#cache-identifier).

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import { KeyringTraceFlag } from '@aws-crypto/material-management'
55

66
export const ACTIVE_AS_BYTES = Buffer.from('ACTIVE', 'utf-8')
7-
export const CACHE_ENTRY_ID_DIGEST_ALGORITHM = 'sha512'
7+
export const CACHE_ENTRY_ID_DIGEST_ALGORITHM = 'sha384'
88
export const KDF_DIGEST_ALGORITHM_SHA_256 = 'sha256'
99
export const ENCRYPT_FLAGS =
1010
KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY |
@@ -18,7 +18,7 @@ export const PROVIDER_ID_HIERARCHY_AS_BYTES = Buffer.from(
1818
'utf-8'
1919
)
2020
export const DERIVED_BRANCH_KEY_LENGTH = 32
21-
export const CACHE_ENTRY_ID_LENGTH = 32
21+
// export const CACHE_ENTRY_ID_LENGTH = 32
2222
export const KEY_DERIVATION_LABEL = Buffer.from(PROVIDER_ID_HIERARCHY, 'utf-8')
2323
export const CIPHERTEXT_STRUCTURE = {
2424
saltLength: 16,

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,27 @@ import {
4141
stringToUtf8Bytes,
4242
} from './kms_hkeyring_node_helpers'
4343
import {
44-
IBranchKeyStoreNode,
44+
BranchKeyStoreNode,
4545
isIBranchKeyStoreNode,
4646
} from '@aws-crypto/branch-keystore-node'
4747
import {
4848
BranchKeyIdSupplier,
4949
isBranchKeyIdSupplier,
5050
} from '@aws-crypto/kms-keyring'
51+
import { randomBytes } from 'crypto'
5152

5253
export interface KmsHierarchicalKeyRingNodeInput {
5354
branchKeyId?: string
5455
branchKeyIdSupplier?: BranchKeyIdSupplier
55-
keyStore: IBranchKeyStoreNode
56+
keyStore: BranchKeyStoreNode
5657
cacheLimitTtl: number
5758
maxCacheSize?: number
5859
}
5960

6061
export interface IKmsHierarchicalKeyRingNode extends KeyringNode {
6162
branchKeyId?: string
6263
branchKeyIdSupplier?: Readonly<BranchKeyIdSupplier>
63-
keyStore: Readonly<IBranchKeyStoreNode>
64+
keyStore: Readonly<BranchKeyStoreNode>
6465
cacheLimitTtl: number
6566
maxCacheSize: number
6667
_onEncrypt(material: NodeEncryptionMaterial): Promise<NodeEncryptionMaterial>
@@ -76,10 +77,12 @@ export class KmsHierarchicalKeyRingNode
7677
{
7778
public declare branchKeyId?: string
7879
public declare branchKeyIdSupplier?: Readonly<BranchKeyIdSupplier>
79-
public declare keyStore: Readonly<IBranchKeyStoreNode>
80+
public declare keyStore: Readonly<BranchKeyStoreNode>
81+
public declare _logicalKeyStoreName: Buffer
8082
public declare cacheLimitTtl: number
8183
public declare maxCacheSize: number
8284
private _cmc: CryptographicMaterialsCache<NodeAlgorithmSuite>
85+
declare readonly _partition: Buffer
8386

8487
constructor({
8588
branchKeyId,
@@ -90,6 +93,10 @@ export class KmsHierarchicalKeyRingNode
9093
}: KmsHierarchicalKeyRingNodeInput) {
9194
super()
9295

96+
const partition = randomBytes(64)
97+
readOnlyProperty(this, '_partition', partition)
98+
readOnlyProperty(this, '_logicalKeyStoreName', stringToUtf8Bytes(keyStore.logicalKeyStoreName))
99+
93100
/* Precondition: The branch key id must be a string */
94101
if (branchKeyId) {
95102
needs(
@@ -205,7 +212,11 @@ export class KmsHierarchicalKeyRingNode
205212

206213
// compute the cache entry id for the active branch key material that we
207214
// want
208-
const cacheEntryId = getCacheEntryId(branchKeyId)
215+
const cacheEntryId = getCacheEntryId(
216+
this._logicalKeyStoreName,
217+
this._partition,
218+
branchKeyId
219+
)
209220

210221
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
211222
//# If a cache entry is found and the entry's TTL has not expired, the hierarchical keyring MUST use those branch key materials for key wrapping.
@@ -317,6 +328,8 @@ export class KmsHierarchicalKeyRingNode
317328
// compute the cache entry id for the versioned branch key material that we
318329
// want
319330
const cacheEntryId = getCacheEntryId(
331+
this._logicalKeyStoreName,
332+
this._partition,
320333
branchKeyId,
321334
branchKeyVersionAsBytes
322335
)

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

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import {
1919
createHash,
2020
randomBytes,
2121
} from 'crypto'
22-
import { uInt32BE } from '@aws-crypto/serialize'
22+
// import { uInt32BE } from '@aws-crypto/serialize'
2323
import { CryptographicMaterialsCache } from '@aws-crypto/cache-material'
2424
import { kdfCounterMode } from '@aws-crypto/kdf-ctr-mode-node'
2525
import {
26-
ACTIVE_AS_BYTES,
26+
// ACTIVE_AS_BYTES,
2727
CACHE_ENTRY_ID_DIGEST_ALGORITHM,
28-
CACHE_ENTRY_ID_LENGTH,
28+
// CACHE_ENTRY_ID_LENGTH,
2929
CIPHERTEXT_STRUCTURE,
3030
DECRYPT_FLAGS,
3131
DERIVED_BRANCH_KEY_LENGTH,
@@ -50,8 +50,8 @@ export const { uuidv4ToCompressedBytes, decompressBytesToUuidv4 } =
5050
uuidv4Factory(stringToHexBytes, hexBytesToString)
5151
export const { serializeEncryptionContext } =
5252
serializeFactory(stringToUtf8Bytes)
53-
const stringToAsciiBytes = (input: string): Buffer =>
54-
Buffer.from(input, 'ascii')
53+
// const stringToAsciiBytes = (input: string): Buffer =>
54+
// Buffer.from(input, 'ascii')
5555

5656
export function getBranchKeyId(
5757
{ branchKeyId, branchKeyIdSupplier }: IKmsHierarchicalKeyRingNode,
@@ -68,45 +68,51 @@ export function getBranchKeyId(
6868
)
6969
}
7070

71+
const RESOURCE_ID = new Uint8Array([0x02])
72+
const NULL_BYTE = new Uint8Array([0x00])
73+
const DECRYPTION_SCOPE = new Uint8Array([0x02])
74+
const ENCRYPTION_SCOPE = new Uint8Array([0x01])
75+
7176
export function getCacheEntryId(
77+
logicalKeyStoreName: Buffer,
78+
partitionId: Buffer,
7279
branchKeyId: string,
7380
versionAsBytes?: Buffer
7481
): string {
7582
// get branch key id as a byte array
7683
const branchKeyIdAsBytes = stringToUtf8Bytes(branchKeyId)
7784

78-
// convert version to ascii bytes if supplied
79-
let versionAsAsciiBytes: Buffer | undefined = undefined
80-
if (versionAsBytes) {
81-
const versionAsString = utf8BytesToString(versionAsBytes)
82-
// conversion will always work because version is a uuid
83-
versionAsAsciiBytes = stringToAsciiBytes(versionAsString)
84-
}
85-
86-
// get the length of the branch key id buffer as a byte array
87-
const lengthAsBytes = uInt32BE(branchKeyId.length)
88-
89-
// encrypt the branch key id buffer with sha512
90-
const branchKeyDigest = createHash(CACHE_ENTRY_ID_DIGEST_ALGORITHM)
91-
.update(branchKeyIdAsBytes)
92-
.digest()
93-
94-
// form a buffer for the cache entry id
95-
const identifier = Buffer.concat([
96-
lengthAsBytes,
97-
branchKeyDigest,
98-
new Uint8Array([0x00]),
99-
versionAsAsciiBytes || ACTIVE_AS_BYTES,
85+
const entryInfo = versionAsBytes
86+
? Buffer.concat([
87+
RESOURCE_ID,
88+
NULL_BYTE,
89+
DECRYPTION_SCOPE,
90+
NULL_BYTE,
91+
partitionId,
92+
NULL_BYTE,
93+
logicalKeyStoreName,
94+
NULL_BYTE,
95+
branchKeyIdAsBytes,
96+
NULL_BYTE,
97+
versionAsBytes
10098
])
99+
: Buffer.concat([
100+
RESOURCE_ID,
101+
NULL_BYTE,
102+
ENCRYPTION_SCOPE,
103+
NULL_BYTE,
104+
partitionId,
105+
NULL_BYTE,
106+
logicalKeyStoreName,
107+
NULL_BYTE,
108+
branchKeyIdAsBytes
109+
])
101110

102-
// encrypt the cache entry id buffer with sha512
103-
const cacheDigest = createHash(CACHE_ENTRY_ID_DIGEST_ALGORITHM)
104-
.update(identifier)
111+
// encrypt the branch key id buffer with sha512
112+
return createHash(CACHE_ENTRY_ID_DIGEST_ALGORITHM)
113+
.update(entryInfo)
105114
.digest()
106-
107-
// get the first 32 bytes of the digest
108-
// get the cache entry id as a string
109-
return cacheDigest.subarray(0, CACHE_ENTRY_ID_LENGTH).toString()
115+
.toString()
110116
}
111117

112118
export async function getBranchKeyMaterials(

modules/kms-keyring-node/test/fixtures.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const TEST_ESDK_ALG_SUITE = new NodeAlgorithmSuite(
2727
)
2828
export const TTL = 1 * 60000 * 10
2929
export const KEYSTORE = new BranchKeyStoreNode({
30-
ddbTableName: DDB_TABLE_NAME,
30+
storage: {ddbTableName: DDB_TABLE_NAME},
3131
logicalKeyStoreName: LOGICAL_KEYSTORE_NAME,
3232
kmsConfiguration: new SrkCompatibilityKmsConfig(KEY_ARN),
3333
})

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const branchKeyId = BRANCH_KEY_ID
2727
const cacheLimitTtl = TTL
2828
const maxCacheSize = 1000
2929
const keyStore = new BranchKeyStoreNode({
30-
ddbTableName: DDB_TABLE_NAME,
30+
storage: {ddbTableName: DDB_TABLE_NAME},
3131
logicalKeyStoreName: LOGICAL_KEYSTORE_NAME,
3232
kmsConfiguration: new SrkCompatibilityKmsConfig(KEY_ARN),
3333
})

0 commit comments

Comments
 (0)