66 ObjectDefineProperties,
77 ObjectDefineProperty,
88 ObjectSetPrototypeOf,
9+ SafeSet,
910 Symbol,
1011 SymbolToStringTag,
1112 Uint8Array,
@@ -49,6 +50,8 @@ const {
4950 kKeyObject,
5051 getArrayBufferOrView,
5152 bigIntArrayToUnsignedBigInt,
53+ normalizeAlgorithm,
54+ hasAnyNotIn,
5255} = require ( 'internal/crypto/util' ) ;
5356
5457const {
@@ -65,6 +68,7 @@ const {
6568const {
6669 customInspectSymbol : kInspect ,
6770 kEnumerableProperty,
71+ lazyDOMException,
6872} = require ( 'internal/util' ) ;
6973
7074const { inspect } = require ( 'internal/util/inspect' ) ;
@@ -148,6 +152,8 @@ const {
148152 } ,
149153 } ) ;
150154
155+ let webidl ;
156+
151157 class SecretKeyObject extends KeyObject {
152158 constructor ( handle ) {
153159 super ( 'secret' , handle ) ;
@@ -168,6 +174,51 @@ const {
168174 }
169175 return this [ kHandle ] . export ( ) ;
170176 }
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+ }
171222 }
172223
173224 const kAsymmetricKeyType = Symbol ( 'kAsymmetricKeyType' ) ;
@@ -209,6 +260,51 @@ const {
209260 return { } ;
210261 }
211262 }
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+ }
212308 }
213309
214310 class PublicKeyObject extends AsymmetricKeyObject {
@@ -801,6 +897,68 @@ function isCryptoKey(obj) {
801897 return obj != null && obj [ kKeyObject ] !== undefined ;
802898}
803899
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+
804962module . exports = {
805963 // Public API.
806964 createSecretKey,
@@ -822,4 +980,5 @@ module.exports = {
822980 PrivateKeyObject,
823981 isKeyObject,
824982 isCryptoKey,
983+ importGenericSecretKey,
825984} ;
0 commit comments