@blamejs/pki 0.8.59 → 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.
Files changed (75) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/lib/acme.js +15 -7
  3. package/lib/alt-sig.js +3 -1
  4. package/lib/asn1-der.js +82 -34
  5. package/lib/attrcert-sign.js +19 -16
  6. package/lib/byte-writer.js +63 -13
  7. package/lib/cbor-det.js +9 -3
  8. package/lib/cmc-build.js +26 -18
  9. package/lib/cmp-build.js +35 -33
  10. package/lib/cmp-session.js +19 -9
  11. package/lib/cms-decrypt.js +37 -23
  12. package/lib/cms-digest.js +2 -3
  13. package/lib/cms-encrypt.js +38 -33
  14. package/lib/cms-sign.js +65 -43
  15. package/lib/cms-verify.js +8 -4
  16. package/lib/composite-kem.js +28 -29
  17. package/lib/crl-sign.js +24 -17
  18. package/lib/crmf-sign.js +11 -17
  19. package/lib/csr-sign.js +5 -2
  20. package/lib/ct.js +38 -25
  21. package/lib/est.js +12 -9
  22. package/lib/guard-bytes.js +5 -1
  23. package/lib/guard-crypto.js +506 -14
  24. package/lib/guard-der.js +6 -1
  25. package/lib/guard-intrinsic.js +12 -4
  26. package/lib/guard-list.js +64 -0
  27. package/lib/guard-name.js +1 -1
  28. package/lib/guard-secret.js +3 -2
  29. package/lib/hpke.js +34 -27
  30. package/lib/http-digest.js +5 -7
  31. package/lib/http-transport.js +12 -3
  32. package/lib/inspect.js +10 -2
  33. package/lib/jose.js +3 -1
  34. package/lib/key.js +41 -29
  35. package/lib/lint.js +236 -152
  36. package/lib/mime.js +9 -5
  37. package/lib/ocsp.js +26 -24
  38. package/lib/path-validate.js +43 -13
  39. package/lib/pbes2.js +12 -9
  40. package/lib/pkcs11-uri.js +3 -1
  41. package/lib/pkcs12-build.js +19 -17
  42. package/lib/pki-build.js +17 -13
  43. package/lib/possession.js +3 -1
  44. package/lib/rc2.js +6 -2
  45. package/lib/revocation-fetch.js +78 -19
  46. package/lib/scep.js +21 -14
  47. package/lib/schema-attrcert.js +4 -2
  48. package/lib/schema-c509.js +94 -78
  49. package/lib/schema-cmc.js +5 -2
  50. package/lib/schema-cmp.js +6 -3
  51. package/lib/schema-cms.js +7 -4
  52. package/lib/schema-crl.js +1 -1
  53. package/lib/schema-crmf.js +1 -1
  54. package/lib/schema-csr.js +3 -3
  55. package/lib/schema-engine.js +36 -18
  56. package/lib/schema-pkcs1.js +7 -3
  57. package/lib/schema-pkcs12.js +9 -6
  58. package/lib/schema-pkix.js +19 -3
  59. package/lib/schema-sec1.js +4 -1
  60. package/lib/schema-tsp.js +7 -4
  61. package/lib/shbs.js +10 -9
  62. package/lib/sign-scheme.js +2 -2
  63. package/lib/sigstore.js +9 -9
  64. package/lib/smime.js +19 -16
  65. package/lib/tlog.js +20 -13
  66. package/lib/tuf.js +7 -4
  67. package/lib/validator-cose.js +2 -2
  68. package/lib/validator-keydesc.js +4 -1
  69. package/lib/validator-tls.js +7 -2
  70. package/lib/webauthn-mds.js +3 -7
  71. package/lib/webauthn.js +4 -11
  72. package/lib/webcrypto.js +70 -49
  73. package/lib/x509-sign.js +20 -15
  74. package/package.json +1 -1
  75. package/sbom.cdx.json +6 -6
package/lib/tuf.js CHANGED
@@ -57,7 +57,9 @@ var _hasOwn = intrinsic.hasOwn;
57
57
  var _bufferFrom = intrinsic.bufferFrom;
58
58
  var _bufferConcat = intrinsic.bufferConcat;
59
59
  var _bufToString = intrinsic.bufToString;
60
- var _push = intrinsic.push;
60
+ /** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
61
+ * setter, so an accessor there takes the element being appended. `append` defines it. */
62
+ var _push = intrinsic.append;
61
63
  var _strSlice = intrinsic.uncurry(String.prototype.slice);
62
64
  var _codePointAt = intrinsic.uncurry(String.prototype.codePointAt);
63
65
  var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
