@@ -12,53 +12,46 @@ import {
12
12
NodeDecryptionMaterial ,
13
13
NodeEncryptionMaterial ,
14
14
} from '@aws-crypto/material-management-node'
15
- import { buildDecrypt } from '../src/index'
15
+ import { buildDecrypt , DecryptOutput } from '../src/index'
16
+ import { buildEncrypt } from '@aws-crypto/encrypt-node'
16
17
import * as fixtures from './fixtures'
17
18
chai . use ( chaiAsPromised )
18
19
const { expect } = chai
19
20
import {
21
+ AlgorithmSuiteIdentifier ,
20
22
CommitmentPolicy ,
21
23
MessageFormat ,
22
24
needs ,
25
+ NodeBranchKeyMaterial ,
23
26
} from '@aws-crypto/material-management'
24
27
25
- import { KmsKeyringNode } from '@aws-crypto/kms-keyring-node'
28
+ import {
29
+ KmsHierarchicalKeyRingNode ,
30
+ KmsKeyringNode ,
31
+ } from '@aws-crypto/kms-keyring-node'
32
+ import { BranchKeyStoreNode } from '@aws-crypto/branch-keystore-node'
33
+
34
+ import { deserializeFactory } from '@aws-crypto/serialize'
35
+ import { NodeAlgorithmSuite } from '@aws-crypto/material-management-node'
36
+ import { readFileSync , writeFileSync } from 'fs'
37
+ const toUtf8 = ( input : Uint8Array ) =>
38
+ Buffer . from ( input . buffer , input . byteOffset , input . byteLength ) . toString ( 'utf8' )
39
+ const deserialize = deserializeFactory ( toUtf8 , NodeAlgorithmSuite )
26
40
27
41
const { decrypt } = buildDecrypt ( CommitmentPolicy . FORBID_ENCRYPT_ALLOW_DECRYPT )
42
+ const { encrypt } = buildEncrypt ( CommitmentPolicy . REQUIRE_ENCRYPT_ALLOW_DECRYPT )
28
43
29
44
describe ( 'committing algorithm test' , ( ) => {
30
45
fixtures . compatibilityVectors ( ) . tests . forEach ( ( test ) => {
31
46
it ( test . comment , async ( ) => {
32
- const {
33
- ciphertext,
34
- status,
35
- 'plaintext-frames' : plaintextFrames ,
36
- commitment,
37
- 'message-id' : messageId ,
38
- 'encryption-context' : encryptionContext ,
39
- } = test
47
+ const { ciphertext, status } = test
40
48
const keyring = buildKeyring ( test )
41
49
if ( status ) {
42
- const { plaintext, messageHeader } = await decrypt (
43
- keyring ,
44
- ciphertext ,
45
- {
46
- encoding : 'base64' ,
47
- }
48
- )
49
- needs (
50
- plaintextFrames && messageHeader . version === MessageFormat . V2 ,
51
- 'Message Failure'
52
- )
53
-
54
- expect ( plaintext . toString ( ) ) . to . equal ( plaintextFrames . join ( '' ) )
55
- expect (
56
- Buffer . from ( messageHeader . suiteData ) . toString ( 'base64' )
57
- ) . to . deep . equal ( commitment )
58
- expect (
59
- Buffer . from ( messageHeader . messageId ) . toString ( 'base64' )
60
- ) . to . deep . equal ( messageId )
61
- expect ( messageHeader . encryptionContext ) . to . deep . equal ( encryptionContext )
50
+ const output = await decrypt ( keyring , ciphertext , {
51
+ encoding : 'base64' ,
52
+ } )
53
+
54
+ ExpectCompatibilityVector ( test , output )
62
55
} else {
63
56
await expect (
64
57
decrypt ( keyring , ciphertext , { encoding : 'base64' } )
@@ -67,26 +60,172 @@ describe('committing algorithm test', () => {
67
60
} )
68
61
} )
69
62
63
+ fixtures . hierarchicalKeyringCompatibilityVectors ( ) . tests . forEach ( ( test ) => {
64
+ it ( `Decrypt test: ${ test . comment } ` , async ( ) => {
65
+ const { ciphertext, status } = test
66
+ const keyring = buildKeyring ( test )
67
+ needs ( status , 'Unexpected Status' )
68
+ const output = await decrypt ( keyring , ciphertext , {
69
+ encoding : 'base64' ,
70
+ } )
71
+
72
+ ExpectCompatibilityVector ( test , output )
73
+ } )
74
+ } )
75
+
76
+ fixtures . hierarchicalKeyringCompatibilityVectors ( ) . tests . forEach ( ( test ) => {
77
+ let once = false
78
+ it ( `Encrypt test: ${ test . comment } ` , async ( ) => {
79
+ const { plaintextBase64, status } = test
80
+ const keyring = buildKeyring ( test )
81
+ needs ( status , 'Unexpected Status' )
82
+ needs ( plaintextBase64 , 'Nothing to encrypt' )
83
+
84
+ const suiteId = AlgorithmSuiteIdentifier . ALG_AES256_GCM_IV12_TAG16_HKDF_SHA512_COMMIT_KEY
85
+ once = true
86
+
87
+ const encryptOutput = await encrypt ( keyring , plaintextBase64 , {
88
+ encoding : 'base64' ,
89
+ suiteId,
90
+ } )
91
+
92
+ const decryptOutput = await decrypt ( keyring , encryptOutput . result )
93
+ expect ( decryptOutput . plaintext . toString ( 'base64' ) ) . to . equal (
94
+ plaintextBase64
95
+ )
96
+ } )
97
+ } )
98
+
99
+ function ExpectCompatibilityVector (
100
+ {
101
+ 'plaintext-frames' : plaintextFrames ,
102
+ plaintextBase64,
103
+ commitment,
104
+ 'message-id' : messageId ,
105
+ 'encryption-context' : encryptionContext ,
106
+ } : fixtures . VectorTest ,
107
+ { plaintext, messageHeader } : DecryptOutput
108
+ ) {
109
+ needs ( messageHeader . version === MessageFormat . V2 , 'Message Failure' )
110
+
111
+ if ( plaintextBase64 ) {
112
+ expect ( plaintext . toString ( 'base64' ) ) . to . equal ( plaintextBase64 )
113
+ }
114
+ if ( plaintextFrames ) {
115
+ expect ( plaintext . toString ( ) ) . to . equal ( plaintextFrames . join ( '' ) )
116
+ }
117
+ expect (
118
+ Buffer . from ( messageHeader . suiteData ) . toString ( 'base64' )
119
+ ) . to . deep . equal ( commitment )
120
+ expect (
121
+ Buffer . from ( messageHeader . messageId ) . toString ( 'base64' )
122
+ ) . to . deep . equal ( messageId )
123
+ expect ( messageHeader . encryptionContext ) . to . deep . equal ( encryptionContext )
124
+ }
125
+
70
126
function buildKeyring ( test : fixtures . VectorTest ) {
71
- if ( test [ 'keyring-type' ] === 'aws-kms' ) {
72
- return new KmsKeyringNode ( { discovery : true } )
127
+ switch ( test [ 'keyring-type' ] ) {
128
+ case 'aws-kms' :
129
+ return new KmsKeyringNode ( { discovery : true } )
130
+ case 'static' :
131
+ const dataKey = Buffer . alloc ( 32 , test [ 'decrypted-dek' ] , 'base64' )
132
+
133
+ return new ( class TestKeyring extends KeyringNode {
134
+ async _onEncrypt ( ) : Promise < NodeEncryptionMaterial > {
135
+ throw new Error ( 'I should never see this error' )
136
+ }
137
+ async _onDecrypt ( material : NodeDecryptionMaterial ) {
138
+ const unencryptedDataKey = dataKey
139
+ const trace = {
140
+ keyNamespace : 'k' ,
141
+ keyName : 'k' ,
142
+ flags : KeyringTraceFlag . WRAPPING_KEY_DECRYPTED_DATA_KEY ,
143
+ }
144
+ return material . setUnencryptedDataKey ( unencryptedDataKey , trace )
145
+ }
146
+ } ) ( )
147
+
148
+ case 'static-branch-key' :
149
+ // This is serious hackery.
150
+ // This is *NOT* recommended.
151
+ // The proper extension point for the KeyStore is _only_ the Storage interface!
152
+ // However, this does let us do some quick test vector testing.
153
+ // At this time this is overly perscriptive,
154
+ // but the expectation is to be able to depracate this
155
+ // in favor of the test vectors project (integration-node)
156
+ const keyStore = {
157
+ __proto__ : BranchKeyStoreNode . prototype ,
158
+ kmsConfiguration : {
159
+ getRegion ( ) {
160
+ return null
161
+ } ,
162
+ } ,
163
+
164
+ getKeyStoreInfo ( ) {
165
+ return {
166
+ logicalKeyStoreName : 'logicalKeyStoreName' ,
167
+ }
168
+ } ,
169
+
170
+ async getBranchKeyVersion (
171
+ branchKeyId : string ,
172
+ branchKeyVersion : string
173
+ ) : Promise < NodeBranchKeyMaterial > {
174
+ needs (
175
+ branchKeyId == 'bd3842ff-3076-4092-9918-4395730050b8' ,
176
+ branchKeyId
177
+ )
178
+ needs (
179
+ branchKeyVersion == 'e9ce18a3-edb5-4272-9f86-1cacb7997ff6' ,
180
+ branchKeyVersion
181
+ )
182
+
183
+ return new NodeBranchKeyMaterial (
184
+ Buffer . from (
185
+ 'tJwf65epYvUt5HMiQsl/6jlvLxS0tgdjIuvFy2BLIwg=' ,
186
+ 'base64'
187
+ ) ,
188
+ branchKeyId ,
189
+ branchKeyVersion ,
190
+ { }
191
+ )
192
+ } ,
193
+ async getActiveBranchKey (
194
+ branchKeyId : string
195
+ ) : Promise < NodeBranchKeyMaterial > {
196
+ needs (
197
+ branchKeyId == 'bd3842ff-3076-4092-9918-4395730050b8' ,
198
+ branchKeyId
199
+ )
200
+
201
+ return new NodeBranchKeyMaterial (
202
+ Buffer . from (
203
+ 'tJwf65epYvUt5HMiQsl/6jlvLxS0tgdjIuvFy2BLIwg=' ,
204
+ 'base64'
205
+ ) ,
206
+ branchKeyId ,
207
+ 'e9ce18a3-edb5-4272-9f86-1cacb7997ff6' ,
208
+ { }
209
+ )
210
+ } ,
211
+
212
+ storage : {
213
+ _config : { } ,
214
+ getKeyStorageInfo ( ) {
215
+ return {
216
+ logicalName : 'logicalKeyStoreName' ,
217
+ }
218
+ } ,
219
+ } ,
220
+ } as any
221
+
222
+ return new KmsHierarchicalKeyRingNode ( {
223
+ branchKeyId : 'bd3842ff-3076-4092-9918-4395730050b8' ,
224
+ keyStore,
225
+ cacheLimitTtl : 1 ,
226
+ } )
73
227
}
74
- needs ( test [ 'keyring-type' ] === 'static' , 'wtf yo' )
75
- const dataKey = Buffer . alloc ( 32 , test [ 'decrypted-dek' ] , 'base64' )
76
228
77
- return new ( class TestKeyring extends KeyringNode {
78
- async _onEncrypt ( ) : Promise < NodeEncryptionMaterial > {
79
- throw new Error ( 'I should never see this error' )
80
- }
81
- async _onDecrypt ( material : NodeDecryptionMaterial ) {
82
- const unencryptedDataKey = dataKey
83
- const trace = {
84
- keyNamespace : 'k' ,
85
- keyName : 'k' ,
86
- flags : KeyringTraceFlag . WRAPPING_KEY_DECRYPTED_DATA_KEY ,
87
- }
88
- return material . setUnencryptedDataKey ( unencryptedDataKey , trace )
89
- }
90
- } ) ( )
229
+ needs ( false , 'Unexpected keyring-type:' + test [ 'keyring-type' ] )
91
230
}
92
231
} )
0 commit comments