@blamejs/pki 0.5.9 → 0.5.11

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 (54) hide show
  1. package/CHANGELOG.md +80 -19
  2. package/README.md +1 -1
  3. package/lib/acme.js +5 -5
  4. package/lib/asn1-der.js +1 -1
  5. package/lib/attrcert-sign.js +1 -1
  6. package/lib/cbor-det.js +4 -4
  7. package/lib/cmc-build.js +5 -5
  8. package/lib/cmc-verify.js +14 -11
  9. package/lib/cms-decrypt.js +2 -2
  10. package/lib/cms-sign.js +3 -5
  11. package/lib/cms-verify.js +9 -6
  12. package/lib/constants.js +1 -1
  13. package/lib/crl-sign.js +1 -1
  14. package/lib/crmf-sign.js +1 -1
  15. package/lib/ct.js +8 -5
  16. package/lib/est.js +20 -14
  17. package/lib/guard-all.js +12 -12
  18. package/lib/guard-bytes.js +568 -82
  19. package/lib/guard-compress.js +2 -2
  20. package/lib/guard-der.js +1 -1
  21. package/lib/guard-identifier.js +694 -6
  22. package/lib/guard-limits.js +2 -2
  23. package/lib/guard-parsed.js +10 -6
  24. package/lib/guard-range.js +1 -1
  25. package/lib/guard-secret.js +1 -1
  26. package/lib/guard-text.js +1 -1
  27. package/lib/guard-time.js +65 -4
  28. package/lib/hpke.js +1 -1
  29. package/lib/http-digest.js +1 -1
  30. package/lib/inspect.js +8 -3
  31. package/lib/jose.js +1 -1
  32. package/lib/key.js +48 -6
  33. package/lib/lint.js +15 -8
  34. package/lib/ocsp-verify.js +10 -4
  35. package/lib/ocsp.js +35 -6
  36. package/lib/oid.js +1 -1
  37. package/lib/path-validate.js +99 -22
  38. package/lib/schema-c509.js +5 -5
  39. package/lib/schema-cmp.js +1 -1
  40. package/lib/schema-crl.js +1 -1
  41. package/lib/schema-engine.js +2 -2
  42. package/lib/schema-pkix.js +1 -1
  43. package/lib/sigstore.js +6 -2
  44. package/lib/smime.js +1 -1
  45. package/lib/trust.js +2 -2
  46. package/lib/tsp-sign.js +2 -2
  47. package/lib/validator-attcert.js +3 -3
  48. package/lib/validator-cose.js +3 -3
  49. package/lib/webauthn-mds.js +17 -17
  50. package/lib/webauthn.js +12 -12
  51. package/lib/webcrypto.js +16 -7
  52. package/lib/x509-sign.js +1 -1
  53. package/package.json +4 -2
  54. package/sbom.cdx.json +6 -6
package/lib/webauthn.js CHANGED
@@ -474,8 +474,8 @@ var ATT_STMT_MAJOR = { compound: 4 };
474
474
  var _AAGUID_SIGNED_BY_FMT = Object.assign(Object.create(null), { "fido-u2f": false });
475
475
  function _aaguidIsSigned(fmt) { return _AAGUID_SIGNED_BY_FMT[fmt] !== false; }
476
476
 