@@ -796,12 +798,13 @@ function _declarationOf(key) {
796
798
  function _checkedPublicKey(key, d) {
797
799
  if (d.nodeType === "ed25519") return null;
798
800
  var imported = _publicFromPem(key.keyval.public, "a " + key.keytype + " public key");
799
- if (imported.asymmetricKeyType !== d.nodeType) {
801
+ var importedType = guard.crypto.keyType(imported);
802
+ if (importedType !== d.nodeType) {
800
803
  throw _err("tuf/bad-key", "the key declared as " + key.keytype + " holds a " +
801
- 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 " +
802
805
  "under an algorithm the metadata does not name");
803
806
  }
804
- var details = imported.asymmetricKeyDetails || {};
807
+ var details = guard.crypto.keyDetails(imported) || {};
805
808
  if (d.curve !== null && details.namedCurve !== d.curve) {
806
809
  throw _err("tuf/bad-key", "the scheme " + key.scheme + " names the " + d.curve +
807
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;
@@ -4,6 +4,9 @@
4
4
  // @internal
5
5
 
6
6
  var asn1 = require("./asn1-der");
7
+ /** @internal The append this module's list is built with: `push` stores at the index and a store
8
+ * consults a setter inherited there, which takes the element being appended. */
9
+ var _push = require("./guard-list").append;
7
10
 
8
11
  function _alGet(seqNode, tag) {
9
12
  if (!seqNode || !seqNode.children) return null;
@@ -23,7 +26,7 @@ function _purposeUnion(a, b, E, code) {
23
26
  var out = [];
24
27
  [a, b].forEach(function (list) {
25
28
  var p = _alGet(list, 1);
26
- if (p && p.children) p.children.forEach(function (c) { var v = _alInt(c, E, code); if (out.indexOf(v) === -1) out.push(v); });
29
+ if (p && p.children) p.children.forEach(function (c) { var v = _alInt(c, E, code); if (out.indexOf(v) === -1) _push(out,v); });
27
30
  });
28
31
  return out;
29
32
  }
@@ -5,6 +5,11 @@
5
5
 
6
6
  var C = require("./constants");
7
7
  var ByteReader = require("./byte-reader");
8
+ /** @internal The append every list here is built with. `push` STORES at the index and a store walks
9
+ * the prototype chain for a setter, so an accessor inherited at an array index takes the element
10
+ * being appended. Taken from `guard-list` rather than `guard-intrinsic`, since this module needs the
11
+ * one primitive and not the captures. */
12
+ var _push = require("./guard-list").append;
8
13
 
9
14
  var MAX_VECTOR_24 = 0xffffff;
10
15
  var MAX_VECTOR_16 = 0xffff;
@@ -36,7 +41,7 @@ function _extensionRecords(view, E, codes) {
36
41
  type + " (RFC 8446 sec. 4.2)");
37
42
  }
38
43
  seen[type] = true;
39
- out.push({ type: type, data: Buffer.from(data) });
44
+ _push(out,{ type: type, data: Buffer.from(data) });
40
45
  }
41
46
  return out;
42
47
  }
@@ -68,7 +73,7 @@ function certificateMessage(view, E, codes, certificateType) {
68
73
  };
69
74
  if (certificateType === "RawPublicKey") entry.spki = Buffer.from(data);
70
75
  else entry.certData = Buffer.from(data);
71
- entries.push(entry);
76
+ _push(entries,entry);
72
77
  }
73
78
  return { certificateRequestContext: Buffer.from(context), entries: entries };
74
79
  }
@@ -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
@@ -89,7 +89,9 @@ var _subarray = intrinsic.subarray;
89
89
  var _arrayBufferSlice = intrinsic.arrayBufferSlice;
90
90
  var _numberToString = intrinsic.numberToString;
91
91
  var _bigIntToString = intrinsic.bigIntToString;
92
- var _push = intrinsic.push;
92
+ /** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
93
+ * setter, so an accessor there takes the element being appended. `append` defines it. */
94
+ var _push = intrinsic.append;
93
95
  var _concat = intrinsic.concat;
94
96
  var _resolve = intrinsic.uncurry(intrinsic.promiseResolve);
95
97
  /** @internal The promise constructor, captured at load. `promiseResolve` builds its promise from the
@@ -222,7 +224,11 @@ function CryptoKey(type, extractable, algorithm, usages, handle) {
222
224
  if (usages != null && !_isArray(usages)) {
223
225
  throw new WebCryptoError("webcrypto/syntax", "usages must be an array of key-usage strings");
224
226
  }
225
- this.usages = usages ? _arraySlice(usages) : [];
227
+ /** @internal `copyList`, not the captured `slice`. `Array.prototype.slice` builds its result
228
+ * through `ArraySpeciesCreate`, which reads the receiver's `constructor` and then its
229
+ * `Symbol.species`, so the copy of a caller's usage list ran a lookup the caller could answer.
230
+ * `copyList` defines each index on a plain array. */
231
+ this.usages = usages ? intrinsic.copyList(usages) : [];
226
232
  _defineProperty(this, "_handle", { value: handle, enumerable: false });
227
233
  }
