Skip to content

Commit a312e70

Browse files
panvaRafaelGSS
authored andcommitted
crypto: prepare webcrypto key import/export for modern algorithms
PR-URL: #59284 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 95b8b7e commit a312e70

8 files changed

Lines changed: 125 additions & 97 deletions

File tree

‎lib/internal/crypto/aes.js‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,7 @@ function aesImportKey(
285285
break;
286286
}
287287
default:
288-
throwlazyDOMException(
289-
`Unable to import AES key with format ${format}`,
290-
'NotSupportedError');
288+
returnundefined;
291289
}
292290

293291
if(length===undefined){

‎lib/internal/crypto/cfrg.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ function cfrgImportKey(
324324
keyObject=createCFRGRawKey(name,keyData,true);
325325
break;
326326
}
327+
default:
328+
returnundefined;
327329
}
328330

329331
if(keyObject.asymmetricKeyType!==name.toLowerCase()){

‎lib/internal/crypto/ec.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ function ecImportKey(
250250
keyObject=createECPublicKeyRaw(namedCurve,keyData);
251251
break;
252252
}
253+
default:
254+
returnundefined;
253255
}
254256

255257
switch(algorithm.name){

‎lib/internal/crypto/keys.js‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -922,15 +922,11 @@ function importGenericSecretKey(
922922
keyObject=createSecretKey(keyData);
923923
break;
924924
}
925+
default:
926+
returnundefined;
925927
}
926928

927-
if(keyObject){
928-
returnnewInternalCryptoKey(keyObject,{ name },keyUsages,false);
929-
}
930-
931-
throwlazyDOMException(
932-
`Unable to import ${name} key with format ${format}`,
933-
'NotSupportedError');
929+
returnnewInternalCryptoKey(keyObject,{ name },keyUsages,false);
934930
}
935931

936932
module.exports={

‎lib/internal/crypto/mac.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ function hmacImportKey(
143143
break;
144144
}
145145
default:
146-
throwlazyDOMException(`Unable to import HMAC key with format ${format}`);
146+
returnundefined;
147147
}
148148

149149
const{ length }=keyObject[kHandle].keyDetail({});

‎lib/internal/crypto/rsa.js‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,7 @@ function rsaImportKey(
305305
break;
306306
}
307307
default:
308-
throwlazyDOMException(
309-
`Unable to import RSA key with format ${format}`,
310-
'NotSupportedError');
308+
returnundefined;
311309
}
312310

313311
if(keyObject.asymmetricKeyType!=='rsa'){

‎lib/internal/crypto/util.js‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,20 @@ const kSupportedAlgorithms = {
189189
'Ed25519': null,
190190
'X25519': null,
191191
},
192+
'exportKey': {
193+
'RSASSA-PKCS1-v1_5': null,
194+
'RSA-PSS': null,
195+
'RSA-OAEP': null,
196+
'ECDSA': null,
197+
'ECDH': null,
198+
'HMAC': null,
199+
'AES-CTR': null,
200+
'AES-CBC': null,
201+
'AES-GCM': null,
202+
'AES-KW': null,
203+
'Ed25519': null,
204+
'X25519': null,
205+
},
192206
'sign': {
193207
'RSASSA-PKCS1-v1_5': null,
194208
'RSA-PSS': 'RsaPssParams',
@@ -259,12 +273,14 @@ const experimentalAlgorithms = ObjectEntries({
259273
generateKey: null,
260274
importKey: null,
261275
deriveBits: 'EcdhKeyDeriveParams',
276+
exportKey: null,
262277
},
263278
'Ed448': {
264279
generateKey: null,
265280
sign: 'Ed448Params',
266281
verify: 'Ed448Params',
267282
importKey: null,
283+
exportKey: null,
268284
},
269285
});
270286

‎lib/internal/crypto/webcrypto.js‎

Lines changed: 99 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -322,36 +322,25 @@ async function exportKeySpki(key) {
322322
case'RSA-PSS':
323323
// Fall through
324324
case'RSA-OAEP':
325-
if(key.type==='public'){
326-
returnrequire('internal/crypto/rsa')
327-
.rsaExportKey(key,kWebCryptoKeyFormatSPKI);
328-
}
329-
break;
325+
returnrequire('internal/crypto/rsa')
326+
.rsaExportKey(key,kWebCryptoKeyFormatSPKI);
330327
case'ECDSA':
331328
// Fall through
332329
case'ECDH':
333-
if(key.type==='public'){
334-
returnrequire('internal/crypto/ec')
335-
.ecExportKey(key,kWebCryptoKeyFormatSPKI);
336-
}
337-
break;
330+
returnrequire('internal/crypto/ec')
331+
.ecExportKey(key,kWebCryptoKeyFormatSPKI);
338332
case'Ed25519':
339333
// Fall through
340334
case'Ed448':
341335
// Fall through
342336
case'X25519':
343337
// Fall through
344338
case'X448':
345-
if(key.type==='public'){
346-
returnrequire('internal/crypto/cfrg')
347-
.cfrgExportKey(key,kWebCryptoKeyFormatSPKI);
348-
}
349-
break;
339+
returnrequire('internal/crypto/cfrg')
340+
.cfrgExportKey(key,kWebCryptoKeyFormatSPKI);
341+
default:
342+
returnundefined;
350343
}
351-
352-
throwlazyDOMException(
353-
`Unable to export a raw ${key.algorithm.name}${key.type} key`,
354-
'InvalidAccessError');
355344
}
356345

