@@ -23,6 +23,120 @@ function fixSalt(hmac, kw, salt) {
23
23
return Buffer . concat ( output ) ;
24
24
}
25
25
26
+ function pbkdf2Fn ( hash ) {
27
+ function prepareProps ( props ) {
28
+ props = props || { } ;
29
+ var keyLen = props . length || 0 ;
30
+ var salt = util . asBuffer ( props . salt || new Buffer ( 0 ) , "base64u4l" ) ,
31
+ itrs = props . iterations || 0 ;
32
+
33
+ if ( 0 >= keyLen ) {
34
+ throw new Error ( "invalid key length" ) ;
35
+ }
36
+ if ( 0 >= itrs ) {
37
+ throw new Error ( "invalid iteration count" ) ;
38
+ }
39
+
40
+ props . length = keyLen ;
41
+ props . salt = salt ;
42
+ props . iterations = itrs ;
43
+
44
+ return props ;
45
+ }
46
+
47
+ var fallback = function ( key , props ) {
48
+ try {
49
+ props = prepareProps ( props ) ;
50
+ } catch ( err ) {
51
+ return Promise . reject ( err ) ;
52
+ }
53
+
54
+ var keyLen = props . length ,
55
+ salt = props . salt ,
56
+ itrs = props . iterations ;
57
+
58
+ var promise = new Promise ( function ( resolve , reject ) {
59
+ var md = forge . md [ hash . replace ( "-" , "" ) . toLowerCase ( ) ] . create ( ) ;
60
+ var cb = function ( err , dk ) {
61
+ if ( err ) {
62
+ reject ( err ) ;
63
+ } else {
64
+ dk = new Buffer ( dk , "binary" ) ;
65
+ resolve ( dk ) ;
66
+ }
67
+ } ;
68
+
69
+ forge . pkcs5 . pbkdf2 ( key . toString ( "binary" ) ,
70
+ salt . toString ( "binary" ) ,
71
+ itrs ,
72
+ keyLen ,
73
+ md ,
74
+ cb ) ;
75
+ } ) ;
76
+ return promise ;
77
+ } ;
78
+ var webcrypto = function ( key , props ) {
79
+ try {
80
+ props = prepareProps ( props ) ;
81
+ } catch ( err ) {
82
+ return Promise . reject ( err ) ;
83
+ }
84
+
85
+ var keyLen = props . length ,
86
+ salt = props . salt ,
87
+ itrs = props . iterations ;
88
+
89
+ var promise = Promise . resolve ( key ) ;
90
+ promise = promise . then ( function ( keyval ) {
91
+ return helpers . subtleCrypto . importKey ( "raw" , keyval , "PBKDF2" , false , [ "deriveBits" ] ) ;
92
+ } ) ;
93
+ promise = promise . then ( function ( key ) {
94
+ var mainAlgo = {
95
+ name : "PBKDF2" ,
96
+ salt : salt ,
97
+ iterations : itrs ,
98
+ hash : hash
99
+ } ;
100
+
101
+ return helpers . subtleCrypto . deriveBits ( mainAlgo , key , keyLen * 8 ) ;
102
+ } ) ;
103
+ promise = promise . then ( function ( result ) {
104
+ return util . asBuffer ( result ) ;
105
+ } ) ;
106
+ return promise ;
107
+ } ;
108
+ var nodejs = function ( key , props ) {
109
+ if ( 6 > helpers . nodeCrypto . pbkdf2 . length ) {
110
+ throw new Error ( "unsupported algorithm: PBES2-" + hmac + "+" + kw ) ;
111
+ }
112
+
113
+ try {
114
+ props = prepareProps ( props ) ;
115
+ } catch ( err ) {
116
+ return Promise . reject ( err ) ;
117
+ }
118
+
119
+ var keyLen = props . length ,
120
+ salt = props . salt ,
121
+ itrs = props . iterations ;
122
+
123
+ var md = hash . replace ( "-" , "" ) ;
124
+ var promise = new Promise ( function ( resolve , reject ) {
125
+ function cb ( err , dk ) {
126
+ if ( err ) {
127
+ reject ( err ) ;
128
+ } else {
129
+ resolve ( dk ) ;
130
+ }
131
+ }
132
+ helpers . nodeCrypto . pbkdf2 ( key , salt , itrs , keyLen , md , cb ) ;
133
+ } ) ;
134
+ return promise ;
135
+ } ;
136
+
137
+ return helpers . setupFallback ( nodejs , webcrypto , fallback ) ;
138
+ }
139
+
26
140
function pbes2EncryptFN ( hmac , kw ) {
27
141
var keyLen = CONSTANTS . KEYLENGTH [ kw ] / 8 ;
28
142
@@ -33,11 +147,10 @@ function pbes2EncryptFN(hmac, kw) {
33
147
itrs = props . p2c || 0 ;
34
148
35
149
if ( 0 >= itrs ) {
36
- return Promise . reject ( new Error ( "invalid iteration count" ) ) ;
150
+ throw new Error ( "invalid iteration count" ) ;
37
151
}
38
-
39
152
if ( 8 > salt . length ) {
40
- return Promise . reject ( new Error ( "salt too small" ) ) ;
153
+ throw new Error ( "salt too small" ) ;
41
154
}
42
155
salt = fixSalt ( hmac , kw , salt ) ;
43
156
@@ -71,14 +184,16 @@ function pbes2EncryptFN(hmac, kw) {
71
184
} ;
72
185
73
186
var webcrypto = function ( key , pdata , props ) {
187
+ props = props || { } ;
188
+
74
189
var salt = util . asBuffer ( props . p2s || new Buffer ( 0 ) , "base64url" ) ,
75
190
itrs = props . p2c || 0 ;
76
191
77
192
if ( 0 >= itrs ) {
78
- return Promise . reject ( new Error ( "invalid iteration count" ) ) ;
193
+ throw new Error ( "invalid iteration count" ) ;
79
194
}
80
195
if ( 8 > salt . length ) {
81
- return Promise . reject ( new Error ( "salt too small" ) ) ;
196
+ throw new Error ( "salt too small" ) ;
82
197
}
83
198
salt = fixSalt ( hmac , kw , salt ) ;
84
199
@@ -139,11 +254,10 @@ function pbes2EncryptFN(hmac, kw) {
139
254
itrs = props . p2c || 0 ;
140
255
141
256
if ( 0 >= itrs ) {
142
- return Promise . reject ( new Error ( "invalid iteration count" ) ) ;
257
+ throw new Error ( "invalid iteration count" ) ;
143
258
}
144
-
145
259
if ( 8 > salt . length ) {
146
- return Promise . reject ( new Error ( "salt too small" ) ) ;
260
+ throw new Error ( "salt too small" ) ;
147
261
}
148
262
salt = fixSalt ( hmac , kw , salt ) ;
149
263
@@ -316,9 +430,22 @@ function pbes2DecryptFN(hmac, kw) {
316
430
}
317
431
318
432
// ### Public API
433
+ var pbes2 = { } ;
434
+
435
+ // * [name].derive
436
+ [
437
+ "PBKDF2-SHA-256" ,
438
+ "PBKDF2-SHA-384" ,
439
+ "PBKDF2-SHA-512"
440
+ ] . forEach ( function ( alg ) {
441
+ var hash = alg . replace ( "PBKDF2-" , "" ) ;
442
+ pbes2 [ alg ] = {
443
+ derive : pbkdf2Fn ( hash )
444
+ } ;
445
+ } ) ;
446
+
319
447
// [name].encrypt
320
448
// [name].decrypt
321
- var pbes2 = { } ;
322
449
[
323
450
"PBES2-HS256+A128KW" ,
324
451
"PBES2-HS384+A192KW" ,
0 commit comments