@blamejs/pki 0.8.60 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +7 -0
  3. package/index.js +55 -26
  4. package/lib/acme.js +5 -5
  5. package/lib/asn1-der.js +1 -1
  6. package/lib/attrcert-sign.js +2 -2
  7. package/lib/cbor-det.js +4 -1
  8. package/lib/cmc-build.js +15 -10
  9. package/lib/cmp-build.js +5 -5
  10. package/lib/cmp-session.js +6 -3
  11. package/lib/cmp-verify.js +1 -1
  12. package/lib/cms-compress.js +5 -2
  13. package/lib/cms-decrypt.js +17 -17
  14. package/lib/cms-digest.js +2 -3
  15. package/lib/cms-encrypt.js +17 -18
  16. package/lib/cms-sign.js +2 -2
  17. package/lib/composite-kem.js +28 -29
  18. package/lib/crl-sign.js +3 -3
  19. package/lib/crmf-sign.js +12 -18
  20. package/lib/csr-sign.js +1 -1
  21. package/lib/ct.js +25 -22
  22. package/lib/est.js +12 -12
  23. package/lib/framework-error.js +1 -1
  24. package/lib/guard-bytes.js +1 -1
  25. package/lib/guard-crypto.js +506 -14
  26. package/lib/guard-limits.js +3 -2
  27. package/lib/guard-secret.js +3 -2
  28. package/lib/hpke.js +26 -26
  29. package/lib/http-digest.js +5 -7
  30. package/lib/http-retry-after.js +4 -1
  31. package/lib/http-transport.js +6 -6
  32. package/lib/inspect.js +9 -4
  33. package/lib/jose.js +3 -3
  34. package/lib/key.js +41 -29
  35. package/lib/merkle.js +4 -4
  36. package/lib/ocsp.js +3 -4
  37. package/lib/path-validate.js +3 -3
  38. package/lib/pbes2.js +14 -11
  39. package/lib/pkcs12-build.js +10 -11
  40. package/lib/pki-build.js +3 -3
  41. package/lib/scep.js +8 -9
  42. package/lib/schema-engine.js +12 -12
  43. package/lib/schema-pkix.js +12 -12
  44. package/lib/schema-tsp.js +3 -3
  45. package/lib/shbs.js +3 -6
  46. package/lib/sign-scheme.js +4 -4
  47. package/lib/sigstore.js +10 -10
  48. package/lib/smime.js +12 -9
  49. package/lib/tlog.js +5 -4
  50. package/lib/tls-cert-compress.js +3 -3
  51. package/lib/tsp-sign.js +6 -6
  52. package/lib/tuf.js +6 -5
  53. package/lib/validator-cose.js +2 -2
  54. package/lib/webauthn-mds.js +4 -8
  55. package/lib/webauthn.js +5 -12
  56. package/lib/webcrypto.js +61 -46
  57. package/lib/x509-sign.js +3 -3
  58. package/package.json +1 -1
  59. package/sbom.cdx.json +6 -6
package/lib/webcrypto.js CHANGED
@@ -261,10 +261,10 @@ SubtleCrypto.prototype.digest = async function digest(algorithm, data) {
261
261
  var name = _normalizeAlg(algorithm, "digest").name;
262
262
  var xof = XOF_NODE[_toUpperCase(_String(name))];
263
263
  var h = xof
264
- ? nodeCrypto.createHash(xof.node, { outputLength: xof.length })
265
- : nodeCrypto.createHash(_hashNode(name, "digest"));
266
- h.update(_toBuf(data, "digest"));
267
- return _toArrayBuffer(h.digest());
264
+ ? guard.crypto.hash(xof.node, xof.length)
265
+ : guard.crypto.hash(_hashNode(name, "digest"));
266
+ _hashUpdate(h, _toBuf(data, "digest"));
267
+ return _toArrayBuffer(_hashDigest(h));
268
268
  };
269
269
 