357346
asyncfunctionexportKeyPkcs8(key){
@@ -361,60 +350,50 @@ async function exportKeyPkcs8(key) {
361350
case'RSA-PSS':
362351
// Fall through
363352
case'RSA-OAEP':
364-
if(key.type==='private'){
365-
returnrequire('internal/crypto/rsa')
366-
.rsaExportKey(key,kWebCryptoKeyFormatPKCS8);
367-
}
368-
break;
353+
returnrequire('internal/crypto/rsa')
354+
.rsaExportKey(key,kWebCryptoKeyFormatPKCS8);
369355
case'ECDSA':
370356
// Fall through
371357
case'ECDH':
372-
if(key.type==='private'){
373-
returnrequire('internal/crypto/ec')
374-
.ecExportKey(key,kWebCryptoKeyFormatPKCS8);
375-
}
376-
break;
358+
returnrequire('internal/crypto/ec')
359+
.ecExportKey(key,kWebCryptoKeyFormatPKCS8);
377360
case'Ed25519':
378361
// Fall through
379362
case'Ed448':
380363
// Fall through
381364
case'X25519':
382365
// Fall through
383366
case'X448':
384-
if(key.type==='private'){
385-
returnrequire('internal/crypto/cfrg')
386-
.cfrgExportKey(key,kWebCryptoKeyFormatPKCS8);
387-
}
388-
break;
367+
returnrequire('internal/crypto/cfrg')
368+
.cfrgExportKey(key,kWebCryptoKeyFormatPKCS8);
369+
default:
370+
returnundefined;
389371
}
390-
391-
throwlazyDOMException(
392-
`Unable to export a pkcs8 ${key.algorithm.name}${key.type} key`,
393-
'InvalidAccessError');
394372
}
395373