228
234
 
@@ -255,10 +261,10 @@ SubtleCrypto.prototype.digest = async function digest(algorithm, data) {
255
261
  var name = _normalizeAlg(algorithm, "digest").name;
256
262
  var xof = XOF_NODE[_toUpperCase(_String(name))];
257
263
  var h = xof
258
- ? nodeCrypto.createHash(xof.node, { outputLength: xof.length })
259
- : nodeCrypto.createHash(_hashNode(name, "digest"));
260
- h.update(_toBuf(data, "digest"));
261
- 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));
262
268
  };
263
269
 
264
270
  SubtleCrypto.prototype.digestStream = async function digestStream(algorithms, source) {
@@ -270,8 +276,8 @@ SubtleCrypto.prototype.digestStream = async function digestStream(algorithms, so
270
276
  var name = _normalizeAlg(algorithms[_h], "digestStream").name;
271
277
  var xof = XOF_NODE[_toUpperCase(_String(name))];
272
278
  hashes[_h] = xof
273
- ? nodeCrypto.createHash(xof.node, { outputLength: xof.length })
274
- : nodeCrypto.createHash(_hashNode(name, "digestStream"));
279
+ ? guard.crypto.hash(xof.node, xof.length)
280
+ : guard.crypto.hash(_hashNode(name, "digestStream"));
275
281
  }
276
282
  var acquire = source == null ? undefined : source[_asyncIterator];
277
283
  if (typeof acquire !== "function") {
@@ -301,8 +307,8 @@ SubtleCrypto.prototype.digestStream = async function digestStream(algorithms, so
301
307
 
302
308
  SubtleCrypto.prototype.encryptStream = async function encryptStream(spec, source) {
303
309
  var cipher = spec.authTagLength
304
- ? nodeCrypto.createCipheriv(spec.algNode, spec.key, spec.iv, { authTagLength: spec.authTagLength })
305
- : 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);
306
312
  if (spec.aad && spec.aad.length) _cipherSetAAD(cipher, spec.aad);
307
313
  var acquire = source == null ? undefined : source[_asyncIterator];
308
314
  if (typeof acquire !== "function") {
@@ -338,7 +344,7 @@ SubtleCrypto.prototype.encryptStream = async function encryptStream(spec, source
338
344
  };
339
345
 
340
346
  SubtleCrypto.prototype.decryptStream = function decryptStream(spec, ct) {
341
- var decipher = nodeCrypto.createDecipheriv(spec.algNode, spec.key, spec.iv);
347
+ var decipher = guard.crypto.decipher(spec.algNode, spec.key, spec.iv);
342
348
  return _decipherDrive(decipher, _bufferFrom(_toBuf(ct, "decryptStream ciphertext")), _STREAM_CHUNK);
343
349
  };
344
350
  async function* _decipherDrive(decipher, ct, chunkSize) {
@@ -362,12 +368,12 @@ SubtleCrypto.prototype.generateKey = async function generateKey(algorithm, extra
362
368
  if (name === "AES-GCM" || name === "AES-CBC" || name === "AES-CTR" || name === "AES-KW") {
363
369
  var bits = alg.length;
364
370
  if (bits !== 128 && bits !== 192 && bits !== 256) throw new WebCryptoError("webcrypto/syntax", name + ": length must be 128/192/256");
365
- var secret = guard.crypto.secretKey(nodeCrypto.randomBytes(bits / 8));
371
+ var secret = guard.crypto.secretKey(guard.crypto.randomBytes(bits / 8));
366
372
  return new CryptoKey("secret", extractable, { name: name, length: bits }, usages, secret);
367
373
  }
368
374
  if (name === "HMAC") {
369
375
  var lenBits = _hmacLengthBits(alg, "generateKey HMAC");
370
- var hkey = guard.crypto.secretKey(nodeCrypto.randomBytes(lenBits / 8));
376
+ var hkey = guard.crypto.secretKey(guard.crypto.randomBytes(lenBits / 8));
371
377
  return new CryptoKey("secret", extractable, { name: name, hash: { name: (typeof alg.hash === "string" ? alg.hash : alg.hash.name) }, length: lenBits }, usages, hkey);
372
378
  }
373
379
 
@@ -385,7 +391,7 @@ function _generateKeyPair(alg) {
385
391
  var name = alg.name, kp, algorithm;
386
392
  if (name === "RSASSA-PKCS1-V1_5" || name === "RSA-PSS" || name === "RSA-OAEP") {
387
393
  var rsaHash = _hashObj(alg.hash, "generateKey " + name);
388
- kp = nodeCrypto.generateKeyPairSync("rsa", {
394
+ kp = guard.crypto.generateKeyPair("rsa", {
389
395
  modulusLength: alg.modulusLength || 2048,
390
396
  publicExponent: alg.publicExponent ? _bufToBigIntNum(alg.publicExponent) : 65537,
391
397
  });
@@ -393,19 +399,19 @@ function _generateKeyPair(alg) {
393
399
  } else if (name === "ECDSA" || name === "ECDH") {
394
400
  var curve = alg.namedCurve;
395
401
  if (!CURVE_NODE[curve]) throw new WebCryptoError("webcrypto/not-supported", name + ": unsupported curve " + _stringify(curve));
396
- kp = nodeCrypto.generateKeyPairSync("ec", { namedCurve: CURVE_NODE[curve] });
402
+ kp = guard.crypto.generateKeyPair("ec", { namedCurve: CURVE_NODE[curve] });
397
403
  algorithm = { name: name, namedCurve: curve };
398
404
  } else if (name === "ED25519" || name === "ED448" || name === "X25519" || name === "X448") {
399
- kp = nodeCrypto.generateKeyPairSync(_toLowerCase(name));
405
+ kp = guard.crypto.generateKeyPair(_toLowerCase(name));
400
406
  algorithm = { name: _stdName(name) };
401
407
  } else if (ML_DSA_NODE[name]) {
402
- kp = nodeCrypto.generateKeyPairSync(ML_DSA_NODE[name]);
408
+ kp = guard.crypto.generateKeyPair(ML_DSA_NODE[name]);
403
409
  algorithm = { name: name };
404
410
  } else if (ML_KEM_NODE[name]) {
405
- kp = nodeCrypto.generateKeyPairSync(ML_KEM_NODE[name]);
411
+ kp = guard.crypto.generateKeyPair(ML_KEM_NODE[name]);
406
412
  algorithm = { name: name };
407
413
  } else if (SLH_DSA_NODE[name]) {
408
- kp = nodeCrypto.generateKeyPairSync(SLH_DSA_NODE[name]);
414
+ kp = guard.crypto.generateKeyPair(SLH_DSA_NODE[name]);
409
415
  algorithm = { name: name };
410
416
  } else {
411
417
  throw new WebCryptoError("webcrypto/not-supported", "generateKey: unsupported algorithm " + _stringify(name));
@@ -509,7 +515,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
509
515
  if (!ENCRYPT_DECRYPT_NAMES[name]) throw new WebCryptoError("webcrypto/not-supported", "encrypt: unsupported algorithm " + _stringify(name));
510
516
  _requireAlgMatch(alg, key, "encrypt");
511
517
  if (name === "RSA-OAEP") {
512
- return _toArrayBuffer(nodeCrypto.publicEncrypt({
518
+ return _toArrayBuffer(guard.crypto.publicEncrypt({
513
519
  key: key._handle, padding: guard.crypto.padding.RSA_PKCS1_OAEP,
514
520
  oaepHash: _hashNode(key.algorithm.hash, "encrypt"),
515
521
  oaepLabel: alg.label ? _toBuf(alg.label, "encrypt label") : undefined,
@@ -520,10 +526,10 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
520
526
  var aad = alg.additionalData ? _toBuf(alg.additionalData, "AES-GCM aad") : null;
521
527
  return _toArrayBuffer(_runCipher(function () {
522
528
  return _withSecretBytes(key, function (kb) {
523
- var cipher = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: (alg.tagLength || 128) / 8 });
524
- 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);
525
531
  var ct = guard.secret.cipherFinish(cipher, buf, WebCryptoError, "webcrypto/operation", "an AES-GCM encrypt intermediate");
526
- return _bufferConcat([ct, cipher.getAuthTag()]);
532
+ return _bufferConcat([ct, guard.crypto.cipherAuthTag(cipher)]);
527
533
  });
528
534
  }, "encrypt"));
529
535
  }
@@ -531,7 +537,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
531
537
  var cbcIv = _toBuf(alg.iv, "AES-CBC iv");
532
538
  return _toArrayBuffer(_runCipher(function () {
533
539
  return _withSecretBytes(key, function (kb) {
534
- var c2 = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-cbc", kb, cbcIv);
540
+ var c2 = guard.crypto.cipher("aes-" + key.algorithm.length + "-cbc", kb, cbcIv);
535
541
  return guard.secret.cipherFinish(c2, buf, WebCryptoError, "webcrypto/operation", "an AES-CBC encrypt intermediate");
536
542
  });
537
543
  }, "encrypt"));
@@ -541,7 +547,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
541
547
  var ctrCounter = _toBuf(alg.counter, "AES-CTR counter");
542
548
  return _toArrayBuffer(_runCipher(function () {
543
549
  return _withSecretBytes(key, function (kb) {
544
- var c3 = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter);
550
+ var c3 = guard.crypto.cipher("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter);
545
551
  return guard.secret.cipherFinish(c3, buf, WebCryptoError, "webcrypto/operation", "an AES-CTR encrypt intermediate");
546
552
  });
547
553
  }, "encrypt"));
@@ -557,7 +563,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
557
563
  if (!ENCRYPT_DECRYPT_NAMES[name]) throw new WebCryptoError("webcrypto/not-supported", "decrypt: unsupported algorithm " + _stringify(name));
558
564
  _requireAlgMatch(alg, key, "decrypt");
559
565
  if (name === "RSA-OAEP") {
560
- var oaepOut = nodeCrypto.privateDecrypt({
566
+ var oaepOut = guard.crypto.privateDecrypt({
561
567
  key: key._handle, padding: guard.crypto.padding.RSA_PKCS1_OAEP,
562
568
  oaepHash: _hashNode(key.algorithm.hash, "decrypt"),
563
569
  oaepLabel: alg.label ? _toBuf(alg.label, "decrypt label") : undefined,
@@ -574,9 +580,9 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
574
580
  var gcmAad = alg.additionalData ? _toBuf(alg.additionalData, "AES-GCM aad") : null;
575
581
  return _toArrayBuffer(_runCipher(function () {
576
582
  return _withSecretBytes(key, function (kb) {
577
- var d = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: tagLen });
578
- if (gcmAad) d.setAAD(gcmAad);
579
- 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);
580
586
  return guard.secret.cipherFinish(d, ct, WebCryptoError, "webcrypto/operation", "the recovered AES-GCM plaintext");
581
587
  });
582
588
  }, "decrypt"));
@@ -585,7 +591,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
585
591
  var cbcIv2 = _toBuf(alg.iv, "AES-CBC iv");
586
592
  return _toArrayBuffer(_runCipher(function () {
587
593
  return _withSecretBytes(key, function (kb) {
588
- var d2 = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-cbc", kb, cbcIv2);
594
+ var d2 = guard.crypto.decipher("aes-" + key.algorithm.length + "-cbc", kb, cbcIv2);
589
595
  return guard.secret.cipherFinish(d2, buf, WebCryptoError, "webcrypto/operation", "the recovered AES-CBC plaintext");
590
596
  });
591
597
  }, "decrypt"));
@@ -595,7 +601,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
595
601
  var ctrCounter2 = _toBuf(alg.counter, "AES-CTR counter");
596
602
  return _toArrayBuffer(_runCipher(function () {
597
603
  return _withSecretBytes(key, function (kb) {
598
- var d3 = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter2);
604
+ var d3 = guard.crypto.decipher("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter2);
599
605
  return guard.secret.cipherFinish(d3, buf, WebCryptoError, "webcrypto/operation", "the recovered AES-CTR plaintext");
600
606
  });
601
607
  }, "decrypt"));
@@ -644,10 +650,10 @@ function _pbkdf2Async(pw, salt, iterations, keylen, digest) {
644
650
  if (next) next();
645
651
  if (err) reject(err); else resolve(derived);
646
652
  }
647
- try { nodeCrypto.pbkdf2(pw, salt, iterations, keylen, digest, done); }
653
+ try { guard.crypto.pbkdf2Async(pw, salt, iterations, keylen, digest, done); }
648
654
  catch (e) { done(e); }
649
655
  }
650
- if (_pbkdf2InFlight < _PBKDF2_MAX_CONCURRENT) start(); else _pbkdf2Waiters.push(start);
656
+ if (_pbkdf2InFlight < _PBKDF2_MAX_CONCURRENT) start(); else _push(_pbkdf2Waiters,start);
651
657
  });
652
658
  }
653
659
 
@@ -656,7 +662,7 @@ async function _deriveBitsRaw(alg, key, length) {
656
662
  if (name === "ECDH" || name === "X25519" || name === "X448") {
657
663
  _requireAlgMatch(alg, alg.public, name + " public key");
658
664
  _requireOwnKey(alg.public, "deriveBits public key");
659
- var secret = nodeCrypto.diffieHellman({ privateKey: key._handle, publicKey: alg.public._handle });
665
+ var secret = guard.crypto.diffieHellman({ privateKey: key._handle, publicKey: alg.public._handle });
660
666
  try {
661
667
  if (length == null) return _toArrayBuffer(secret);
662
668
  _requireDeriveLength(length, name);
@@ -671,7 +677,7 @@ async function _deriveBitsRaw(alg, key, length) {
671
677
  if (name === "HKDF") {
672
678
  _requireDeriveLength(length, "HKDF");
673
679
  return _withSecretBytes(key, function (ikm) {
674
- 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);
675
681
  return _types.isArrayBuffer(derived) ? derived : _toArrayBuffer(_bufferFrom(derived));
676
682
  });
677
683
  }
@@ -704,7 +710,7 @@ function _x963Kdf(hashNode, z, sharedInfo, lenBytes) {
704
710
  * hash of the shared secret with this counter in it, so a replaced write makes two blocks derive
705
711
  * from the same input and the key material repeats. */
706
712
  var ctr = _bufferAlloc(4); intrinsic.writeUInt32BE(ctr, counter, 0);
707
- var h = nodeCrypto.createHash(hashNode).update(z).update(ctr).update(sharedInfo).digest();
713
+ var h = guard.crypto.digestParts(hashNode, [z, ctr, sharedInfo]);
708
714
  _push(blocks, h); got += h.length; counter += 1;
709
715
  }
710
716
  var joined = _bufferConcat(blocks);
@@ -752,7 +758,7 @@ SubtleCrypto.prototype.encapsulateBits = async function encapsulateBits(algorith
752
758
  _requireAlgMatch(alg, encapsulationKey, "encapsulateBits");
753
759
  if (encapsulationKey.type !== "public") throw new WebCryptoError("webcrypto/invalid-access", "encapsulateBits requires a public (encapsulation) key, got " + _stringify(encapsulationKey.type));
754
760
  var r;
755
- try { r = nodeCrypto.encapsulate(encapsulationKey._handle); }
761
+ try { r = guard.crypto.encapsulate(encapsulationKey._handle); }
756
762
  catch (e) { throw new WebCryptoError("webcrypto/operation", "encapsulateBits: ML-KEM encapsulation failed", e); }
757
763
  try {
758
764
  return { sharedKey: _toArrayBuffer(r.sharedKey), ciphertext: _toArrayBuffer(r.ciphertext) };
@@ -774,7 +780,7 @@ SubtleCrypto.prototype.decapsulateBits = async function decapsulateBits(algorith
774
780
  "decapsulateBits: " + alg.name + " expects a " + kemRow.ct + "-octet ciphertext, got " + ct.length + " (FIPS 203 sec. 7.3)");
775
781
  }
776
782
  var ss;
777
- try { ss = nodeCrypto.decapsulate(decapsulationKey._handle, ct); }
783
+ try { ss = guard.crypto.decapsulate(decapsulationKey._handle, ct); }
778
784
  catch (e) { throw new WebCryptoError("webcrypto/operation", "decapsulateBits: ML-KEM decapsulation failed (malformed or wrong-length ciphertext)", e); }
779
785
  try {
780
786
  return _toArrayBuffer(ss);
@@ -797,7 +803,7 @@ SubtleCrypto.prototype.wrapKey = async function wrapKey(format, key, wrappingKey
797
803
  }
798
804
  try {
799
805
  return _withSecretBytes(wrappingKey, function (wkBytes) {
800
- 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"));
801
807
  return _toArrayBuffer(guard.secret.cipherFinish(c, bytes, WebCryptoError, "webcrypto/operation", "an AES-KW wrap intermediate"));
802
808
  });
803
809
  } catch (e) { throw new WebCryptoError("webcrypto/operation", "wrapKey: AES-KW key wrap failed", e); }
@@ -822,7 +828,7 @@ SubtleCrypto.prototype.unwrapKey = async function unwrapKey(format, wrappedKey,
822
828
  }
823
829
  try {
824
830
  bytes = _withSecretBytes(unwrappingKey, function (kwBytes) {
825
- 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"));
826
832
  return guard.secret.cipherFinish(d, wrapped, WebCryptoError, "webcrypto/operation", "the unwrapped key material");
827
833
  });
828
834
  } catch (e) { throw new WebCryptoError("webcrypto/operation", "unwrapKey: AES-KW key unwrap failed (integrity or length)", e); }
@@ -1015,8 +1021,13 @@ _forEach([ML_DSA_NODE, ML_KEM_NODE, SLH_DSA_NODE], function (m) {
1015
1021
  });
1016
1022
  function _algFromImport(name, alg, keyObject) {
1017
1023
  var wantType = IMPORT_KEY_TYPE[name];
1018
- if (wantType && keyObject && keyObject.asymmetricKeyType && !wantType[keyObject.asymmetricKeyType]) {
1019
- 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 +
1020
1031
  " key, which is not compatible with algorithm " + name);
1021
1032
  }
1022
1033
  if (name === "ECDSA" || name === "ECDH") {
@@ -1130,17 +1141,17 @@ Crypto.prototype.getRandomValues = function getRandomValues(typedArray) {
1130
1141
  if (out.length > MAX_RANDOM_BYTES) {
1131
1142
  throw new WebCryptoError("webcrypto/data", "getRandomValues: byteLength exceeds " + MAX_RANDOM_BYTES);
1132
1143
  }
1133
- nodeCrypto.randomFillSync(out);
1144
+ guard.crypto.randomFill(out);
1134
1145
  return typedArray;
1135
1146
  };
1136
1147
 
1137
- Crypto.prototype.randomUUID = function randomUUID() { return nodeCrypto.randomUUID(); };
1148
+ Crypto.prototype.randomUUID = function randomUUID() { return guard.crypto.randomUUID(); };
1138
1149
 
1139
1150
  function decompressEcPoint(sec1Compressed, nodeCurve, E, code) {
1140
1151
  var head = sec1Compressed[0];
1141
1152
  if (head !== 0x02 && head !== 0x03) throw E(code, "EC point de-compression expects a compressed SEC1 point (0x02/0x03)");
1142
1153
  try {
1143
- return nodeCrypto.ECDH.convertKey(sec1Compressed, nodeCurve, undefined, undefined, "uncompressed");
1154
+ return guard.crypto.ecConvertPoint(sec1Compressed, nodeCurve, "uncompressed");
1144
1155
  } catch (e) {
1145
1156
  throw E(code, "EC point is not on curve " + nodeCurve + " (de-compression failed)", e);
1146
1157
  }
@@ -1164,9 +1175,19 @@ function isCryptoKeyLike(x) {
1164
1175
  * key this engine did not make while the others returned it. A JWK is an object rather than
1165
1176
  * bytes, so only the byte formats are wrapped. */
1166
1177
  function exportAnyKey(key, E, code, want) {
1167
- 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()];
1168
1189
  if (!format) throw E(code, "a CryptoKey with a private, public, or secret type is required");
1169
- if (want === "jwk" && !_EXPORT_FORMAT[key && key.type]) {
1190
+ if (want === "jwk" && !_EXPORT_FORMAT[typeOnce()]) {
1170
1191
  throw E(code, "a CryptoKey with a private, public, or secret type is required");
1171
1192
  }
1172
1193
  var asJwk = format === "jwk";
@@ -1180,7 +1201,7 @@ function exportAnyKey(key, E, code, want) {
1180
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");
1181
1202
  }
1182
1203
  var handle = key._handle;
1183
- if (handle instanceof nodeCrypto.KeyObject && handle.type === key.type) {
1204
+ if (guard.crypto.isKeyObject(handle) && guard.crypto.keyKind(handle) === key.type) {
1184
1205
  return _resolve(_Promise).then(function () {
1185
1206
  if (asJwk) return guard.crypto.exportKey(handle, { format: "jwk" });
1186
1207
  return format === "raw" ? guard.crypto.exportKey(handle) : guard.crypto.exportKey(handle, { format: "der", type: format });
@@ -1189,7 +1210,7 @@ function exportAnyKey(key, E, code, want) {
1189
1210
  });
1190
1211
  }
1191
1212
  return _resolve(_Promise)
1192
- .then(function () { return nodeCrypto.webcrypto.subtle.exportKey(format, key); })
1213
+ .then(function () { return guard.crypto.nodeExportKey(format, key); })
1193
1214
  .then(wrap, function (e) {
1194
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);
1195
1216
  });
package/lib/x509-sign.js CHANGED
@@ -22,6 +22,11 @@ var x509 = require("./schema-x509");
22
22
  var signScheme = require("./sign-scheme");
23
23
  var guard = require("./guard-all");
24
24
  var intrinsic = require("./guard-intrinsic");
25
+ /** @internal The append every list here is built with. `push` STORES at the index, and a store walks
26
+ * the prototype chain for a setter, so an accessor inherited at an array index receives each element
27
+ * as it is appended and the index reads back whatever its getter answers. These lists become the
28
+ * bytes that get signed. */
29
+ var _push = intrinsic.append;
25
30
  var _isArray = intrinsic.isArray, _bufferEquals = intrinsic.bufferEquals, _isBuffer = intrinsic.isBuffer;
26
31
  var _arrSlice = intrinsic.arraySlice, _promiseResolve = intrinsic.uncurry(intrinsic.promiseResolve);
27
32
  /** @internal The RECEIVER for the captured `Promise.resolve`, captured too. `resolve` builds through
@@ -243,23 +248,23 @@ function _buildExtensions(extSpec, ctx) {
243
248
  if (skiVal === false) {
244
249
  if (caTrue) throw _err("x509/bad-input", "a CA certificate MUST carry a subjectKeyIdentifier, so subjectKeyIdentifier: false is refused when basicConstraints cA is TRUE (RFC 5280 sec. 4.2.1.2)");
245
250
  } else {
246
- out.push(_ext(O("subjectKeyIdentifier"), false, _extSki(_skiKeyId(skiVal, ctx.spki))));
251
+ _push(out,_ext(O("subjectKeyIdentifier"), false, _extSki(_skiKeyId(skiVal, ctx.spki))));
247
252
  }
248
253
  var akiVal = extSpec.authorityKeyIdentifier == null ? !ctx.selfSigned : extSpec.authorityKeyIdentifier;
249
254
  if (akiVal === false) {
250
255
  if (!ctx.selfSigned) throw _err("x509/bad-input", "the authorityKeyIdentifier keyIdentifier MUST be included in every certificate a CA generates other than a self-signed one, so authorityKeyIdentifier: false is refused here (RFC 5280 sec. 4.2.1.1)");
251
256
  } else {
252
257
  var akiF = _akiFields(akiVal, ctx);
253
- out.push(_ext(O("authorityKeyIdentifier"), false, _extAki(akiF[0], akiF[1], akiF[2])));
258
+ _push(out,_ext(O("authorityKeyIdentifier"), false, _extAki(akiF[0], akiF[1], akiF[2])));
254
259
  }
255
- if (ku != null) out.push(_ext(O("keyUsage"), extSpec.keyUsageCritical !== false, _extKeyUsage(ku)));
256
- if (extSpec.extendedKeyUsage != null) out.push(_ext(O("extKeyUsage"), !!extSpec.extendedKeyUsageCritical, _extExtKeyUsage(extSpec.extendedKeyUsage)));
260
+ if (ku != null) _push(out,_ext(O("keyUsage"), extSpec.keyUsageCritical !== false, _extKeyUsage(ku)));
261
+ if (extSpec.extendedKeyUsage != null) _push(out,_ext(O("extKeyUsage"), !!extSpec.extendedKeyUsageCritical, _extExtKeyUsage(extSpec.extendedKeyUsage)));
257
262
  if (bc != null) {
258
263
  if (bc.cA === true && bc.critical === false) throw _err("x509/bad-input", "a CA certificate's basicConstraints MUST be critical (RFC 5280 sec. 4.2.1.9)");
259
- out.push(_ext(O("basicConstraints"), bc.critical !== false, _extBasicConstraints(bc)));
264
+ _push(out,_ext(O("basicConstraints"), bc.critical !== false, _extBasicConstraints(bc)));
260
265
  }
261
- if (extSpec.subjectAltName != null) out.push(_ext(O("subjectAltName"), ctx.subjectEmpty, _extSan(extSpec.subjectAltName)));
262
- if (extSpec.certificatePolicies != null) out.push(_ext(O("certificatePolicies"), !!extSpec.certificatePoliciesCritical, _extCertPolicies(extSpec.certificatePolicies)));
266
+ if (extSpec.subjectAltName != null) _push(out,_ext(O("subjectAltName"), ctx.subjectEmpty, _extSan(extSpec.subjectAltName)));
267
+ if (extSpec.certificatePolicies != null) _push(out,_ext(O("certificatePolicies"), !!extSpec.certificatePoliciesCritical, _extCertPolicies(extSpec.certificatePolicies)));
263
268
  /** @internal Sections 4.2.2.1 and 4.2.1.15 fix these non-critical; sec. 4.2.1.13 states a SHOULD
264
269
  * and the toolkit issues the conforming form. */
265
270
  if (extSpec.authorityInfoAccess != null) guard.list.append(out, _ext(O("authorityInfoAccess"), false, _extAia(extSpec.authorityInfoAccess)));
@@ -788,14 +793,14 @@ function _sign(spec, issuer, opts) {
788
793
  * signature covers (draft-truskovsky-lamps-pq-hybrid-x509 sec. 4). */
789
794
  function tbsOver(extList, omitSignatureAlg) {
790
795
  var tbsChildren = [];
791
- if (version !== 1) tbsChildren.push(b.explicit(0, b.integer(BigInt(version - 1))));
792
- tbsChildren.push(serialTlv);
793
- if (omitSignatureAlg !== true) tbsChildren.push(scheme.sigAlgId);
794
- tbsChildren.push(issuerDer);
795
- tbsChildren.push(validityDer);
796
- tbsChildren.push(subjectDer);
797
- tbsChildren.push(b.raw(spki));
798
- if (extList.length) tbsChildren.push(b.explicit(3, b.sequence(extList)));
796
+ if (version !== 1) _push(tbsChildren,b.explicit(0, b.integer(BigInt(version - 1))));
797
+ _push(tbsChildren,serialTlv);
798
+ if (omitSignatureAlg !== true) _push(tbsChildren,scheme.sigAlgId);
799
+ _push(tbsChildren,issuerDer);
800
+ _push(tbsChildren,validityDer);
801
+ _push(tbsChildren,subjectDer);
802
+ _push(tbsChildren,b.raw(spki));
803
+ if (extList.length) _push(tbsChildren,b.explicit(3, b.sequence(extList)));
799
804
  return b.sequence(tbsChildren);
800
805
  }
801
806
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.8.59",
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:2b5749b0-053a-41de-947c-63a7a8df8028",
5
+ "serialNumber": "urn:uuid:dc638a09-3eb3-4620-b84b-f3edd3453ec6",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-10-07T05:12:27.182Z",
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.59",
22
+ "bom-ref": "@blamejs/pki@0.8.61",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.8.59",
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.59",
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.59",
57
+ "ref": "@blamejs/pki@0.8.61",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]