6
6
ObjectDefineProperties,
7
7
ObjectDefineProperty,
8
8
ObjectSetPrototypeOf,
9
+ SafeSet,
9
10
Symbol,
10
11
SymbolToStringTag,
11
12
Uint8Array,
@@ -49,6 +50,8 @@ const {
49
50
kKeyObject,
50
51
getArrayBufferOrView,
51
52
bigIntArrayToUnsignedBigInt,
53
+ normalizeAlgorithm,
54
+ hasAnyNotIn,
52
55
} = require ( 'internal/crypto/util' ) ;
53
56
54
57
const {
@@ -65,6 +68,7 @@ const {
65
68
const {
66
69
customInspectSymbol : kInspect ,
67
70
kEnumerableProperty,
71
+ lazyDOMException,
68
72
} = require ( 'internal/util' ) ;
69
73
70
74
const { inspect } = require ( 'internal/util/inspect' ) ;
@@ -148,6 +152,8 @@ const {
148
152
} ,
149
153
} ) ;
150
154
155
+ let webidl ;
156
+
151
157
class SecretKeyObject extends KeyObject {
152
158
constructor ( handle ) {
153
159
super ( 'secret' , handle ) ;
@@ -168,6 +174,51 @@ const {
168
174
}
169
175
return this [ kHandle ] . export ( ) ;
170
176
}
177
+
178
+ toCryptoKey ( algorithm , extractable , keyUsages ) {
179
+ webidl ??= require ( 'internal/crypto/webidl' ) ;
180
+ algorithm = normalizeAlgorithm ( webidl . converters . AlgorithmIdentifier ( algorithm ) , 'importKey' ) ;
181
+ extractable = webidl . converters . boolean ( extractable ) ;
182
+ keyUsages = webidl . converters [ 'sequence<KeyUsage>' ] ( keyUsages ) ;
183
+
184
+ let result ;
185
+ switch ( algorithm . name ) {
186
+ case 'HMAC' :
187
+ result = require ( 'internal/crypto/mac' )
188
+ . hmacImportKey ( 'KeyObject' , this , algorithm , extractable , keyUsages ) ;
189
+ break ;
190
+ case 'AES-CTR' :
191
+ // Fall through
192
+ case 'AES-CBC' :
193
+ // Fall through
194
+ case 'AES-GCM' :
195
+ // Fall through
196
+ case 'AES-KW' :
197
+ result = require ( 'internal/crypto/aes' )
198
+ . aesImportKey ( algorithm , 'KeyObject' , this , extractable , keyUsages ) ;
199
+ break ;
200
+ case 'HKDF' :
201
+ // Fall through
202
+ case 'PBKDF2' :
203
+ result = importGenericSecretKey (
204
+ algorithm ,
205
+ 'KeyObject' ,
206
+ this ,
207
+ extractable ,
208
+ keyUsages ) ;
209
+ break ;
210
+ default :
211
+ throw lazyDOMException ( 'Unrecognized algorithm name' , 'NotSupportedError' ) ;
212
+ }
213
+
214
+ if ( result . usages . length === 0 ) {
215
+ throw lazyDOMException (
216
+ `Usages cannot be empty when importing a ${ result . type } key.` ,
217
+ 'SyntaxError' ) ;
218
+ }
219
+
220
+ return result ;
221
+ }
171
222
}
172
223
173
224
const kAsymmetricKeyType = Symbol ( 'kAsymmetricKeyType' ) ;
@@ -209,6 +260,51 @@ const {
209
260
return { } ;
210
261
}
211
262
}
263
+
264
+ toCryptoKey ( algorithm , extractable , keyUsages ) {
265
+ webidl ??= require ( 'internal/crypto/webidl' ) ;
266
+ algorithm = normalizeAlgorithm ( webidl . converters . AlgorithmIdentifier ( algorithm ) , 'importKey' ) ;
267
+ extractable = webidl . converters . boolean ( extractable ) ;
268
+ keyUsages = webidl . converters [ 'sequence<KeyUsage>' ] ( keyUsages ) ;
269
+
270
+ let result ;
271
+ switch ( algorithm . name ) {
272
+ case 'RSASSA-PKCS1-v1_5' :
273
+ // Fall through
274
+ case 'RSA-PSS' :
275
+ // Fall through
276
+ case 'RSA-OAEP' :
277
+ result = require ( 'internal/crypto/rsa' )
278
+ . rsaImportKey ( 'KeyObject' , this , algorithm , extractable , keyUsages ) ;
279
+ break ;
280
+ case 'ECDSA' :
281
+ // Fall through
282
+ case 'ECDH' :
283
+ result = require ( 'internal/crypto/ec' )
284
+ . ecImportKey ( 'KeyObject' , this , algorithm , extractable , keyUsages ) ;
285
+ break ;
286
+ case 'Ed25519' :
287
+ // Fall through
288
+ case 'Ed448' :
289
+ // Fall through
290
+ case 'X25519' :
291
+ // Fall through
292
+ case 'X448' :
293
+ result = require ( 'internal/crypto/cfrg' )
294
+ . cfrgImportKey ( 'KeyObject' , this , algorithm , extractable , keyUsages ) ;
295
+ break ;
296
+ default :
297
+ throw lazyDOMException ( 'Unrecognized algorithm name' , 'NotSupportedError' ) ;
298
+ }
299
+
300
+ if ( result . type === 'private' && result . usages . length === 0 ) {
301
+ throw lazyDOMException (
302
+ `Usages cannot be empty when importing a ${ result . type } key.` ,
303
+ 'SyntaxError' ) ;
304
+ }
305
+
306
+ return result ;
307
+ }
212
308
}
213
309
214
310
class PublicKeyObject extends AsymmetricKeyObject {
@@ -801,6 +897,68 @@ function isCryptoKey(obj) {
801
897
return obj != null && obj [ kKeyObject ] !== undefined ;
802
898
}
803
899
900
+ function importGenericSecretKey (
901
+ { name, length } ,
902
+ format ,
903
+ keyData ,
904
+ extractable ,
905
+ keyUsages ) {
906
+ const usagesSet = new SafeSet ( keyUsages ) ;
907
+ if ( extractable )
908
+ throw lazyDOMException ( `${ name } keys are not extractable` , 'SyntaxError' ) ;
909
+
910
+ if ( hasAnyNotIn ( usagesSet , [ 'deriveKey' , 'deriveBits' ] ) ) {
911
+ throw lazyDOMException (
912
+ `Unsupported key usage for a ${ name } key` ,
913
+ 'SyntaxError' ) ;
914
+ }
915
+
916
+ switch ( format ) {
917
+ case 'KeyObject' : {
918
+ if ( hasAnyNotIn ( usagesSet , [ 'deriveKey' , 'deriveBits' ] ) ) {
919
+ throw lazyDOMException (
920
+ `Unsupported key usage for a ${ name } key` ,
921
+ 'SyntaxError' ) ;
922
+ }
923
+
924
+ const checkLength = keyData . symmetricKeySize * 8 ;
925
+
926
+ // The Web Crypto spec allows for key lengths that are not multiples of
927
+ // 8. We don't. Our check here is stricter than that defined by the spec
928
+ // in that we require that algorithm.length match keyData.length * 8 if
929
+ // algorithm.length is specified.
930
+ if ( length !== undefined && length !== checkLength ) {
931
+ throw lazyDOMException ( 'Invalid key length' , 'DataError' ) ;
932
+ }
933
+ return new InternalCryptoKey ( keyData , { name } , keyUsages , false ) ;
934
+ }
935
+ case 'raw' : {
936
+ if ( hasAnyNotIn ( usagesSet , [ 'deriveKey' , 'deriveBits' ] ) ) {
937
+ throw lazyDOMException (
938
+ `Unsupported key usage for a ${ name } key` ,
939
+ 'SyntaxError' ) ;
940
+ }
941
+
942
+ const checkLength = keyData . byteLength * 8 ;
943
+
944
+ // The Web Crypto spec allows for key lengths that are not multiples of
945
+ // 8. We don't. Our check here is stricter than that defined by the spec
946
+ // in that we require that algorithm.length match keyData.length * 8 if
947
+ // algorithm.length is specified.
948
+ if ( length !== undefined && length !== checkLength ) {
949
+ throw lazyDOMException ( 'Invalid key length' , 'DataError' ) ;
950
+ }
951
+
952
+ const keyObject = createSecretKey ( keyData ) ;
953
+ return new InternalCryptoKey ( keyObject , { name } , keyUsages , false ) ;
954
+ }
955
+ }
956
+
957
+ throw lazyDOMException (
958
+ `Unable to import ${ name } key with format ${ format } ` ,
959
+ 'NotSupportedError' ) ;
960
+ }
961
+
804
962
module . exports = {
805
963
// Public API.
806
964
createSecretKey,
@@ -822,4 +980,5 @@ module.exports = {
822
980
PrivateKeyObject,
823
981
isKeyObject,
824
982
isCryptoKey,
983
+ importGenericSecretKey,
825
984
} ;
0 commit comments