6
6
"use strict" ;
7
7
8
8
var helpers = require ( "./helpers.js" ) ,
9
+ util = require ( "../util" ) ,
9
10
CONSTANTS = require ( "./constants.js" ) ,
10
11
GCM = require ( "../deps/ciphermodes/gcm" ) ;
11
12
12
- function gcmEncryptFN ( size ) {
13
+ function gcmEncryptFN ( size , wrap ) {
13
14
function commonChecks ( key , iv ) {
14
15
if ( size !== ( key . length << 3 ) ) {
15
16
throw new Error ( "invalid key size" ) ;
16
17
}
17
- if ( 12 !== iv . length ) {
18
+ if ( ! iv && ! wrap ) {
19
+ throw new Error ( "invalid iv" ) ;
20
+ }
21
+ if ( iv && 12 !== iv . length ) {
18
22
throw new Error ( "invalid iv" ) ;
19
23
}
20
24
}
21
25
26
+ function prepareResults ( results ) {
27
+ if ( wrap ) {
28
+ var iv = util . base64url . encode ( results . iv ) ;
29
+ var tag = util . base64url . encode ( results . tag ) ;
30
+
31
+ results = {
32
+ data : results . data ,
33
+ header : {
34
+ iv : iv ,
35
+ tag : tag
36
+ }
37
+ } ;
38
+ }
39
+
40
+ return results ;
41
+ }
42
+
22
43
// ### 'fallback' implementation -- uses forge
23
44
var fallback = function ( key , pdata , props ) {
24
- var iv = props . iv || Buffer . alloc ( 0 ) ,
45
+ var iv = props . iv ,
25
46
adata = props . aad || props . adata || Buffer . alloc ( 0 ) ,
26
47
cipher ,
27
48
cdata ;
@@ -33,6 +54,8 @@ function gcmEncryptFN(size) {
33
54
return Promise . reject ( err ) ;
34
55
}
35
56
57
+ iv = iv || util . randomBytes ( 12 ) ;
58
+
36
59
// setup cipher
37
60
cipher = GCM . createCipher ( {
38
61
key : key ,
@@ -69,10 +92,11 @@ function gcmEncryptFN(size) {
69
92
70
93
// resolve with output
71
94
var tag = cipher . tag ;
72
- resolve ( {
95
+ resolve ( prepareResults ( {
73
96
data : cdata ,
97
+ iv : iv ,
74
98
tag : tag
75
- } ) ;
99
+ } ) ) ;
76
100
} ) ( ) ;
77
101
} ) ;
78
102
@@ -82,7 +106,7 @@ function gcmEncryptFN(size) {
82
106
// ### WebCryptoAPI implementation
83
107
// TODO: cache CryptoKey sooner
84
108
var webcrypto = function ( key , pdata , props ) {
85
- var iv = props . iv || Buffer . alloc ( 0 ) ,
109
+ var iv = props . iv ,
86
110
adata = props . aad || props . adata || Buffer . alloc ( 0 ) ;
87
111
88
112
try {
@@ -91,6 +115,8 @@ function gcmEncryptFN(size) {
91
115
return Promise . reject ( err ) ;
92
116
}
93
117
118
+ iv = iv || util . randomBytes ( 12 ) ;
119
+
94
120
var alg = {
95
121
name : "AES-GCM"
96
122
} ;
@@ -114,18 +140,19 @@ function gcmEncryptFN(size) {
114
140
var cdata = result . slice ( 0 , tagStart ) ;
115
141
cdata = Buffer . from ( cdata ) ;
116
142
117
- return {
143
+ return prepareResults ( {
118
144
data : cdata ,
145
+ iv : iv ,
119
146
tag : tag
120
- } ;
147
+ } ) ;
121
148
} ) ;
122
149
123
150
return promise ;
124
151
} ;
125
152
126
153
// ### NodeJS implementation
127
154
var nodejs = function ( key , pdata , props ) {
128
- var iv = props . iv || Buffer . alloc ( 0 ) ,
155
+ var iv = props . iv ,
129
156
adata = props . aad || props . adata || Buffer . alloc ( 0 ) ;
130
157
131
158
try {
@@ -134,6 +161,8 @@ function gcmEncryptFN(size) {
134
161
return Promise . reject ( err ) ;
135
162
}
136
163
164
+ iv = iv || util . randomBytes ( 12 ) ;
165
+
137
166
var alg = "aes-" + ( key . length * 8 ) + "-gcm" ;
138
167
var cipher ;
139
168
try {
@@ -154,14 +183,16 @@ function gcmEncryptFN(size) {
154
183
] ) ;
155
184
var tag = cipher . getAuthTag ( ) ;
156
185
157
- return {
186
+ return prepareResults ( {
158
187
data : cdata ,
188
+ iv : iv ,
159
189
tag : tag
160
- } ;
190
+ } ) ;
161
191
} ;
162
192
163
193
return helpers . setupFallback ( nodejs , webcrypto , fallback ) ;
164
194
}
195
+
165
196
function gcmDecryptFN ( size ) {
166
197
function commonChecks ( key , iv , tag ) {
167
198
if ( size !== ( key . length << 3 ) ) {
@@ -331,10 +362,12 @@ var aesGcm = {};
331
362
"A192GCMKW" ,
332
363
"A256GCMKW"
333
364
] . forEach ( function ( alg ) {
334
- var size = parseInt ( / A ( \d + ) G C M (?: K W ) ? / g. exec ( alg ) [ 1 ] ) ;
365
+ var parts = / A ( \d + ) G C M ( K W ) ? / g. exec ( alg ) ;
366
+ var size = parseInt ( parts [ 1 ] ) ;
367
+ var wrap = ( parts [ 2 ] === "KW" ) ;
335
368
aesGcm [ alg ] = {
336
- encrypt : gcmEncryptFN ( size ) ,
337
- decrypt : gcmDecryptFN ( size )
369
+ encrypt : gcmEncryptFN ( size , wrap ) ,
370
+ decrypt : gcmDecryptFN ( size , wrap )
338
371
} ;
339
372
} ) ;
340
373
0 commit comments