@blamejs/pki 0.8.60 → 0.8.61

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.
package/lib/sigstore.js CHANGED
@@ -28,7 +28,6 @@
28
28
  * @card Verify an npm --provenance Sigstore bundle offline (DSSE + Fulcio + Rekor + SLSA).
29
29
  */
30
30
 
31
- var nodeCrypto = require("crypto");
32
31
  var frameworkError = require("./framework-error");
33
32
  var constants = require("./constants");
34
33
  var asn1 = require("./asn1-der");
@@ -227,8 +226,8 @@ function _assertKeyDetailsParameters(want, leafSpki, declared) {
227
226
  if (want.bits !== undefined) {
228
227
  var bits;
229
228
  try {
230
- bits = guard.crypto.publicKey({ key: leafSpki.bytes, format: "der", type: "spki" })
231
- .asymmetricKeyDetails.modulusLength;
229
+ bits = guard.crypto.keyDetails(
230
+ guard.crypto.publicKey({ key: leafSpki.bytes, format: "der", type: "spki" })).modulusLength;
232
231
  } catch (_e) { bits = null; } // allow:swallow-unverified -- a key that will not import has no modulus size to match, and the mismatch below is the verdict
233
232
  if (bits !== want.bits) {
234
233
  throw _err("sigstore/entry-mismatch", "the Rekor entry states the signing key is " +
@@ -709,13 +708,14 @@ function _chainDers(vm) {
709
708
  }
710
709
 
711
710
  function _rawVerify(keyObj, data, derSig) {
712
- var t = keyObj.asymmetricKeyType;
711
+ var t = guard.crypto.keyType(keyObj);
713
712
  if (t === "ed25519" || t === "ed448") {
714
713
  var edSpki = guard.crypto.exportKey(keyObj, { type: "spki", format: "der" });
715
714
  edwardsPoint.validateSpki(edSpki, t === "ed25519" ? 6 : 7, SigstoreError, "sigstore/bad-key");
716
715
  return guard.crypto.verify(null, data, keyObj, derSig);
717
716
  }
718
- var crv = keyObj.asymmetricKeyDetails && keyObj.asymmetricKeyDetails.namedCurve;
717
+ var keyObjDetails = guard.crypto.keyDetails(keyObj);
718
+ var crv = keyObjDetails && keyObjDetails.namedCurve;
719
719
  var hash = crv === "secp384r1" ? "sha384" : (crv === "secp521r1" ? "sha512" : "sha256");
720
720
  return guard.crypto.verify(hash, data, { key: keyObj, dsaEncoding: "der" }, derSig);
721
721
  }
@@ -723,7 +723,7 @@ function _pubFromSpki(spkiDer, label) {
723
723
  var key;
724
724
  try { key = guard.crypto.publicKey({ key: spkiDer, format: "der", type: "spki" }); }
725
725
  catch (e) { throw _err("sigstore/bad-key", "invalid " + label + " public key", e); }
726
- var t = key.asymmetricKeyType;
726
+ var t = guard.crypto.keyType(key);
727
727
  if (t === "ed25519" || t === "ed448") {
728
728
  edwardsPoint.validateSpki(spkiDer, t === "ed25519" ? 6 : 7, SigstoreError, "sigstore/bad-key");
729
729
  }
@@ -735,7 +735,7 @@ function _parseCert(der, label) {
735
735
  }
736
736
 
737
737
 
738
- function _sha256(buf) { return nodeCrypto.createHash("sha256").update(buf).digest(); }
738
+ function _sha256(buf) { return guard.crypto.digest("sha256", buf); }
739
739
 
740
740
  function _toMs(x) {
741
741
  if (x == null) return null;
@@ -1109,7 +1109,7 @@ function _bindHashedRekordV002Entry(body, arm, leafDer, contentType, payloadType
1109
1109
  }
1110
1110
  var digest = _b64(data.digest, "hashedRekordV002.data.digest");
1111
1111
  if (contentType === "dsseEnvelope") {
1112
- var computed = nodeCrypto.createHash(alg.node).update(pae(payloadType, payload)).digest();
1112
+ var computed = guard.crypto.digest(alg.node, pae(payloadType, payload));
1113
1113
  if (!guard.crypto.constantTimeEqual(computed, digest)) {
1114
1114
  throw _err("sigstore/entry-mismatch", "the Rekor entry digest is not the hash of this envelope's " +
1115
1115
  "signing preimage, so the entry records a different signature than the bundle carries");
@@ -1831,7 +1831,7 @@ async function verifyBundle(bundle, opts) {
1831
1831
  var artifactDigests = intrinsic.create(null);
1832
1832
  function _artifactDigest(nodeName) {
1833
1833
  if (!intrinsic.hasOwn(artifactDigests, nodeName)) {
1834
- artifactDigests[nodeName] = nodeCrypto.createHash(nodeName).update(artifact).digest();
1834
+ artifactDigests[nodeName] = guard.crypto.digest(nodeName, artifact);
1835
1835
  }
1836
1836
  return artifactDigests[nodeName];
1837
1837
  }
package/lib/smime.js CHANGED
@@ -48,7 +48,6 @@ var _push = guard.list.append;
48
48
  var pkiBuild = require("./pki-build.js");
49
49
  var C = require("./constants.js");
50
50
  var nodeUtil = require("util");
51
- var nodeCrypto = require("crypto");
52
51
 
53
52
  var SmimeError = frameworkError.SmimeError;
54
53
 
@@ -591,7 +590,7 @@ function _micalgOf(p7Der) {
591
590
  return out.length ? out.sort().join(",") : null;
592
591
  }
593
592
 
594
- function _boundary() { return "----=_pki_smime_" + nodeCrypto.randomBytes(18).toString("hex"); }
593
+ function _boundary() { return "----=_pki_smime_" + guard.crypto.randomBytes(18).toString("hex"); }
595
594
 
596
595
  function _wrap64Crlf(s) {
597
596
  var out = "";
package/lib/tlog.js CHANGED
@@ -299,12 +299,13 @@ function _resolveKey(keyName, publicKey) {
299
299
  throw _err("tlog/bad-input", "publicKey must be the raw " + ED25519_RAW_BYTES +
300
300
  " Ed25519 bytes or a SubjectPublicKeyInfo, got " + bytes.length + " bytes", e);
301
301
  }
302
- var type = key.asymmetricKeyType;
302
+ var type = guard.crypto.keyType(key);
303
303
  if (type === "ed25519") {
304
304
  return _edKey(name, bytes, _subarray(bytes, bytes.length - ED25519_RAW_BYTES));
305
305
  }
306
306
  if (type === "ec") {
307
- var curve = key.asymmetricKeyDetails && key.asymmetricKeyDetails.namedCurve;
307
+ var keyDetails = guard.crypto.keyDetails(key);
308
+ var curve = keyDetails && keyDetails.namedCurve;
308
309
  if (EC_CURVES[curve] !== 1) {
309
310
  throw _err("tlog/bad-input", "a signed note names no key-ID derivation for the elliptic curve " +
310
311
  guard.text.showValue(_stringOf(curve)));
package/lib/tuf.js CHANGED
@@ -798,12 +798,13 @@ function _declarationOf(key) {
798
798
  function _checkedPublicKey(key, d) {
799
799
  if (d.nodeType === "ed25519") return null;
800
800
  var imported = _publicFromPem(key.keyval.public, "a " + key.keytype + " public key");
801
- if (imported.asymmetricKeyType !== d.nodeType) {
801
+ var importedType = guard.crypto.keyType(imported);
802
+ if (importedType !== d.nodeType) {
802
803
  throw _err("tuf/bad-key", "the key declared as " + key.keytype + " holds a " +
803
- guard.text.showValue(imported.asymmetricKeyType) + " public key, so the signature would be checked " +
804
+ guard.text.showValue(importedType) + " public key, so the signature would be checked " +
804
805
  "under an algorithm the metadata does not name");
805
806
  }
806
- var details = imported.asymmetricKeyDetails || {};
807
+ var details = guard.crypto.keyDetails(imported) || {};
807
808
  if (d.curve !== null && details.namedCurve !== d.curve) {
808
809
  throw _err("tuf/bad-key", "the scheme " + key.scheme + " names the " + d.curve +
809
810
  " curve; the key is on " + guard.text.showValue(details.namedCurve));
@@ -7,7 +7,7 @@ var cbor = require("./cbor-det");
7
7
  var asn1 = require("./asn1-der");
8
8
  var oid = require("./oid");
9
9
  var edwardsPoint = require("./edwards-point");
10
- var nodeCrypto = require("crypto");
10
+ var guard = require("./guard-all.js");
11
11
 
12
12
  var EC2_CRV_LEN = Object.assign(Object.create(null), { 1: 32, 2: 48, 3: 66 });
13
13
  var EC2_CRV_OID = Object.assign(Object.create(null), { 1: "prime256v1", 2: "secp384r1", 3: "secp521r1" });
@@ -114,7 +114,7 @@ function assertKeyMaterial(key, E, code, unsupportedCode) {
114
114
  if (!prof) throw new E(unsupportedCode || code, "unsupported credential key algorithm " + key.alg);
115
115
  if (prof.kty !== key.kty) throw bad("credential key algorithm " + key.alg + " is inconsistent with key type " + key.kty);
116
116
  if (prof.crv != null && prof.crv !== key.crv) throw bad("credential key algorithm " + key.alg + " requires a different curve");
117
- try { nodeCrypto.createPublicKey({ key: toSpki(key, E, code), format: "der", type: "spki" }); }
117
+ try { guard.crypto.publicKey({ key: toSpki(key, E, code), format: "der", type: "spki" }); }
118
118
  catch (e) { throw bad("the credential public key point is not valid for its curve", e); }
119
119
  if (Number(key.kty) === 1 && !edwardsPoint.validate(key.x, key.crv)) throw bad("the OKP credential public key is not a valid, full-order Edwards point");
120
120
  return key;
@@ -26,12 +26,6 @@ var _charAt = intrinsic.uncurry(String.prototype.charAt);
26
26
  var _strToLowerCase = intrinsic.toLowerCase;
27
27
  var _strSlice = intrinsic.uncurry(String.prototype.slice);
28
28
  var _strSplit = intrinsic.uncurry(String.prototype.split);
29
- /** @internal The hash constructor and the methods of the object it returns. What a digest here
30
- * produces is a metadata lookup key and the identity two certificates are told apart by, so a
31
- * replaced constructor, update or digest decides which entry governs an attestation. */
32
- var _createHash = _nodeCrypto.createHash;
33
- var _hashUpdate = intrinsic.uncurry(_nodeCrypto.createHash("sha256").update);
34
- var _hashDigest = intrinsic.uncurry(_nodeCrypto.createHash("sha256").digest);
35
29
  var jose = require("./jose");
36
30
  var rfc3339 = require("./rfc3339");
37
31
  var constants = require("./constants");
@@ -702,7 +696,9 @@ function certKeyIdentifier(cert) {
702
696
  if (!pk || !intrinsic.isBuffer(pk.bytes)) {
703
697
  throw _err("webauthn/bad-input", "certKeyIdentifier expects a parsed certificate carrying a subject public key");
704
698
  }
705
- return _hashDigest(_hashUpdate(_createHash("sha1"), pk.bytes), "hex");
699
+ /** @internal A metadata lookup key, and the identity two certificates are told apart by, so
700
+ * whatever computes it decides which entry governs an attestation. */
701
+ return guard.crypto.digest("sha1", pk.bytes, { output: "hex" });
706
702
  }
707
703
 
708
704
  function metadataForKeyIdentifier(metadata, keyId) {
package/lib/webauthn.js CHANGED
@@ -54,7 +54,6 @@ var _promiseResolve = intrinsic.uncurry(intrinsic.promiseResolve);
54
54
  var _promiseReject = intrinsic.uncurry(intrinsic.promiseReject);
55
55
  var jose = require("./jose");
56
56
  var mds = require("./webauthn-mds");
57
- var nodeCrypto = require("crypto");
58
57
 
59
58
  var WebauthnError = frameworkError.WebauthnError;
60
59
  function _err(code, message, cause) { return new WebauthnError(code, message, cause); }
@@ -76,16 +75,10 @@ var _subtleVerify = intrinsic.uncurry(subtle.verify);
76
75
  * while the bytes handed in were never the credential's. */
77
76
  var _subtleImportKey = intrinsic.uncurry(subtle.importKey);
78
77
 
79
- /** @internal The hash constructor is captured, and so are the methods of the object it returns. Every
80
- * attestation comparison in this module rests on a digest, so a replaced `createHash`, or a replaced
81
- * `update` or `digest` on the object it hands back, chooses what the comparison sees. */
82
- var _createHash = nodeCrypto.createHash;
83
- function _sha(name, buf) {
84
- var h = _createHash(name);
85
- return _hashDigest(_hashUpdate(h, buf));
86
- }
87
- var _hashUpdate = intrinsic.uncurry(nodeCrypto.createHash("sha256").update);
88
- var _hashDigest = intrinsic.uncurry(nodeCrypto.createHash("sha256").digest);
78
+ /** @internal Every attestation comparison in this module rests on a digest, so whatever computes one
79
+ * chooses what the comparison sees. The guard owns the hash construction and the methods of the
80
+ * object it returns. */
81
+ function _sha(name, buf) { return guard.crypto.digest(name, buf); }
89
82
  /** @internal The comparison goes through the captured operation. This is what decides that an
90
83
  * attestation statement's key is the credential's key, so a replacement answering zero makes a
91
84
  * different key match. */
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.8.60",
3
+ "version": "0.8.61",
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:dc638a09-3eb3-4620-b84b-f3edd3453ec6",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-10-07T18:31:09.061Z",
8
+ "timestamp": "2026-10-07T23:02:52.146Z",
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.8.61",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.8.60",
25
+ "version": "0.8.61",
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.8.61",
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.8.61",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]