396-
asyncfunctionexportKeyRaw(key){
374+
asyncfunctionexportKeyRawPublic(key){
397375
switch(key.algorithm.name){
398376
case'ECDSA':
399377
// Fall through
400378
case'ECDH':
401-
if(key.type==='public'){
402-
returnrequire('internal/crypto/ec')
403-
.ecExportKey(key,kWebCryptoKeyFormatRaw);
404-
}
405-
break;
379+
returnrequire('internal/crypto/ec')
380+
.ecExportKey(key,kWebCryptoKeyFormatRaw);
406381
case'Ed25519':
407382
// Fall through
408383
case'Ed448':
409384
// Fall through
410385
case'X25519':
411386
// Fall through
412387
case'X448':
413-
if(key.type==='public'){
414-
returnrequire('internal/crypto/cfrg')
415-
.cfrgExportKey(key,kWebCryptoKeyFormatRaw);
416-
}
417-
break;
388+
returnrequire('internal/crypto/cfrg')
389+
.cfrgExportKey(key,kWebCryptoKeyFormatRaw);
390+
default:
391+
returnundefined;
392+
}
393+
}
394+
395+
asyncfunctionexportKeyRawSecret(key){
396+
switch(key.algorithm.name){
418397
case'AES-CTR':
419398
// Fall through
420399
case'AES-CBC':
@@ -424,71 +403,66 @@ async function exportKeyRaw(key) {
424403
case'AES-KW':
425404
// Fall through
426405
case'HMAC':
427-
returnkey[kKeyObject].export().buffer;
406+
returnkey[kKeyObject][kHandle].export().buffer;
407+
default:
408+
returnundefined;
428409
}
429-
430-
throwlazyDOMException(
431-
`Unable to export a raw ${key.algorithm.name}${key.type} key`,
432-
'InvalidAccessError');
433410
}
434411

435412
asyncfunctionexportKeyJWK(key){
436-
constjwk=key[kKeyObject][kHandle].exportJwk({
413+
constparameters={
437414
key_ops: key.usages,
438415
ext: key.extractable,
439-
},true);
416+
};
440417
switch(key.algorithm.name){
441418
case'RSASSA-PKCS1-v1_5':
442-
jwk.alg=normalizeHashName(
419+
parameters.alg=normalizeHashName(
443420
key.algorithm.hash.name,
444421
normalizeHashName.kContextJwkRsa);
445-
returnjwk;
422+
break;
446423
case'RSA-PSS':
447-
jwk.alg=normalizeHashName(
424+
parameters.alg=normalizeHashName(
448425
key.algorithm.hash.name,
449426
normalizeHashName.kContextJwkRsaPss);
450-
returnjwk;
427+
break;
451428
case'RSA-OAEP':
452-
jwk.alg=normalizeHashName(
429+
parameters.alg=normalizeHashName(
453430
key.algorithm.hash.name,
454431
normalizeHashName.kContextJwkRsaOaep);
455-
returnjwk;
432+
break;
456433
case'ECDSA':
457434
// Fall through
458435
case'ECDH':
459-
jwk.crv||=key.algorithm.namedCurve;
460-
returnjwk;
436+
// Fall through
461437
case'X25519':
462438
// Fall through
463439
case'X448':
464-
jwk.crv||=key.algorithm.name;
465-
returnjwk;
440+
break;
466441
case'Ed25519':
467442
// Fall through
468443
case'Ed448':
469-
jwk.crv||=key.algorithm.name;
470-
jwk.alg=key.algorithm.name;
471-
returnjwk;
444+
parameters.alg=key.algorithm.name;
445+
break;
472446
case'AES-CTR':
473447
// Fall through
474448
case'AES-CBC':
475449
// Fall through
476450
case'AES-GCM':
477451
// Fall through
478452
case'AES-KW':
479-
jwk.alg=require('internal/crypto/aes')
453+
parameters.alg=require('internal/crypto/aes')
480454
.getAlgorithmName(key.algorithm.name,key.algorithm.length);
481-
returnjwk;
455+
break;
482456
case'HMAC':
483-
jwk.alg=normalizeHashName(
457+
parameters.alg=normalizeHashName(
484458
key.algorithm.hash.name,
485459
normalizeHashName.kContextJwkHmac);
486-
returnjwk;
460+
break;
487461
default:
488-
// Fall through
462+
returnundefined;
489463
}
490464

491-
throwlazyDOMException('Not yet supported','NotSupportedError');
465+
returnkey[kKeyObject][kHandle].exportJwk(parameters,true);
492466
}
493467

494468
asyncfunctionexportKey(format,key){
@@ -506,17 +480,55 @@ async function exportKey(format, key) {
506480
context: '2nd argument',
507481
});
508482

483+
try{
484+
normalizeAlgorithm(key.algorithm,'exportKey');
485+
}catch{
486+
throwlazyDOMException(
487+
`${key.algorithm.name} key export is not supported`,'NotSupportedError');
488+
}
489+
509490
if(!key.extractable)
510491
throwlazyDOMException('key is not extractable','InvalidAccessException');
511492

493+
letresult;
512494
switch(format){
513-
case'spki': returnexportKeySpki(key);
514-
case'pkcs8': returnexportKeyPkcs8(key);
515-
case'jwk': returnexportKeyJWK(key);
516-
case'raw': returnexportKeyRaw(key);
495+
case'spki': {
496+
if(key.type==='public'){
497+
result=awaitexportKeySpki(key);
498+
}
499+
break;
500+
}
501+
case'pkcs8': {
502+
if(key.type==='private'){
503+
result=awaitexportKeyPkcs8(key);
504+
}
505+
break;
506+
}
507+
case'jwk': {
508+
result=awaitexportKeyJWK(key);
509+
break;
510+
}
511+
case'raw': {
512+
if(key.type==='secret'){
513+
result=awaitexportKeyRawSecret(key);
514+
break;
515+
}
516+
517+
if(key.type==='public'){
518+
result=awaitexportKeyRawPublic(key);
519+
break;
520+
}
521+
break;
522+
}
517523
}
518-
throwlazyDOMException(
519-
'Export format is unsupported','NotSupportedError');
524+
525+
if(!result){
526+
throwlazyDOMException(
527+
`Unable to export ${key.algorithm.name}${key.type} key using ${format} format`,
528+
'NotSupportedError');
529+
}
530+
531+
returnresult;
520532
}
521533

522534
asyncfunctionimportKey(
@@ -603,8 +615,12 @@ async function importKey(
603615
extractable,
604616
keyUsages);
605617
break;
606-
default:
607-
throwlazyDOMException('Unrecognized algorithm name','NotSupportedError');
618+
}
619+
620+
if(!result){
621+
throwlazyDOMException(
622+
`Unable to import ${algorithm.name} using ${format} format`,
623+
'NotSupportedError');
608624
}
609625

610626
if((result.type==='secret'||result.type==='private')&&result.usages.length===0){

0 commit comments

Comments
 (0)