477
- // The options pki.webauthn.verify recognises. Null-prototype, so a caller-supplied key cannot
478
- // resolve to an inherited Object member and read as recognised.
477
+ // The options pki.webauthn.verify recognizes. Null-prototype, so a caller-supplied key cannot
478
+ // resolve to an inherited Object member and read as recognized.
479
479
  var _VERIFY_OPTS = Object.assign(Object.create(null), {
480
480
  time: 1, metadata: 1, tpmPolicy: 1, safetyNetRoots: 1, verifySafetyNetJws: 1, requireCtsProfileMatch: 1,
481
481
  expectedRpId: 1, requireUserPresence: 1, requireUserVerification: 1, allowedAlgorithms: 1,
@@ -511,7 +511,7 @@ var _FORMAT_SCOPED_BOOLEAN_OPTS = ["verifySafetyNetJws", "requireCtsProfileMatch
511
511
  // so a caller that recycles the array or overwrites a certificate's bytes in between
512
512
  // would have the attestation anchored against the replacement roots while the verdict
513
513
  // still reports `anchoredTo: "rootCertificates"` (CWE-367 reaching a wrong trust
514
- // decision). Same defence, and the same reason, as the assertion input's snapshot.
514
+ // decision). Same defense, and the same reason, as the assertion input's snapshot.
515
515
  // Shape faults are NOT raised here: the array is validated where it is consumed, so
516
516
  // supplying a malformed pin alongside a metadata catalogue that answers keeps failing
517
517
  // exactly where it did before.
@@ -533,7 +533,7 @@ function _cloneParsed(v, depth) {
533
533
  if (depth > 64) throw _err("webauthn/bad-input", "opts.rootCertificates[] is nested too deeply to be a parsed certificate");
534
534
  if (Buffer.isBuffer(v) || v instanceof Uint8Array) return guard.bytes.snapshot(v, _err, "webauthn/bad-input", "a byte field of opts.rootCertificates[]");
535
535
  if (Array.isArray(v)) return v.map(function (x) { return _cloneParsed(x, depth + 1); });
536
- if (v instanceof Date) return new Date(v.getTime());
536
+ if (guard.time.isDate(v)) return new Date(guard.time.instantOf(v));
537
537
  if (v && typeof v === "object") {
538
538
  var out = {};
539
539
  Object.keys(v).forEach(function (k) { out[k] = _cloneParsed(v[k], depth + 1); });
@@ -645,7 +645,7 @@ function _applyCallerRoots(res, supplied, vopts, onlyPaths) {
645
645
  var at = vopts.time !== undefined ? vopts.time : new Date();
646
646
  // EVERY path, not merely one: a compound's elements are independent claims, and
647
647
  // accepting the whole because one element anchored would let an unanchored element
648
- // ride along on its neighbour's trust.
648
+ // ride along on its neighbor's trust.
649
649
  return paths.reduce(function (p, info) {
650
650
  return p.then(function () {
651
651
  var pathAt = vopts.time !== undefined ? vopts.time : (info.at || at);
@@ -1114,7 +1114,7 @@ var VERIFIERS = {
1114
1114
  });
1115
1115
  });
1116
1116
  }, Promise.resolve()).then(function () {
1117
- // sec. 8.9 lists the supported attestation type as "Any" and authorises returning
1117
+ // sec. 8.9 lists the supported attestation type as "Any" and authorizes returning
1118
1118
  // "implementation-specific values representing any combination of outputs". A distinct type
1119
1119
  // rather than a merge: collapsing to the strongest element would let a wrapper upgrade a
1120
1120
  // caller's attestationType check, and collapsing to the weakest would spuriously fail one.
@@ -1388,7 +1388,7 @@ function verify(attestationObject, clientDataHash, opts) {
1388
1388
  // Every option here either GATES the verdict or supplies the trust material a gate needs, so a
1389
1389
  // misspelled key is not a harmless no-op: `metdata` leaves the metadata gate switched off and the
1390
1390
  // call returns a pass the caller believes was checked against the catalogue. Reject an
1391
- // unrecognised key at the boundary, and validate the one shared option every arm reads, so a bad
1391
+ // unrecognized key at the boundary, and validate the one shared option every arm reads, so a bad
1392
1392
  // instant is a config fault here rather than a trust failure reported from deep inside a chain.
1393
1393
  try {
1394
1394
  if (!_isPlainObject(opts)) throw _err("webauthn/bad-input", "opts must be an object");
@@ -1406,7 +1406,7 @@ function verify(attestationObject, clientDataHash, opts) {
1406
1406
  // The boolean switches are typed HERE rather than in the arm that reads them. Validated only
1407
1407
  // inside the android-safetynet arm, `requireCtsProfileMatch: "true"` reaching any other format
1408
1408
  // is never examined at all -- a truthy string that demands nothing, silently accepted. A
1409
- // recognised key with an unusable value is the same class of caller mistake as an unrecognised
1409
+ // recognized key with an unusable value is the same class of caller mistake as an unrecognized
1410
1410
  // key, and belongs at the same boundary.
1411
1411
  _FORMAT_SCOPED_BOOLEAN_OPTS.forEach(function (k) {
1412
1412
  if (opts[k] !== undefined && typeof opts[k] !== "boolean") throw _err("webauthn/bad-input", "opts." + k + " must be a boolean");
@@ -1597,7 +1597,7 @@ function verify(attestationObject, clientDataHash, opts) {
1597
1597
  function _applyMetadata(res, att, opts) {
1598
1598
  var md = opts.metadata;
1599
1599
  // Provenance, not shape: only a catalogue this toolkit actually verified may decide which roots
1600
- // an authenticator is allowed to chain to. Recognising it by its property names would accept a
1600
+ // an authenticator is allowed to chain to. Recognizing it by its property names would accept a
1601
1601
  // hand-built object, or one restored from a cache an attacker can write -- neither of which has
1602
1602
  // been through the signature and chain checks that give the catalogue its authority.
1603
1603
  if (!mds.isVerifiedResult(md)) {
@@ -1703,7 +1703,7 @@ function _applyMetadata(res, att, opts) {
1703
1703
  mds.assertFresh(md, at, "the metadata supplied as opts.metadata");
1704
1704
  // EVERY path must pass, not merely one of them: for a compound attestation each element is an
1705
1705
  // independent claim, and accepting the whole because one element anchored would let an
1706
- // unanchored -- or revoked -- element ride along on its neighbour's trust.
1706
+ // unanchored -- or revoked -- element ride along on its neighbor's trust.
1707
1707
  // Govern EVERY path BEFORE any is chain-validated, and let the SEVEREST outcome decide
1708
1708
  // rather than the first one reached. A compound's elements are independent claims and
1709
1709
  // its element order is NOT signed, so aborting on the first failure lets that order pick
@@ -1836,7 +1836,7 @@ void constants;
1836
1836
  * (the default; any disqualifying report ever filed), `"latest-by-date"` (only the
1837
1837
  * most recent report counts, so a later remediation clears an earlier revocation),
1838
1838
  * or a function receiving the raw report array and returning true to deny.
1839
- * - `rejectUnknownStatus` -- treat a status this toolkit does not recognise as
1839
+ * - `rejectUnknownStatus` -- treat a status this toolkit does not recognize as
1840
1840
  * disqualifying. Off by default: the specification requires an unknown status be
1841
1841
  * ignored, never failed on.
1842
1842
  *
@@ -2146,7 +2146,7 @@ function parseAuthenticatorData(bytes) {
2146
2146
  return _parseAuthData(_bytesArg(bytes, "authenticatorData"), _err);
2147
2147
  }
2148
2148
 
2149
- // The options pki.webauthn.verifyAssertion recognises, null-prototype for the same
2149
+ // The options pki.webauthn.verifyAssertion recognizes, null-prototype for the same
2150
2150
  // reason _VERIFY_OPTS is.
2151
2151
  var _ASSERT_OPTS = Object.assign(Object.create(null), {
2152
2152
  authenticatorData: 1, clientDataHash: 1, clientDataJSON: 1, signature: 1,
package/lib/webcrypto.js CHANGED
@@ -1275,14 +1275,23 @@ Crypto.prototype.getRandomValues = function getRandomValues(typedArray) {
1275
1275
  if (!ArrayBuffer.isView(typedArray) || typedArray instanceof Float32Array || typedArray instanceof Float64Array || typedArray instanceof DataView) {
1276
1276
  throw new WebCryptoError("webcrypto/data", "getRandomValues: expected an integer TypedArray");
1277
1277
  }
1278
- if (typedArray.byteLength > MAX_RANDOM_BYTES) {
1278
+ // Re-view the (already integer-TypedArray-validated) output buffer through the OUTPUT door --
1279
+ // any TypedArray, not just Uint8Array -- so a detached backing store fails closed here; the
1280
+ // returned Buffer aliases typedArray, so randomFillSync writes through to the caller's array.
1281
+ //
1282
+ // The output door, because the input one refuses shared memory: bytes another thread can rewrite
1283
+ // after they have been checked cannot be checked. That answers a question about input. Here the
1284
+ // caller is asking for random bytes in memory they chose, and a `SharedArrayBuffer`-backed view
1285
+ // is a supported W3C argument that the platform fills; refusing it made a working call an error.
1286
+ var out = guard.bytes.outputView(typedArray, WebCryptoError, "webcrypto/data", "getRandomValues");
1287
+ // The ceiling is measured on that view, and never on `typedArray.byteLength`. `byteLength` is an
1288
+ // accessor on the shared typed-array prototype, so a caller's subclass answers it: one reporting
1289
+ // 0 passed the ceiling while the fill below wrote the array's real length, which is the bound
1290
+ // being bypassed rather than enforced. The view is built from the internal slot.
1291
+ if (out.length > MAX_RANDOM_BYTES) {
1279
1292
  throw new WebCryptoError("webcrypto/data", "getRandomValues: byteLength exceeds " + MAX_RANDOM_BYTES);
1280
1293
  }
1281
- // Re-view the (already integer-TypedArray-validated) output buffer via
1282
- // guard.bytes.source -- any TypedArray, not just Uint8Array -- so a detached
1283
- // backing store fails closed here; the returned Buffer aliases typedArray, so
1284
- // randomFillSync writes through to the caller's array.
1285
- nodeCrypto.randomFillSync(guard.bytes.source(typedArray, WebCryptoError, "webcrypto/data", "getRandomValues"));
1294
+ nodeCrypto.randomFillSync(out);
1286
1295
  return typedArray;
1287
1296
  };
1288
1297
 
@@ -1344,7 +1353,7 @@ function exportAnyKey(key, E, code) {
1344
1353
  // A separately-installed copy of this engine is the same code under a different class identity, so
1345
1354
  // its keys fail the `instanceof` above while carrying the very handle this engine reads -- and no
1346
1355
  // WebCrypto implementation but that copy would accept them. Read the handle directly. The
1347
- // extractable check above stays AHEAD of this: the handle can always be read, so honouring the
1356
+ // extractable check above stays AHEAD of this: the handle can always be read, so honoring the
1348
1357
  // key's own extractable promise is this branch's responsibility, not the crypto library's.
1349
1358
  var handle = key._handle;
1350
1359
  if (handle instanceof nodeCrypto.KeyObject && handle.type === key.type) {
package/lib/x509-sign.js CHANGED
@@ -321,7 +321,7 @@ function _sign(spec, issuer, opts) {
321
321
  guard.time.assertValid(spec.notBefore, _err, "x509/bad-input", "notBefore");
322
322
  guard.time.assertValid(spec.notAfter, _err, "x509/bad-input", "notAfter");
323
323
  // allow:nan-date-comparison-unguarded -- both operands are guard.time.assertValid'd on the two lines above (an Invalid Date throws before this comparison).
324
- if (spec.notBefore.getTime() > spec.notAfter.getTime()) throw _err("x509/bad-input", "notBefore must not be after notAfter (RFC 5280 sec. 4.1.2.5)");
324
+ if (guard.time.instantOf(spec.notBefore) > guard.time.instantOf(spec.notAfter)) throw _err("x509/bad-input", "notBefore must not be after notAfter (RFC 5280 sec. 4.1.2.5)");
325
325
  var validityDer = b.sequence([_timeDer(spec.notBefore, "notBefore"), _timeDer(spec.notAfter, "notAfter")]);
326
326
 
327
327
  var exts = _buildExtensions(spec.extensions, { spki: spki, issuerSpki: issuerSpki, issuerCert: issuerCert, subjectEmpty: subjectEmpty });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
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",
@@ -68,9 +68,11 @@
68
68
  "test": "node test/smoke.js",
69
69
  "lint": "eslint --max-warnings 0 .",
70
70
  "fuzz": "npm ci --prefix fuzz && npx --prefix fuzz jazzer fuzz/asn1-der.fuzz.js -- -max_total_time=60",
71
- "gates": "node test/layer-0-primitives/codebase-patterns.test.js && node scripts/validate-source-comment-blocks.js && node scripts/check-api-snapshot.js",
71
+ "gates": "node test/layer-0-primitives/codebase-patterns.test.js && node scripts/validate-source-comment-blocks.js && node scripts/check-api-snapshot.js && node scripts/check-spelling-consistency.js",
72
+ "check:spelling": "node scripts/check-spelling-consistency.js",
72
73
  "coverage": "c8 --include=lib/** --include=index.js --reporter=text-summary --reporter=lcov node test/smoke.js",
73
74
  "check:prose": "node scripts/check-operator-prose.js",
75
+ "check:prose:all": "node -e \"process.env.PKI_PROSE_CHECKS='all';var r=require('child_process').spawnSync(process.execPath,['scripts/check-operator-prose.js'],{stdio:'inherit'});if(r.error)throw r.error;process.exit(r.signal?1:r.status)\"",
74
76
  "check:swallows": "node scripts/check-swallow-coverage.js",
75
77
  "coverage:gated": "npm run coverage && npm run check:swallows",
76
78
  "coverage:unified": "node scripts/coverage-unified.js",
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:0541b2cd-7339-4ee1-9122-38999da30d35",
5
+ "serialNumber": "urn:uuid:70c8692d-688f-45e6-a4af-49916d0b01c7",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-08-18T06:52:40.138Z",
8
+ "timestamp": "2026-08-19T06:52:36.445Z",
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.5.9",
22
+ "bom-ref": "@blamejs/pki@0.5.11",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.5.9",
25
+ "version": "0.5.11",
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.5.9",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.5.11",
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.5.9",
57
+ "ref": "@blamejs/pki@0.5.11",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]