@@ -322,36 +322,25 @@ async function exportKeySpki(key) { |
322 | 322 | case 'RSA-PSS': |
323 | 323 | // Fall through |
324 | 324 | case 'RSA-OAEP': |
325 | | - if (key.type === 'public') { |
326 | | - return require('internal/crypto/rsa') |
327 | | - .rsaExportKey(key, kWebCryptoKeyFormatSPKI); |
328 | | - } |
329 | | - break; |
| 325 | + return require('internal/crypto/rsa') |
| 326 | + .rsaExportKey(key, kWebCryptoKeyFormatSPKI); |
330 | 327 | case 'ECDSA': |
331 | 328 | // Fall through |
332 | 329 | case 'ECDH': |
333 | | - if (key.type === 'public') { |
334 | | - return require('internal/crypto/ec') |
335 | | - .ecExportKey(key, kWebCryptoKeyFormatSPKI); |
336 | | - } |
337 | | - break; |
| 330 | + return require('internal/crypto/ec') |
| 331 | + .ecExportKey(key, kWebCryptoKeyFormatSPKI); |
338 | 332 | case 'Ed25519': |
339 | 333 | // Fall through |
340 | 334 | case 'Ed448': |
341 | 335 | // Fall through |
342 | 336 | case 'X25519': |
343 | 337 | // Fall through |
344 | 338 | case 'X448': |
345 | | - if (key.type === 'public') { |
346 | | - return require('internal/crypto/cfrg') |
347 | | - .cfrgExportKey(key, kWebCryptoKeyFormatSPKI); |
348 | | - } |
349 | | - break; |
| 339 | + return require('internal/crypto/cfrg') |
| 340 | + .cfrgExportKey(key, kWebCryptoKeyFormatSPKI); |
| 341 | + default: |
| 342 | + return undefined; |
350 | 343 | } |
351 | | - |
352 | | - throw lazyDOMException( |
353 | | - `Unable to export a raw ${key.algorithm.name} ${key.type} key`, |
354 | | - 'InvalidAccessError'); |
355 | 344 | } |
356 | 345 |
|
357 | 346 | async function exportKeyPkcs8(key) { |
@@ -361,60 +350,50 @@ async function exportKeyPkcs8(key) { |
361 | 350 | case 'RSA-PSS': |
362 | 351 | // Fall through |
363 | 352 | case 'RSA-OAEP': |
364 | | - if (key.type === 'private') { |
365 | | - return require('internal/crypto/rsa') |
366 | | - .rsaExportKey(key, kWebCryptoKeyFormatPKCS8); |
367 | | - } |
368 | | - break; |
| 353 | + return require('internal/crypto/rsa') |
| 354 | + .rsaExportKey(key, kWebCryptoKeyFormatPKCS8); |
369 | 355 | case 'ECDSA': |
370 | 356 | // Fall through |
371 | 357 | case 'ECDH': |
372 | | - if (key.type === 'private') { |
373 | | - return require('internal/crypto/ec') |
374 | | - .ecExportKey(key, kWebCryptoKeyFormatPKCS8); |
375 | | - } |
376 | | - break; |
| 358 | + return require('internal/crypto/ec') |
| 359 | + .ecExportKey(key, kWebCryptoKeyFormatPKCS8); |
377 | 360 | case 'Ed25519': |
378 | 361 | // Fall through |
379 | 362 | case 'Ed448': |
380 | 363 | // Fall through |
381 | 364 | case 'X25519': |
382 | 365 | // Fall through |
383 | 366 | case 'X448': |
384 | | - if (key.type === 'private') { |
385 | | - return require('internal/crypto/cfrg') |
386 | | - .cfrgExportKey(key, kWebCryptoKeyFormatPKCS8); |
387 | | - } |
388 | | - break; |
| 367 | + return require('internal/crypto/cfrg') |
| 368 | + .cfrgExportKey(key, kWebCryptoKeyFormatPKCS8); |
| 369 | + default: |
| 370 | + return undefined; |
389 | 371 | } |
390 | | - |
391 | | - throw lazyDOMException( |
392 | | - `Unable to export a pkcs8 ${key.algorithm.name} ${key.type} key`, |
393 | | - 'InvalidAccessError'); |
394 | 372 | } |
395 | 373 |
|
396 | | -async function exportKeyRaw(key) { |
| 374 | +async function exportKeyRawPublic(key) { |
397 | 375 | switch (key.algorithm.name) { |
398 | 376 | case 'ECDSA': |
399 | 377 | // Fall through |
400 | 378 | case 'ECDH': |
401 | | - if (key.type === 'public') { |
402 | | - return require('internal/crypto/ec') |
403 | | - .ecExportKey(key, kWebCryptoKeyFormatRaw); |
404 | | - } |
405 | | - break; |
| 379 | + return require('internal/crypto/ec') |
| 380 | + .ecExportKey(key, kWebCryptoKeyFormatRaw); |
406 | 381 | case 'Ed25519': |
407 | 382 | // Fall through |
408 | 383 | case 'Ed448': |
409 | 384 | // Fall through |
410 | 385 | case 'X25519': |
411 | 386 | // Fall through |
412 | 387 | case 'X448': |
413 | | - if (key.type === 'public') { |
414 | | - return require('internal/crypto/cfrg') |
415 | | - .cfrgExportKey(key, kWebCryptoKeyFormatRaw); |
416 | | - } |
417 | | - break; |
| 388 | + return require('internal/crypto/cfrg') |
| 389 | + .cfrgExportKey(key, kWebCryptoKeyFormatRaw); |
| 390 | + default: |
| 391 | + return undefined; |
| 392 | + } |
| 393 | +} |
| 394 | + |
| 395 | +async function exportKeyRawSecret(key) { |
| 396 | + switch (key.algorithm.name) { |
418 | 397 | case 'AES-CTR': |
419 | 398 | // Fall through |
420 | 399 | case 'AES-CBC': |
@@ -424,71 +403,66 @@ async function exportKeyRaw(key) { |
424 | 403 | case 'AES-KW': |
425 | 404 | // Fall through |
426 | 405 | case 'HMAC': |
427 | | - return key[kKeyObject].export().buffer; |
| 406 | + return key[kKeyObject][kHandle].export().buffer; |
| 407 | + default: |
| 408 | + return undefined; |
428 | 409 | } |
429 | | - |
430 | | - throw lazyDOMException( |
431 | | - `Unable to export a raw ${key.algorithm.name} ${key.type} key`, |
432 | | - 'InvalidAccessError'); |
433 | 410 | } |
434 | 411 |
|
435 | 412 | async function exportKeyJWK(key) { |
436 | | - const jwk = key[kKeyObject][kHandle].exportJwk({ |
| 413 | + const parameters = { |
437 | 414 | key_ops: key.usages, |
438 | 415 | ext: key.extractable, |
439 | | - }, true); |
| 416 | + }; |
440 | 417 | switch (key.algorithm.name) { |
441 | 418 | case 'RSASSA-PKCS1-v1_5': |
442 | | - jwk.alg = normalizeHashName( |
| 419 | + parameters.alg = normalizeHashName( |
443 | 420 | key.algorithm.hash.name, |
444 | 421 | normalizeHashName.kContextJwkRsa); |
445 | | - return jwk; |
| 422 | + break; |
446 | 423 | case 'RSA-PSS': |
447 | | - jwk.alg = normalizeHashName( |
| 424 | + parameters.alg = normalizeHashName( |
448 | 425 | key.algorithm.hash.name, |
449 | 426 | normalizeHashName.kContextJwkRsaPss); |
450 | | - return jwk; |
| 427 | + break; |
451 | 428 | case 'RSA-OAEP': |
452 | | - jwk.alg = normalizeHashName( |
| 429 | + parameters.alg = normalizeHashName( |
453 | 430 | key.algorithm.hash.name, |
454 | 431 | normalizeHashName.kContextJwkRsaOaep); |
455 | | - return jwk; |
| 432 | + break; |
456 | 433 | case 'ECDSA': |
457 | 434 | // Fall through |
458 | 435 | case 'ECDH': |
459 | | - jwk.crv ||= key.algorithm.namedCurve; |
460 | | - return jwk; |
| 436 | + // Fall through |
461 | 437 | case 'X25519': |
462 | 438 | // Fall through |
463 | 439 | case 'X448': |
464 | | - jwk.crv ||= key.algorithm.name; |
465 | | - return jwk; |
| 440 | + break; |
466 | 441 | case 'Ed25519': |
467 | 442 | // Fall through |
468 | 443 | case 'Ed448': |
469 | | - jwk.crv ||= key.algorithm.name; |
470 | | - jwk.alg = key.algorithm.name; |
471 | | - return jwk; |
| 444 | + parameters.alg = key.algorithm.name; |
| 445 | + break; |
472 | 446 | case 'AES-CTR': |
473 | 447 | // Fall through |
474 | 448 | case 'AES-CBC': |
475 | 449 | // Fall through |
476 | 450 | case 'AES-GCM': |
477 | 451 | // Fall through |
478 | 452 | case 'AES-KW': |
479 | | - jwk.alg = require('internal/crypto/aes') |
| 453 | + parameters.alg = require('internal/crypto/aes') |
480 | 454 | .getAlgorithmName(key.algorithm.name, key.algorithm.length); |
481 | | - return jwk; |
| 455 | + break; |
482 | 456 | case 'HMAC': |
483 | | - jwk.alg = normalizeHashName( |
| 457 | + parameters.alg = normalizeHashName( |
484 | 458 | key.algorithm.hash.name, |
485 | 459 | normalizeHashName.kContextJwkHmac); |
486 | | - return jwk; |
| 460 | + break; |
487 | 461 | default: |
488 | | - // Fall through |
| 462 | + return undefined; |
489 | 463 | } |
490 | 464 |
|
491 | | - throw lazyDOMException('Not yet supported', 'NotSupportedError'); |
| 465 | + return key[kKeyObject][kHandle].exportJwk(parameters, true); |
492 | 466 | } |
493 | 467 |
|
494 | 468 | async function exportKey(format, key) { |
@@ -506,17 +480,55 @@ async function exportKey(format, key) { |
506 | 480 | context: '2nd argument', |
507 | 481 | }); |
508 | 482 |
|
| 483 | + try { |
| 484 | + normalizeAlgorithm(key.algorithm, 'exportKey'); |
| 485 | + } catch { |
| 486 | + throw lazyDOMException( |
| 487 | + `${key.algorithm.name} key export is not supported`, 'NotSupportedError'); |
| 488 | + } |
| 489 | + |
509 | 490 | if (!key.extractable) |
510 | 491 | throw lazyDOMException('key is not extractable', 'InvalidAccessException'); |
511 | 492 |
|
| 493 | + let result; |
512 | 494 | switch (format) { |
513 | | - case 'spki': return exportKeySpki(key); |
514 | | - case 'pkcs8': return exportKeyPkcs8(key); |
515 | | - case 'jwk': return exportKeyJWK(key); |
516 | | - case 'raw': return exportKeyRaw(key); |
| 495 | + case 'spki': { |
| 496 | + if (key.type === 'public') { |
| 497 | + result = await exportKeySpki(key); |
| 498 | + } |
| 499 | + break; |
| 500 | + } |
| 501 | + case 'pkcs8': { |
| 502 | + if (key.type === 'private') { |
| 503 | + result = await exportKeyPkcs8(key); |
| 504 | + } |
| 505 | + break; |
| 506 | + } |
| 507 | + case 'jwk': { |
| 508 | + result = await exportKeyJWK(key); |
| 509 | + break; |
| 510 | + } |
| 511 | + case 'raw': { |
| 512 | + if (key.type === 'secret') { |
| 513 | + result = await exportKeyRawSecret(key); |
| 514 | + break; |
| 515 | + } |
| 516 | + |
| 517 | + if (key.type === 'public') { |
| 518 | + result = await exportKeyRawPublic(key); |
| 519 | + break; |
| 520 | + } |
| 521 | + break; |
| 522 | + } |
517 | 523 | } |
518 | | - throw lazyDOMException( |
519 | | - 'Export format is unsupported', 'NotSupportedError'); |
| 524 | + |
| 525 | + if (!result) { |
| 526 | + throw lazyDOMException( |
| 527 | + `Unable to export ${key.algorithm.name} ${key.type} key using ${format} format`, |
| 528 | + 'NotSupportedError'); |
| 529 | + } |
| 530 | + |
| 531 | + return result; |
520 | 532 | } |
521 | 533 |
|
522 | 534 | async function importKey( |
@@ -603,8 +615,12 @@ async function importKey( |
603 | 615 | extractable, |
604 | 616 | keyUsages); |
605 | 617 | break; |
606 | | - default: |
607 | | - throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError'); |
| 618 | + } |
| 619 | + |
| 620 | + if (!result) { |
| 621 | + throw lazyDOMException( |
| 622 | + `Unable to import ${algorithm.name} using ${format} format`, |
| 623 | + 'NotSupportedError'); |
608 | 624 | } |
609 | 625 |
|
610 | 626 | if ((result.type === 'secret' || result.type === 'private') && result.usages.length === 0) { |
|