270
270
  SubtleCrypto.prototype.digestStream = async function digestStream(algorithms, source) {
@@ -276,8 +276,8 @@ SubtleCrypto.prototype.digestStream = async function digestStream(algorithms, so
276
276
  var name = _normalizeAlg(algorithms[_h], "digestStream").name;
277
277
  var xof = XOF_NODE[_toUpperCase(_String(name))];
278
278
  hashes[_h] = xof
279
- ? nodeCrypto.createHash(xof.node, { outputLength: xof.length })
280
- : nodeCrypto.createHash(_hashNode(name, "digestStream"));
279
+ ? guard.crypto.hash(xof.node, xof.length)
280
+ : guard.crypto.hash(_hashNode(name, "digestStream"));
281
281
  }
282
282
  var acquire = source == null ? undefined : source[_asyncIterator];
283
283
  if (typeof acquire !== "function") {
@@ -307,8 +307,8 @@ SubtleCrypto.prototype.digestStream = async function digestStream(algorithms, so
307
307
 
308
308
  SubtleCrypto.prototype.encryptStream = async function encryptStream(spec, source) {
309
309
  var cipher = spec.authTagLength
310
- ? nodeCrypto.createCipheriv(spec.algNode, spec.key, spec.iv, { authTagLength: spec.authTagLength })
311
- : nodeCrypto.createCipheriv(spec.algNode, spec.key, spec.iv);
310
+ ? guard.crypto.cipher(spec.algNode, spec.key, spec.iv, { authTagLength: spec.authTagLength })
311
+ : guard.crypto.cipher(spec.algNode, spec.key, spec.iv);
312
312
  if (spec.aad && spec.aad.length) _cipherSetAAD(cipher, spec.aad);
313
313
  var acquire = source == null ? undefined : source[_asyncIterator];
314
314
  if (typeof acquire !== "function") {
@@ -344,7 +344,7 @@ SubtleCrypto.prototype.encryptStream = async function encryptStream(spec, source
344
344
  };
345
345
 
346
346
  SubtleCrypto.prototype.decryptStream = function decryptStream(spec, ct) {
347
- var decipher = nodeCrypto.createDecipheriv(spec.algNode, spec.key, spec.iv);
347
+ var decipher = guard.crypto.decipher(spec.algNode, spec.key, spec.iv);
348
348
  return _decipherDrive(decipher, _bufferFrom(_toBuf(ct, "decryptStream ciphertext")), _STREAM_CHUNK);
349
349
  };
350
350
  async function* _decipherDrive(decipher, ct, chunkSize) {
@@ -368,12 +368,12 @@ SubtleCrypto.prototype.generateKey = async function generateKey(algorithm, extra
368
368
  if (name === "AES-GCM" || name === "AES-CBC" || name === "AES-CTR" || name === "AES-KW") {
369
369
  var bits = alg.length;
370
370
  if (bits !== 128 && bits !== 192 && bits !== 256) throw new WebCryptoError("webcrypto/syntax", name + ": length must be 128/192/256");
371
- var secret = guard.crypto.secretKey(nodeCrypto.randomBytes(bits / 8));
371
+ var secret = guard.crypto.secretKey(guard.crypto.randomBytes(bits / 8));
372
372
  return new CryptoKey("secret", extractable, { name: name, length: bits }, usages, secret);
373
373
  }
374
374
  if (name === "HMAC") {
375
375
  var lenBits = _hmacLengthBits(alg, "generateKey HMAC");
376
- var hkey = guard.crypto.secretKey(nodeCrypto.randomBytes(lenBits / 8));
376
+ var hkey = guard.crypto.secretKey(guard.crypto.randomBytes(lenBits / 8));
377
377
  return new CryptoKey("secret", extractable, { name: name, hash: { name: (typeof alg.hash === "string" ? alg.hash : alg.hash.name) }, length: lenBits }, usages, hkey);
378
378
  }
379
379
 
@@ -391,7 +391,7 @@ function _generateKeyPair(alg) {
391
391
  var name = alg.name, kp, algorithm;
392
392
  if (name === "RSASSA-PKCS1-V1_5" || name === "RSA-PSS" || name === "RSA-OAEP") {
393
393
  var rsaHash = _hashObj(alg.hash, "generateKey " + name);
394
- kp = nodeCrypto.generateKeyPairSync("rsa", {
394
+ kp = guard.crypto.generateKeyPair("rsa", {
395
395
  modulusLength: alg.modulusLength || 2048,
396
396
  publicExponent: alg.publicExponent ? _bufToBigIntNum(alg.publicExponent) : 65537,
397
397
  });
@@ -399,19 +399,19 @@ function _generateKeyPair(alg) {
399
399
  } else if (name === "ECDSA" || name === "ECDH") {
400
400
  var curve = alg.namedCurve;
401
401
  if (!CURVE_NODE[curve]) throw new WebCryptoError("webcrypto/not-supported", name + ": unsupported curve " + _stringify(curve));
402
- kp = nodeCrypto.generateKeyPairSync("ec", { namedCurve: CURVE_NODE[curve] });
402
+ kp = guard.crypto.generateKeyPair("ec", { namedCurve: CURVE_NODE[curve] });
403
403
  algorithm = { name: name, namedCurve: curve };
404
404
  } else if (name === "ED25519" || name === "ED448" || name === "X25519" || name === "X448") {
405
- kp = nodeCrypto.generateKeyPairSync(_toLowerCase(name));
405
+ kp = guard.crypto.generateKeyPair(_toLowerCase(name));
406
406
  algorithm = { name: _stdName(name) };
407
407
  } else if (ML_DSA_NODE[name]) {
408
- kp = nodeCrypto.generateKeyPairSync(ML_DSA_NODE[name]);
408
+ kp = guard.crypto.generateKeyPair(ML_DSA_NODE[name]);
409
409
  algorithm = { name: name };
410
410
  } else if (ML_KEM_NODE[name]) {
411
- kp = nodeCrypto.generateKeyPairSync(ML_KEM_NODE[name]);
411
+ kp = guard.crypto.generateKeyPair(ML_KEM_NODE[name]);
412
412
  algorithm = { name: name };
413
413
  } else if (SLH_DSA_NODE[name]) {
414
- kp = nodeCrypto.generateKeyPairSync(SLH_DSA_NODE[name]);
414
+ kp = guard.crypto.generateKeyPair(SLH_DSA_NODE[name]);
415
415
  algorithm = { name: name };
416
416
  } else {
417
417
  throw new WebCryptoError("webcrypto/not-supported", "generateKey: unsupported algorithm " + _stringify(name));
@@ -515,7 +515,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
515
515
  if (!ENCRYPT_DECRYPT_NAMES[name]) throw new WebCryptoError("webcrypto/not-supported", "encrypt: unsupported algorithm " + _stringify(name));
516
516
  _requireAlgMatch(alg, key, "encrypt");
517
517
  if (name === "RSA-OAEP") {
518
- return _toArrayBuffer(nodeCrypto.publicEncrypt({
518
+ return _toArrayBuffer(guard.crypto.publicEncrypt({
519
519
  key: key._handle, padding: guard.crypto.padding.RSA_PKCS1_OAEP,
520
520
  oaepHash: _hashNode(key.algorithm.hash, "encrypt"),
521
521
  oaepLabel: alg.label ? _toBuf(alg.label, "encrypt label") : undefined,
@@ -526,10 +526,10 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
526
526
  var aad = alg.additionalData ? _toBuf(alg.additionalData, "AES-GCM aad") : null;
527
527
  return _toArrayBuffer(_runCipher(function () {
528
528
  return _withSecretBytes(key, function (kb) {
529
- var cipher = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: (alg.tagLength || 128) / 8 });
530
- if (aad) cipher.setAAD(aad);
529
+ var cipher = guard.crypto.cipher("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: (alg.tagLength || 128) / 8 });
530
+ if (aad) guard.crypto.transformSetAAD(cipher, aad);
531
531
  var ct = guard.secret.cipherFinish(cipher, buf, WebCryptoError, "webcrypto/operation", "an AES-GCM encrypt intermediate");
532
- return _bufferConcat([ct, cipher.getAuthTag()]);
532
+ return _bufferConcat([ct, guard.crypto.cipherAuthTag(cipher)]);
533
533
  });
534
534
  }, "encrypt"));
535
535
  }
@@ -537,7 +537,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
537
537
  var cbcIv = _toBuf(alg.iv, "AES-CBC iv");
538
538
  return _toArrayBuffer(_runCipher(function () {
539
539
  return _withSecretBytes(key, function (kb) {
540
- var c2 = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-cbc", kb, cbcIv);
540
+ var c2 = guard.crypto.cipher("aes-" + key.algorithm.length + "-cbc", kb, cbcIv);
541
541
  return guard.secret.cipherFinish(c2, buf, WebCryptoError, "webcrypto/operation", "an AES-CBC encrypt intermediate");
542
542
  });
543
543
  }, "encrypt"));
@@ -547,7 +547,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
547
547
  var ctrCounter = _toBuf(alg.counter, "AES-CTR counter");
548
548
  return _toArrayBuffer(_runCipher(function () {
549
549
  return _withSecretBytes(key, function (kb) {
550
- var c3 = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter);
550
+ var c3 = guard.crypto.cipher("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter);
551
551
  return guard.secret.cipherFinish(c3, buf, WebCryptoError, "webcrypto/operation", "an AES-CTR encrypt intermediate");
552
552
  });
553
553
  }, "encrypt"));
@@ -563,7 +563,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
563
563
  if (!ENCRYPT_DECRYPT_NAMES[name]) throw new WebCryptoError("webcrypto/not-supported", "decrypt: unsupported algorithm " + _stringify(name));
564
564
  _requireAlgMatch(alg, key, "decrypt");
565
565
  if (name === "RSA-OAEP") {
566
- var oaepOut = nodeCrypto.privateDecrypt({
566
+ var oaepOut = guard.crypto.privateDecrypt({
567
567
  key: key._handle, padding: guard.crypto.padding.RSA_PKCS1_OAEP,
568
568
  oaepHash: _hashNode(key.algorithm.hash, "decrypt"),
569
569
  oaepLabel: alg.label ? _toBuf(alg.label, "decrypt label") : undefined,
@@ -580,9 +580,9 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
580
580
  var gcmAad = alg.additionalData ? _toBuf(alg.additionalData, "AES-GCM aad") : null;
581
581
  return _toArrayBuffer(_runCipher(function () {
582
582
  return _withSecretBytes(key, function (kb) {
583
- var d = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: tagLen });
584
- if (gcmAad) d.setAAD(gcmAad);
585
- d.setAuthTag(tag);
583
+ var d = guard.crypto.decipher("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: tagLen });
584
+ if (gcmAad) guard.crypto.transformSetAAD(d, gcmAad);
585
+ guard.crypto.decipherSetAuthTag(d, tag);
586
586
  return guard.secret.cipherFinish(d, ct, WebCryptoError, "webcrypto/operation", "the recovered AES-GCM plaintext");
587
587
  });
588
588
  }, "decrypt"));
@@ -591,7 +591,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
591
591
  var cbcIv2 = _toBuf(alg.iv, "AES-CBC iv");
592
592
  return _toArrayBuffer(_runCipher(function () {
593
593
  return _withSecretBytes(key, function (kb) {
594
- var d2 = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-cbc", kb, cbcIv2);
594
+ var d2 = guard.crypto.decipher("aes-" + key.algorithm.length + "-cbc", kb, cbcIv2);
595
595
  return guard.secret.cipherFinish(d2, buf, WebCryptoError, "webcrypto/operation", "the recovered AES-CBC plaintext");
596
596
  });
597
597
  }, "decrypt"));
@@ -601,7 +601,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
601
601
  var ctrCounter2 = _toBuf(alg.counter, "AES-CTR counter");
602
602
  return _toArrayBuffer(_runCipher(function () {
603
603
  return _withSecretBytes(key, function (kb) {
604
- var d3 = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter2);
604
+ var d3 = guard.crypto.decipher("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter2);
605
605
  return guard.secret.cipherFinish(d3, buf, WebCryptoError, "webcrypto/operation", "the recovered AES-CTR plaintext");
606
606
  });
607
607
  }, "decrypt"));
@@ -650,7 +650,7 @@ function _pbkdf2Async(pw, salt, iterations, keylen, digest) {
650
650
  if (next) next();
651
651
  if (err) reject(err); else resolve(derived);
652
652
  }
653
- try { nodeCrypto.pbkdf2(pw, salt, iterations, keylen, digest, done); }
653
+ try { guard.crypto.pbkdf2Async(pw, salt, iterations, keylen, digest, done); }
654
654
  catch (e) { done(e); }
655
655
  }
656
656
  if (_pbkdf2InFlight < _PBKDF2_MAX_CONCURRENT) start(); else _push(_pbkdf2Waiters,start);
@@ -662,7 +662,7 @@ async function _deriveBitsRaw(alg, key, length) {
662
662
  if (name === "ECDH" || name === "X25519" || name === "X448") {
663
663
  _requireAlgMatch(alg, alg.public, name + " public key");
664
664
  _requireOwnKey(alg.public, "deriveBits public key");
665
- var secret = nodeCrypto.diffieHellman({ privateKey: key._handle, publicKey: alg.public._handle });
665
+ var secret = guard.crypto.diffieHellman({ privateKey: key._handle, publicKey: alg.public._handle });
666
666
  try {
667
667
  if (length == null) return _toArrayBuffer(secret);
668
668
  _requireDeriveLength(length, name);
@@ -677,7 +677,7 @@ async function _deriveBitsRaw(alg, key, length) {
677
677
  if (name === "HKDF") {
678
678
  _requireDeriveLength(length, "HKDF");
679
679
  return _withSecretBytes(key, function (ikm) {
680
- var derived = nodeCrypto.hkdfSync(_hashNode(alg.hash, "HKDF"), ikm, _toBuf(alg.salt, "HKDF salt"), _toBuf(alg.info || _bufferAlloc(0), "HKDF info"), length / 8);
680
+ var derived = guard.crypto.hkdf(_hashNode(alg.hash, "HKDF"), ikm, _toBuf(alg.salt, "HKDF salt"), _toBuf(alg.info || _bufferAlloc(0), "HKDF info"), length / 8);
681
681
  return _types.isArrayBuffer(derived) ? derived : _toArrayBuffer(_bufferFrom(derived));
682
682
  });
683
683
  }
@@ -710,7 +710,7 @@ function _x963Kdf(hashNode, z, sharedInfo, lenBytes) {
710
710
  * hash of the shared secret with this counter in it, so a replaced write makes two blocks derive
711
711
  * from the same input and the key material repeats. */
712
712
  var ctr = _bufferAlloc(4); intrinsic.writeUInt32BE(ctr, counter, 0);
713
- var h = nodeCrypto.createHash(hashNode).update(z).update(ctr).update(sharedInfo).digest();
713
+ var h = guard.crypto.digestParts(hashNode, [z, ctr, sharedInfo]);
714
714
  _push(blocks, h); got += h.length; counter += 1;
715
715
  }
716
716
  var joined = _bufferConcat(blocks);
@@ -758,7 +758,7 @@ SubtleCrypto.prototype.encapsulateBits = async function encapsulateBits(algorith
758
758
  _requireAlgMatch(alg, encapsulationKey, "encapsulateBits");
759
759
  if (encapsulationKey.type !== "public") throw new WebCryptoError("webcrypto/invalid-access", "encapsulateBits requires a public (encapsulation) key, got " + _stringify(encapsulationKey.type));
760
760
  var r;
761
- try { r = nodeCrypto.encapsulate(encapsulationKey._handle); }
761
+ try { r = guard.crypto.encapsulate(encapsulationKey._handle); }
762
762
  catch (e) { throw new WebCryptoError("webcrypto/operation", "encapsulateBits: ML-KEM encapsulation failed", e); }
763
763
  try {
764
764
  return { sharedKey: _toArrayBuffer(r.sharedKey), ciphertext: _toArrayBuffer(r.ciphertext) };
@@ -780,7 +780,7 @@ SubtleCrypto.prototype.decapsulateBits = async function decapsulateBits(algorith
780
780
  "decapsulateBits: " + alg.name + " expects a " + kemRow.ct + "-octet ciphertext, got " + ct.length + " (FIPS 203 sec. 7.3)");
781
781
  }
782
782
  var ss;
783
- try { ss = nodeCrypto.decapsulate(decapsulationKey._handle, ct); }
783
+ try { ss = guard.crypto.decapsulate(decapsulationKey._handle, ct); }
784
784
  catch (e) { throw new WebCryptoError("webcrypto/operation", "decapsulateBits: ML-KEM decapsulation failed (malformed or wrong-length ciphertext)", e); }
785
785
  try {
786
786
  return _toArrayBuffer(ss);
@@ -803,7 +803,7 @@ SubtleCrypto.prototype.wrapKey = async function wrapKey(format, key, wrappingKey
803
803
  }
804
804
  try {
805
805
  return _withSecretBytes(wrappingKey, function (wkBytes) {
806
- var c = nodeCrypto.createCipheriv("aes" + wrappingKey.algorithm.length + "-wrap", wkBytes, _bufferFrom("A6A6A6A6A6A6A6A6", "hex"));
806
+ var c = guard.crypto.cipher("aes" + wrappingKey.algorithm.length + "-wrap", wkBytes, _bufferFrom("A6A6A6A6A6A6A6A6", "hex"));
807
807
  return _toArrayBuffer(guard.secret.cipherFinish(c, bytes, WebCryptoError, "webcrypto/operation", "an AES-KW wrap intermediate"));
808
808
  });
809
809
  } catch (e) { throw new WebCryptoError("webcrypto/operation", "wrapKey: AES-KW key wrap failed", e); }
@@ -828,7 +828,7 @@ SubtleCrypto.prototype.unwrapKey = async function unwrapKey(format, wrappedKey,
828
828
  }
829
829
  try {
830
830
  bytes = _withSecretBytes(unwrappingKey, function (kwBytes) {
831
- var d = nodeCrypto.createDecipheriv("aes" + unwrappingKey.algorithm.length + "-wrap", kwBytes, _bufferFrom("A6A6A6A6A6A6A6A6", "hex"));
831
+ var d = guard.crypto.decipher("aes" + unwrappingKey.algorithm.length + "-wrap", kwBytes, _bufferFrom("A6A6A6A6A6A6A6A6", "hex"));
832
832
  return guard.secret.cipherFinish(d, wrapped, WebCryptoError, "webcrypto/operation", "the unwrapped key material");
833
833
  });
834
834
  } catch (e) { throw new WebCryptoError("webcrypto/operation", "unwrapKey: AES-KW key unwrap failed (integrity or length)", e); }
@@ -1021,8 +1021,13 @@ _forEach([ML_DSA_NODE, ML_KEM_NODE, SLH_DSA_NODE], function (m) {
1021
1021
  });
1022
1022
  function _algFromImport(name, alg, keyObject) {
1023
1023
  var wantType = IMPORT_KEY_TYPE[name];
1024
- if (wantType && keyObject && keyObject.asymmetricKeyType && !wantType[keyObject.asymmetricKeyType]) {
1025
- throw new WebCryptoError("webcrypto/data", name + ": the imported key is a " + keyObject.asymmetricKeyType +
1024
+ /** @internal The key's own family, read through the accessor captured at load. This is the check
1025
+ * that binds the algorithm a caller named to the key they supplied, so reading it off the live
1026
+ * prototype let a replaced accessor answer `"rsa"` for an Ed25519 key and the import accepted it
1027
+ * as RSA-PSS. */
1028
+ var actualType = guard.crypto.keyTypeOf(keyObject);
1029
+ if (wantType && actualType && !wantType[actualType]) {
1030
+ throw new WebCryptoError("webcrypto/data", name + ": the imported key is a " + actualType +
1026
1031
  " key, which is not compatible with algorithm " + name);
1027
1032
  }
1028
1033
  if (name === "ECDSA" || name === "ECDH") {
@@ -1136,17 +1141,17 @@ Crypto.prototype.getRandomValues = function getRandomValues(typedArray) {
1136
1141
  if (out.length > MAX_RANDOM_BYTES) {
1137
1142
  throw new WebCryptoError("webcrypto/data", "getRandomValues: byteLength exceeds " + MAX_RANDOM_BYTES);
1138
1143
  }
1139
- nodeCrypto.randomFillSync(out);
1144
+ guard.crypto.randomFill(out);
1140
1145
  return typedArray;
1141
1146
  };
1142
1147
 
1143
- Crypto.prototype.randomUUID = function randomUUID() { return nodeCrypto.randomUUID(); };
1148
+ Crypto.prototype.randomUUID = function randomUUID() { return guard.crypto.randomUUID(); };
1144
1149
 
1145
1150
  function decompressEcPoint(sec1Compressed, nodeCurve, E, code) {
1146
1151
  var head = sec1Compressed[0];
1147
1152
  if (head !== 0x02 && head !== 0x03) throw E(code, "EC point de-compression expects a compressed SEC1 point (0x02/0x03)");
1148
1153
  try {
1149
- return nodeCrypto.ECDH.convertKey(sec1Compressed, nodeCurve, undefined, undefined, "uncompressed");
1154
+ return guard.crypto.ecConvertPoint(sec1Compressed, nodeCurve, "uncompressed");
1150
1155
  } catch (e) {
1151
1156
  throw E(code, "EC point is not on curve " + nodeCurve + " (de-compression failed)", e);
1152
1157
  }
@@ -1170,9 +1175,19 @@ function isCryptoKeyLike(x) {
1170
1175
  * key this engine did not make while the others returned it. A JWK is an object rather than
1171
1176
  * bytes, so only the byte formats are wrapped. */
1172
1177
  function exportAnyKey(key, E, code, want) {
1173
- var format = want || _EXPORT_FORMAT[key && key.type];
1178
+ /** @internal At most ONE read of the key's type, and none at all when the caller named the format
1179
+ * it wants. It is a getter on node's own CryptoKey, so each read is a call a replacement answers,
1180
+ * and reading it per decision let one answer "private" where a PEM label was chosen and "public"
1181
+ * where the bytes were, which put a public key inside a `PRIVATE KEY` block. */
1182
+ var keyType;
1183
+ var readType = false;
1184
+ function typeOnce() {
1185
+ if (!readType) { keyType = key == null ? undefined : key.type; readType = true; }
1186
+ return keyType;
1187
+ }
1188
+ var format = want || _EXPORT_FORMAT[typeOnce()];
1174
1189
  if (!format) throw E(code, "a CryptoKey with a private, public, or secret type is required");
1175
- if (want === "jwk" && !_EXPORT_FORMAT[key && key.type]) {
1190
+ if (want === "jwk" && !_EXPORT_FORMAT[typeOnce()]) {
1176
1191
  throw E(code, "a CryptoKey with a private, public, or secret type is required");
1177
1192
  }
1178
1193
  var asJwk = format === "jwk";
@@ -1186,7 +1201,7 @@ function exportAnyKey(key, E, code, want) {
1186
1201
  throw E(code, "the CryptoKey comes from a different WebCrypto implementation and is not extractable, so its key material cannot be reached; import it through pki.webcrypto.subtle, or pass the key as DER");
1187
1202
  }
1188
1203
  var handle = key._handle;
1189
- if (handle instanceof nodeCrypto.KeyObject && handle.type === key.type) {
1204
+ if (guard.crypto.isKeyObject(handle) && guard.crypto.keyKind(handle) === key.type) {
1190
1205
  return _resolve(_Promise).then(function () {
1191
1206
  if (asJwk) return guard.crypto.exportKey(handle, { format: "jwk" });
1192
1207
  return format === "raw" ? guard.crypto.exportKey(handle) : guard.crypto.exportKey(handle, { format: "der", type: format });
@@ -1195,7 +1210,7 @@ function exportAnyKey(key, E, code, want) {
1195
1210
  });
1196
1211
  }
1197
1212
  return _resolve(_Promise)
1198
- .then(function () { return nodeCrypto.webcrypto.subtle.exportKey(format, key); })
1213
+ .then(function () { return guard.crypto.nodeExportKey(format, key); })
1199
1214
  .then(wrap, function (e) {
1200
1215
  throw E(code, "the CryptoKey comes from a different WebCrypto implementation and could not be exported for re-import; import it through pki.webcrypto.subtle, or pass the key as DER", e);
1201
1216
  });
package/lib/x509-sign.js CHANGED
@@ -166,7 +166,7 @@ var RESERVED_ALT_EXTS = intrinsic.assign(intrinsic.create(null), (function () {
166
166
  })());
167
167
 
168
168
  function _buildExtensions(extSpec, ctx) {
169
- if (extSpec == null) extSpec = {};
169
+ if (extSpec == null) extSpec = intrinsic.create(null);
170
170
  if (_isArray(extSpec)) {
171
171
  var seenExt = intrinsic.create(null), arrCa = false, arrKeyCertSign = false, arrPathLen = false, arrNameConstraints = false;
172
172
  var oidBc = O("basicConstraints"), oidKu = O("keyUsage"), oidNc = O("nameConstraints"), oidPm = O("policyMappings");
@@ -708,9 +708,9 @@ function sign(spec, issuer, opts) {
708
708
  }
709
709
 
710
710
  function _sign(spec, issuer, opts) {
711
- opts = opts || {};
711
+ opts = opts || intrinsic.create(null);
712
712
  if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("x509/bad-input", "the certificate spec must be an object");
713
- issuer = issuer || {};
713
+ issuer = issuer || intrinsic.create(null);
714
714
  guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, _err, "x509/bad-input", function (k) {
715
715
  return "unknown certificate spec field " + JSON.stringify(k) +
716
716
  (k === "issuer" ? "; the issuer is the SECOND argument to pki.x509.sign, not a spec field" : "") +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.8.60",
3
+ "version": "0.9.0",
4
4
  "description": "Pure-JavaScript PKI toolkit that owns its stack — X.509, ASN.1/DER, CMS, PQC-first.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
package/sbom.cdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:a0bc3a87-4c9e-4598-95ba-7457dca63e87",
5
+ "serialNumber": "urn:uuid:f52bf92f-41f7-4879-bff9-6077f2cf84f5",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-10-07T18:31:09.061Z",
8
+ "timestamp": "2026-10-08T01:34:26.318Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "build"
@@ -19,14 +19,14 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@blamejs/pki@0.8.60",
22
+ "bom-ref": "@blamejs/pki@0.9.0",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.8.60",
25
+ "version": "0.9.0",
26
26
  "scope": "required",
27
27
  "author": "blamejs contributors",
28
28
  "description": "Pure-JavaScript PKI toolkit that owns its stack — X.509, ASN.1/DER, CMS, PQC-first.",
29
- "purl": "pkg:npm/%40blamejs/pki@0.8.60",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.9.0",
30
30
  "properties": [],
31
31
  "externalReferences": [
32
32
  {
@@ -54,7 +54,7 @@
54
54
  "components": [],
55
55
  "dependencies": [
56
56
  {
57
- "ref": "@blamejs/pki@0.8.60",
57
+ "ref": "@blamejs/pki@0.9.0",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]