Skip to content

Commit 139cc00

Browse files
committed
feat: Support AWS SDK V2
Addresses feedback in #1177: #1177 (review)
1 parent e21f779 commit 139cc00

File tree

8 files changed

+547
-14419
lines changed

8 files changed

+547
-14419
lines changed

modules/kms-keyring-browser/test/kms_keyring_browser.test.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import * as chai from 'chai'
77
import chaiAsPromised from 'chai-as-promised'
88
import { KmsKeyringBrowser, getClient } from '../src/index'
9+
import { KMS as V2KMS } from 'aws-sdk'
910
import { KMS as V3KMS } from '@aws-sdk/client-kms'
1011
import {
1112
KeyringWebCrypto,
@@ -29,7 +30,7 @@ describe('KmsKeyringBrowser::constructor', () => {
2930
const keyArn =
3031
'arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f'
3132
const keyIds = [keyArn]
32-
const clientProvider = getClient(V3KMS, { credentials })
33+
const clientProvider = getClient(V2KMS, { credentials })
3334

3435
const test = new KmsKeyringBrowser({
3536
clientProvider,
@@ -50,6 +51,46 @@ describe('KmsKeyringBrowser::constructor', () => {
5051
})
5152
})
5253

54+
describe('KmsKeyringBrowser can encrypt/decrypt with AWS SDK v2 client', () => {
55+
const generatorKeyId =
56+
'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'
57+
const keyArn =
58+
'arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f'
59+
const keyIds = [keyArn]
60+
const clientProvider = getClient(V2KMS, { credentials })
61+
const keyring = new KmsKeyringBrowser({
62+
clientProvider,
63+
generatorKeyId,
64+
keyIds,
65+
})
66+
let encryptedDataKey: EncryptedDataKey
67+
68+
it('can encrypt and create unencrypted data key', async () => {
69+
const suite = new WebCryptoAlgorithmSuite(
70+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
71+
)
72+
const material = new WebCryptoEncryptionMaterial(suite, {})
73+
const test = await keyring.onEncrypt(material)
74+
expect(test.hasValidKey()).to.equal(true)
75+
const udk = test.getUnencryptedDataKey()
76+
expect(udk).to.have.lengthOf(suite.keyLengthBytes)
77+
expect(test.encryptedDataKeys).to.have.lengthOf(2)
78+
const [edk] = test.encryptedDataKeys
79+
encryptedDataKey = edk
80+
})
81+
82+
it('can decrypt an EncryptedDataKey', async () => {
83+
const suite = new WebCryptoAlgorithmSuite(
84+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
85+
)
86+
const material = new WebCryptoDecryptionMaterial(suite, {})
87+
const test = await keyring.onDecrypt(material, [encryptedDataKey])
88+
expect(test.hasValidKey()).to.equal(true)
89+
// The UnencryptedDataKey should be zeroed, because the cryptoKey has been set
90+
expect(() => test.getUnencryptedDataKey()).to.throw()
91+
})
92+
})
93+
5394
describe('KmsKeyringBrowser can encrypt/decrypt with AWS SDK v3 client', () => {
5495
const generatorKeyId =
5596
'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'

modules/kms-keyring-browser/test/kms_mrk_discovery_keyring_browser.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
AlgorithmSuiteIdentifier,
1717
WebCryptoDecryptionMaterial,
1818
} from '@aws-crypto/material-management-browser'
19+
import { KMS as V2KMS } from 'aws-sdk'
1920
import { KMS as V3KMS } from '@aws-sdk/client-kms'
2021

2122
chai.use(chaiAsPromised)
@@ -56,6 +57,54 @@ describe('AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser::constructor', () => {
5657
/* Injected from @aws-sdk/karma-credential-loader. */
5758
declare const credentials: any
5859

60+
describe('AwsKmsMrkAwareSymmetricKeyringBrowser can encrypt/decrypt with AWS SDK v2 client', () => {
61+
const discoveryFilter = { accountIDs: ['658956600833'], partition: 'aws' }
62+
63+
const eastKeyId =
64+
'arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7'
65+
const grantTokens = ['grant']
66+
const encryptionContext = { some: 'context' }
67+
const suite = new WebCryptoAlgorithmSuite(
68+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
69+
)
70+
71+
const keyring = new AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser({
72+
// Note the difference in the region from the keyId
73+
client: new V2KMS({ region: 'us-west-2', credentials }),
74+
discoveryFilter,
75+
grantTokens,
76+
})
77+
78+
it('throws an error on encrypt', async () => {
79+
const material = new WebCryptoEncryptionMaterial(suite, encryptionContext)
80+
return expect(keyring.onEncrypt(material)).to.rejectedWith(
81+
Error,
82+
'AwsKmsMrkAwareSymmetricDiscoveryKeyring cannot be used to encrypt'
83+
)
84+
})
85+
86+
it('can decrypt an EncryptedDataKey', async () => {
87+
const encryptKeyring = new AwsKmsMrkAwareSymmetricKeyringBrowser({
88+
client: new V2KMS({ region: 'us-east-1', credentials }),
89+
keyId: eastKeyId,
90+
grantTokens,
91+
})
92+
const encryptMaterial = await encryptKeyring.onEncrypt(
93+
new WebCryptoEncryptionMaterial(suite, encryptionContext)
94+
)
95+
const [edk] = encryptMaterial.encryptedDataKeys
96+
97+
const material = await keyring.onDecrypt(
98+
new WebCryptoDecryptionMaterial(suite, encryptionContext),
99+
[edk]
100+
)
101+
const test = await keyring.onDecrypt(material, [edk])
102+
expect(test.hasValidKey()).to.equal(true)
103+
// The UnencryptedDataKey should be zeroed, because the cryptoKey has been set
104+
expect(() => test.getUnencryptedDataKey()).to.throw()
105+
})
106+
})
107+
59108
describe('AwsKmsMrkAwareSymmetricKeyringBrowser can encrypt/decrypt with AWS SDK v3 client', () => {
60109
const discoveryFilter = { accountIDs: ['658956600833'], partition: 'aws' }
61110

modules/kms-keyring-browser/test/kms_mrk_keyring_browser.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
WebCryptoDecryptionMaterial,
1616
KeyringTraceFlag,
1717
} from '@aws-crypto/material-management-browser'
18+
import { KMS as V2KMS } from 'aws-sdk'
1819
import { KMS as V3KMS } from '@aws-sdk/client-kms'
1920

2021
chai.use(chaiAsPromised)
@@ -50,6 +51,69 @@ describe('AwsKmsMrkAwareSymmetricKeyringBrowser::constructor', () => {
5051
/* Injected from @aws-sdk/karma-credential-loader. */
5152
declare const credentials: any
5253

54+
describe('AwsKmsMrkAwareSymmetricKeyringBrowser can encrypt/decrypt with AWS SDK v2 client', () => {
55+
const westKeyId =
56+
'arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7'
57+
const eastKeyId =
58+
'arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7'
59+
const grantTokens = ['grant']
60+
const encryptionContext = { some: 'context' }
61+
const suite = new WebCryptoAlgorithmSuite(
62+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
63+
)
64+
65+
const encryptKeyring = new AwsKmsMrkAwareSymmetricKeyringBrowser({
66+
client: new V2KMS({ region: 'us-west-2', credentials }),
67+
keyId: westKeyId,
68+
grantTokens,
69+
})
70+
const decryptKeyring = new AwsKmsMrkAwareSymmetricKeyringBrowser({
71+
client: new V2KMS({ region: 'us-east-1', credentials }),
72+
keyId: eastKeyId,
73+
grantTokens,
74+
})
75+
let encryptedDataKey: EncryptedDataKey
76+
77+
it('can encrypt and create unencrypted data key', async () => {
78+
const material = new WebCryptoEncryptionMaterial(suite, encryptionContext)
79+
const test = await encryptKeyring.onEncrypt(material)
80+
expect(test.hasValidKey()).to.equal(true)
81+
const udk = test.getUnencryptedDataKey()
82+
expect(udk).to.have.lengthOf(suite.keyLengthBytes)
83+
expect(test.encryptedDataKeys).to.have.lengthOf(1)
84+
const [edk] = test.encryptedDataKeys
85+
encryptedDataKey = edk
86+
})
87+
88+
it('can encrypt a pre-existing plaintext data key', async () => {
89+
const seedMaterial = new WebCryptoEncryptionMaterial(
90+
suite,
91+
encryptionContext
92+
).setUnencryptedDataKey(new Uint8Array(suite.keyLengthBytes), {
93+
keyName: 'keyName',
94+
keyNamespace: 'keyNamespace',
95+
flags: KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY,
96+
})
97+
const encryptTest = await encryptKeyring.onEncrypt(seedMaterial)
98+
expect(encryptTest.hasValidKey()).to.equal(true)
99+
expect(encryptTest.encryptedDataKeys).to.have.lengthOf(1)
100+
const [kmsEDK] = encryptTest.encryptedDataKeys
101+
expect(kmsEDK.providerId).to.equal('aws-kms')
102+
expect(kmsEDK.providerInfo).to.equal(westKeyId)
103+
})
104+
105+
it('can decrypt an EncryptedDataKey', async () => {
106+
const suite = new WebCryptoAlgorithmSuite(
107+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
108+
)
109+
const material = new WebCryptoDecryptionMaterial(suite, encryptionContext)
110+
const test = await decryptKeyring.onDecrypt(material, [encryptedDataKey])
111+
expect(test.hasValidKey()).to.equal(true)
112+
// The UnencryptedDataKey should be zeroed, because the cryptoKey has been set
113+
expect(() => test.getUnencryptedDataKey()).to.throw()
114+
})
115+
})
116+
53117
describe('AwsKmsMrkAwareSymmetricKeyringBrowser can encrypt/decrypt with AWS SDK v3 client', () => {
54118
const westKeyId =
55119
'arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7'

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import { expect } from 'chai'
77
import { KmsKeyringNode, getClient } from '../src/index'
8+
import { KMS as V2KMS } from 'aws-sdk'
89
import { KMS as V3KMS } from '@aws-sdk/client-kms'
910
import {
1011
KeyringNode,
@@ -39,6 +40,44 @@ describe('KmsKeyringNode::constructor', () => {
3940
})
4041
})
4142

43+
describe('KmsKeyringNode can encrypt/decrypt with AWS SDK v2 client', () => {
44+
const generatorKeyId =
45+
'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'
46+
const keyArn =
47+
'arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f'
48+
const keyIds = [keyArn]
49+
50+
const clientProvider = getClient(V2KMS)
51+
52+
const keyring = new KmsKeyringNode({ clientProvider, generatorKeyId, keyIds })
53+
let encryptedDataKey: EncryptedDataKey
54+
let udk: Uint8Array
55+
56+
it('can encrypt and create unencrypted data key', async () => {
57+
const suite = new NodeAlgorithmSuite(
58+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
59+
)
60+
const material = new NodeEncryptionMaterial(suite, {})
61+
const test = await keyring.onEncrypt(material)
62+
expect(test.hasValidKey()).to.equal(true)
63+
udk = unwrapDataKey(test.getUnencryptedDataKey())
64+
expect(udk).to.have.lengthOf(suite.keyLengthBytes)
65+
expect(test.encryptedDataKeys).to.have.lengthOf(2)
66+
const [edk] = test.encryptedDataKeys
67+
encryptedDataKey = edk
68+
})
69+
70+
it('can decrypt an EncryptedDataKey', async () => {
71+
const suite = new NodeAlgorithmSuite(
72+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
73+
)
74+
const material = new NodeDecryptionMaterial(suite, {})
75+
const test = await keyring.onDecrypt(material, [encryptedDataKey])
76+
expect(test.hasValidKey()).to.equal(true)
77+
expect(unwrapDataKey(test.getUnencryptedDataKey())).to.deep.equal(udk)
78+
})
79+
})
80+
4281
describe('KmsKeyringNode can encrypt/decrypt with AWS SDK v3 client', () => {
4382
const generatorKeyId =
4483
'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '@aws-crypto/material-management-node'
1818
chai.use(chaiAsPromised)
1919
const { expect } = chai
20+
import { KMS as V2KMS } from 'aws-sdk'
2021
import { KMS as V3KMS } from '@aws-sdk/client-kms'
2122

2223
describe('AwsKmsMrkAwareSymmetricKeyringNode::constructor', () => {
@@ -51,6 +52,54 @@ describe('AwsKmsMrkAwareSymmetricKeyringNode::constructor', () => {
5152
})
5253
})
5354

55+
describe('AwsKmsMrkAwareSymmetricDiscoveryKeyringNode can encrypt/decrypt with AWS SDK v2 client', () => {
56+
const discoveryFilter = { accountIDs: ['658956600833'], partition: 'aws' }
57+
const keyId =
58+
'arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f'
59+
const grantTokens = ['grant']
60+
const encryptionContext = { some: 'context' }
61+
const suite = new NodeAlgorithmSuite(
62+
AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA256
63+
)
64+
const client = new V2KMS({ region: 'us-west-2' })
65+
66+
const keyring = new AwsKmsMrkAwareSymmetricDiscoveryKeyringNode({
67+
client,
68+
discoveryFilter,
69+
grantTokens,
70+
})
71+
it('throws an error on encrypt', async () => {
72+
const material = new NodeEncryptionMaterial(suite, encryptionContext)
73+
await expect(keyring.onEncrypt(material)).to.rejectedWith(
74+
Error,
75+
'AwsKmsMrkAwareSymmetricDiscoveryKeyring cannot be used to encrypt'
76+
)
77+
})
78+
79+
it('can decrypt an EncryptedDataKey', async () => {
80+
const { CiphertextBlob } = await client
81+
.generateDataKey({
82+
KeyId: keyId,
83+
NumberOfBytes: suite.keyLengthBytes,
84+
EncryptionContext: encryptionContext,
85+
})
86+
.promise()
87+
needs(Buffer.isBuffer(CiphertextBlob), 'never')
88+
const edk = new EncryptedDataKey({
89+
providerId: 'aws-kms',
90+
providerInfo: keyId,
91+
encryptedDataKey: new Uint8Array(CiphertextBlob),
92+
})
93+
94+
const material = await keyring.onDecrypt(
95+
new NodeDecryptionMaterial(suite, encryptionContext),
96+
[edk]
97+
)
98+
const decryptTest = await keyring.onDecrypt(material, [edk])
99+
expect(decryptTest.hasValidKey()).to.equal(true)
100+
})
101+
})
102+
54103
describe('AwsKmsMrkAwareSymmetricDiscoveryKeyringNode can encrypt/decrypt with AWS SDK v3 client', () => {
55104
const discoveryFilter = { accountIDs: ['658956600833'], partition: 'aws' }
56105
const keyId =

0 commit comments

Comments
 (0)