@blamejs/pki 0.6.39 → 0.6.41

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 (79) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/lib/acme.js +24 -13
  3. package/lib/asn1-der.js +5 -5
  4. package/lib/attrcert-sign.js +16 -16
  5. package/lib/cbor-det.js +2 -2
  6. package/lib/cmc-build.js +16 -16
  7. package/lib/cmc-verify.js +5 -5
  8. package/lib/cmp-build.js +29 -19
  9. package/lib/cmp-session.js +25 -20
  10. package/lib/cmp-verify.js +8 -12
  11. package/lib/cms-decrypt.js +8 -8
  12. package/lib/cms-encrypt.js +22 -22
  13. package/lib/cms-sign.js +17 -17
  14. package/lib/cms-verify.js +13 -13
  15. package/lib/composite-kem.js +1 -1
  16. package/lib/composite-sig.js +4 -4
  17. package/lib/constants.js +13 -9
  18. package/lib/crl-sign.js +25 -25
  19. package/lib/crmf-sign.js +11 -11
  20. package/lib/csr-sign.js +4 -4
  21. package/lib/ct.js +33 -25
  22. package/lib/edwards-point.js +2 -2
  23. package/lib/est.js +74 -43
  24. package/lib/guard-async.js +17 -1
  25. package/lib/guard-bytes.js +3 -3
  26. package/lib/guard-compress.js +5 -5
  27. package/lib/guard-identifier.js +46 -2
  28. package/lib/guard-json.js +1 -1
  29. package/lib/guard-list.js +16 -0
  30. package/lib/guard-name.js +1 -1
  31. package/lib/guard-parsed.js +1 -1
  32. package/lib/guard-time.js +3 -1
  33. package/lib/guard-verdict.js +7 -1
  34. package/lib/hpke.js +10 -10
  35. package/lib/http-digest.js +2 -2
  36. package/lib/http-transport.js +3 -3
  37. package/lib/inspect.js +9 -9
  38. package/lib/ip-utils.js +1 -1
  39. package/lib/jose.js +14 -14
  40. package/lib/key.js +7 -7
  41. package/lib/lint.js +6 -4
  42. package/lib/merkle.js +2 -2
  43. package/lib/mime.js +2 -2
  44. package/lib/ocsp-verify.js +1 -1
  45. package/lib/ocsp.js +5 -5
  46. package/lib/oid.js +3 -3
  47. package/lib/path-validate.js +127 -117
  48. package/lib/pbes2.js +2 -2
  49. package/lib/pkcs12-build.js +26 -24
  50. package/lib/pki-build.js +2 -2
  51. package/lib/scep.js +47 -16
  52. package/lib/schema-all.js +1 -1
  53. package/lib/schema-attrcert.js +4 -3
  54. package/lib/schema-c509.js +23 -23
  55. package/lib/schema-cmc.js +6 -6
  56. package/lib/schema-cmp.js +3 -3
  57. package/lib/schema-cms.js +15 -8
  58. package/lib/schema-crmf.js +1 -1
  59. package/lib/schema-csr.js +1 -1
  60. package/lib/schema-engine.js +2 -1
  61. package/lib/schema-pkcs12.js +1 -1
  62. package/lib/schema-pkix.js +3 -0
  63. package/lib/schema-tsp.js +2 -2
  64. package/lib/shbs.js +2 -2
  65. package/lib/sign-scheme.js +9 -9
  66. package/lib/sigstore.js +24 -14
  67. package/lib/smime.js +16 -16
  68. package/lib/tls-cert-compress.js +6 -6
  69. package/lib/trust.js +9 -9
  70. package/lib/tsp-sign.js +30 -30
  71. package/lib/validator-attcert.js +2 -2
  72. package/lib/validator-cose.js +5 -5
  73. package/lib/validator-sig.js +3 -3
  74. package/lib/validator-tpm.js +5 -4
  75. package/lib/webauthn.js +58 -54
  76. package/lib/webcrypto.js +22 -14
  77. package/lib/x509-sign.js +8 -8
  78. package/package.json +1 -1
  79. package/sbom.cdx.json +6 -6
@@ -9,20 +9,20 @@ var oid = require("./oid");
9
9
  var edwardsPoint = require("./edwards-point");
10
10
  var nodeCrypto = require("crypto");
11
11
 
12
- var EC2_CRV_LEN = { 1: 32, 2: 48, 3: 66 };
13
- var EC2_CRV_OID = { 1: "prime256v1", 2: "secp384r1", 3: "secp521r1" };
14
- var OKP_CRV = { 6: { oid: "Ed25519", len: 32 }, 7: { oid: "Ed448", len: 57 } };
12
+ var EC2_CRV_LEN = Object.assign(Object.create(null), { 1: 32, 2: 48, 3: 66 });
13
+ var EC2_CRV_OID = Object.assign(Object.create(null), { 1: "prime256v1", 2: "secp384r1", 3: "secp521r1" });
14
+ var OKP_CRV = Object.assign(Object.create(null), { 6: { oid: "Ed25519", len: 32 }, 7: { oid: "Ed448", len: 57 } });
15
15
  var RSA_MIN_MODULUS_BITS = 2048;
16
16
  var RSA_MAX_EXPONENT_BYTES = 8;
17
17
  function _modulusBits(n) { return (n.length - 1) * 8 + (32 - Math.clz32(n[0])); }
18
18
 
19
- var ALG_PROFILE = {
19
+ var ALG_PROFILE = Object.assign(Object.create(null), {
20
20
  "-7": { kty: 2, crv: 1 }, "-35": { kty: 2, crv: 2 }, "-36": { kty: 2, crv: 3 },
21
21
  "-9": { kty: 2, crv: 1 }, "-51": { kty: 2, crv: 2 }, "-52": { kty: 2, crv: 3 },
22
22
  "-8": { kty: 1, crv: 6 }, "-19": { kty: 1, crv: 6 }, "-53": { kty: 1, crv: 7 },
23
23
  "-257": { kty: 3 }, "-258": { kty: 3 }, "-259": { kty: 3 },
24
24
  "-37": { kty: 3 }, "-38": { kty: 3 }, "-39": { kty: 3 }, "-65535": { kty: 3 },
25
- };
25
+ });
26
26
 
27
27
  // @enforced-by validator-shape-reinlined
28
28
  // @validator-shape kty\s*===\s*2n
@@ -15,12 +15,12 @@ function rawToEcdsaDer(raw, coordLen) {
15
15
  return asn1.build.sequence([asn1.build.integer(r), asn1.build.integer(s)]);
16
16
  }
17
17
 
18
- var CURVE_FIELD_BYTES = { "P-256": 32, "P-384": 48, "P-521": 66 };
19
- var CURVE_ORDER = {
18
+ var CURVE_FIELD_BYTES = Object.assign(Object.create(null), { "P-256": 32, "P-384": 48, "P-521": 66 });
19
+ var CURVE_ORDER = Object.assign(Object.create(null), {
20
20
  "P-256": BigInt("0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"),
21
21
  "P-384": BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"),
22
22
  "P-521": BigInt("0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"),
23
- };
23
+ });
24
24
 
25
25
  // @enforced-by behavioral -- a DER ECDSA-Sig-Value decode has no rename-proof code shape distinct
26
26
  function ecdsaDerToP1363(der, curve, E, code) {
@@ -8,9 +8,9 @@ var guard = require("./guard-all");
8
8
 
9
9
  var TPM_GENERATED_VALUE = 0xff544347;
10
10
  var TPM_ST_ATTEST_CERTIFY = 0x8017;
11
- var TPM_ALG = { RSA: 0x0001, SHA1: 0x0004, SHA256: 0x000b, SHA384: 0x000c, SHA512: 0x000d, NULL: 0x0010, ECC: 0x0023 };
12
- var TPM_ALG_HASH = {}; TPM_ALG_HASH[TPM_ALG.SHA1] = "sha1"; TPM_ALG_HASH[TPM_ALG.SHA256] = "sha256"; TPM_ALG_HASH[TPM_ALG.SHA384] = "sha384"; TPM_ALG_HASH[TPM_ALG.SHA512] = "sha512";
13
- var TPM_CURVE_TO_COSE = {}; TPM_CURVE_TO_COSE[0x0003] = 1; TPM_CURVE_TO_COSE[0x0004] = 2; TPM_CURVE_TO_COSE[0x0005] = 3;
11
+ var TPM_ALG = Object.assign(Object.create(null), { RSA: 0x0001, SHA1: 0x0004, SHA256: 0x000b, SHA384: 0x000c, SHA512: 0x000d, NULL: 0x0010, ECC: 0x0023 });
12
+ var TPM_ALG_HASH = Object.create(null); TPM_ALG_HASH[TPM_ALG.SHA1] = "sha1"; TPM_ALG_HASH[TPM_ALG.SHA256] = "sha256"; TPM_ALG_HASH[TPM_ALG.SHA384] = "sha384"; TPM_ALG_HASH[TPM_ALG.SHA512] = "sha512";
13
+ var TPM_CURVE_TO_COSE = Object.create(null); TPM_CURVE_TO_COSE[0x0003] = 1; TPM_CURVE_TO_COSE[0x0004] = 2; TPM_CURVE_TO_COSE[0x0005] = 3;
14
14
 
15
15
  function _ucmp(a, b) {
16
16
  function strip(x) { var i = 0; while (i < x.length - 1 && x[i] === 0) i++; return x.subarray(i); }
@@ -32,6 +32,7 @@ var TPMA_OBJECT_RESERVED = 0xfff0f009;
32
32
 
33
33
  // @enforced-by behavioral -- a bit-position table lookup has no rename-proof code shape; the RED
34
34
  function _decodeAttributes(oa) {
35
+ // allow:registry-table-inherits-object-prototype -- the attributes record an operator reads as result.tpm.attributes by field name, whose keys are the fixed TPMA_OBJECT_BITS list rather than anything the attestation supplies
35
36
  var out = {};
36
37
  Object.keys(TPMA_OBJECT_BITS).forEach(function (n) { out[n] = ((oa >>> TPMA_OBJECT_BITS[n]) & 1) === 1; });
37
38
  return out;
@@ -112,7 +113,7 @@ function normalizeObjectAttributePolicy(policy, E, code) {
112
113
  if (policy === undefined) return null;
113
114
  if (!policy || typeof policy !== "object" || Array.isArray(policy)) throw new E(code, "opts.tpmPolicy must be an object");
114
115
  guard.identifier.assertKnownKeys(policy, _TPM_POLICY_KEYS, function (c, m) { return new E(c, m); }, code, "opts.tpmPolicy has an unknown key ");
115
- var want = {};
116
+ var want = Object.create(null);
116
117
  if (policy.profile !== undefined) {
117
118
  var preset = TPM_POLICY_PROFILES[guard.text.keyOf(policy.profile)];
118
119
  if (!preset) throw new E(code, "opts.tpmPolicy.profile " + guard.text.showValue(policy.profile) + " is not a defined profile");
package/lib/webauthn.js CHANGED
@@ -59,7 +59,7 @@ function _ucmp(a, b) {
59
59
  return Buffer.compare(strip(a), strip(b)) === 0;
60
60
  }
61
61
  function _isInteger(node) { return !!node && !node.constructed && node.tagClass === "universal" && node.tagNumber === asn1.TAGS.INTEGER; }
62
- var COSE_ALG_HASH = { "-7": "sha256", "-9": "sha256", "-257": "sha256", "-37": "sha256", "-35": "sha384", "-51": "sha384", "-258": "sha384", "-38": "sha384", "-36": "sha512", "-52": "sha512", "-259": "sha512", "-39": "sha512", "-65535": "sha1" };
62
+ var COSE_ALG_HASH = intrinsic.assign(intrinsic.create(null), { "-7": "sha256", "-9": "sha256", "-257": "sha256", "-37": "sha256", "-35": "sha384", "-51": "sha384", "-258": "sha384", "-38": "sha384", "-36": "sha512", "-52": "sha512", "-259": "sha512", "-39": "sha512", "-65535": "sha1" });
63
63
  function _coseAlgHash(alg, E) {
64
64
  var h = COSE_ALG_HASH[String(alg)];
65
65
  if (!h) throw E("webauthn/unsupported-algorithm", "no hash mapping for COSE algorithm " + alg);
@@ -154,7 +154,7 @@ function parseCoseKey(bytes) {
154
154
  }
155
155
 
156
156
 
157
- var COSE_ALG = {
157
+ var COSE_ALG = intrinsic.assign(intrinsic.create(null), {
158
158
  "-7": { imp: { name: "ECDSA", namedCurve: "P-256" }, verify: { name: "ECDSA", hash: "SHA-256" }, ecdsa: 32 },
159
159
  "-35": { imp: { name: "ECDSA", namedCurve: "P-384" }, verify: { name: "ECDSA", hash: "SHA-384" }, ecdsa: 48 },
160
160
  "-36": { imp: { name: "ECDSA", namedCurve: "P-521" }, verify: { name: "ECDSA", hash: "SHA-512" }, ecdsa: 66 },
@@ -171,7 +171,7 @@ var COSE_ALG = {
171
171
  "-38": { imp: { name: "RSA-PSS", hash: "SHA-384" }, verify: { name: "RSA-PSS", saltLength: 48 }, ecdsa: 0 },
172
172
  "-39": { imp: { name: "RSA-PSS", hash: "SHA-512" }, verify: { name: "RSA-PSS", saltLength: 64 }, ecdsa: 0 },
173
173
  "-65535": { imp: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-1" }, verify: { name: "RSASSA-PKCS1-v1_5" }, ecdsa: 0 },
174
- };
174
+ });
175
175
 
176
176
  function _derEcdsaToRaw(der, curve) { return validator.sig.ecdsaDerToP1363(der, curve, WebauthnError, "webauthn/bad-signature"); }
177
177
 
@@ -186,7 +186,7 @@ function _verifySig(alg, sig, spkiBytes, message, E) {
186
186
  .then(function (key) { return subtle.verify(ver, key, s, message); })
187
187
  .catch(function (e) { throw _err("webauthn/verify-error", "the attestation signature could not be evaluated", e); });
188
188
  }
189
- var ED_OID_NAME = {};
189
+ var ED_OID_NAME = intrinsic.create(null);
190
190
  ED_OID_NAME[oid.byName("Ed25519")] = "Ed25519";
191
191
  ED_OID_NAME[oid.byName("Ed448")] = "Ed448";
192
192
  function _edName(spkiBytes, E) {
@@ -325,7 +325,7 @@ function _attRead(map, key, reader, what) {
325
325
  function _algOf(attStmt) { return Number(_attRead(attStmt, "alg", cbor.read.int, "an integer")); }
326
326
  function _sigOf(attStmt) { return _attRead(attStmt, "sig", cbor.read.byteString, "a byte string"); }
327
327
  function _requireAttShape(attStmt, allowed, required) {
328
- var have = {};
328
+ var have = intrinsic.create(null);
329
329
  cbor.read.map(attStmt).forEach(function (kv) {
330
330
  if (kv[0].majorType !== 3) throw _err("webauthn/bad-att-stmt", "the attestation statement has a non-text-string field key");
331
331
  have[cbor.read.textString(kv[0])] = true;
@@ -333,7 +333,7 @@ function _requireAttShape(attStmt, allowed, required) {
333
333
  Object.keys(have).forEach(function (k) { if (allowed.indexOf(k) === -1) throw _err("webauthn/bad-att-stmt", "the attestation statement carries an unexpected field '" + k + "'"); });
334
334
  required.forEach(function (k) { if (!have[k]) throw _err("webauthn/bad-att-stmt", "the attestation statement is missing the '" + k + "' field"); });
335
335
  }
336
- var ATT_STMT_MAJOR = { compound: 4 };
336
+ var ATT_STMT_MAJOR = intrinsic.assign(intrinsic.create(null), { compound: 4 });
337
337
 
338
338
  var _AAGUID_SIGNED_BY_FMT = Object.assign(Object.create(null), { "fido-u2f": false });
339
339
  function _aaguidIsSigned(fmt) { return _AAGUID_SIGNED_BY_FMT[fmt] !== false; }
@@ -353,7 +353,7 @@ function _cloneParsed(v, depth) {
353
353
  if (Array.isArray(v)) return v.map(function (x) { return _cloneParsed(x, depth + 1); });
354
354
  if (guard.time.isDate(v)) return new Date(guard.time.instantOf(v));
355
355
  if (v && typeof v === "object") {
356
- var out = {};
356
+ var out = intrinsic.create(null);
357
357
  Object.keys(v).forEach(function (k) { out[k] = _cloneParsed(v[k], depth + 1); });
358
358
  return out;
359
359
  }
@@ -395,8 +395,8 @@ function _applyCallerRoots(res, supplied, vopts, onlyPaths) {
395
395
  .map(function (el) { return { tp: el.trustPath, at: el.chainValidatedAt }; })
396
396
  : (res.trustPath && res.trustPath.length ? [{ tp: res.trustPath, at: res.chainValidatedAt }] : []));
397
397
  if (!onlyPaths) {
398
- res.anchoredElements = { total: (res.fmt === "compound" && Array.isArray(res.compound)) ? res.compound.length : 1,
399
- anchored: paths.length };
398
+ res = guard.verdict.of(res, { anchoredElements: { total: (res.fmt === "compound" && Array.isArray(res.compound)) ? res.compound.length : 1,
399
+ anchored: paths.length } });
400
400
  }
401
401
  if (!paths.length) {
402
402
  throw _err("webauthn/anchor-not-applicable",
@@ -410,8 +410,7 @@ function _applyCallerRoots(res, supplied, vopts, onlyPaths) {
410
410
  "attestation trust path (against the roots supplied as opts.rootCertificates)");
411
411
  });
412
412
  }, Promise.resolve()).then(function () {
413
- res.anchoredTo = _anchoredRoutes(res, "rootCertificates");
414
- return res;
413
+ return guard.verdict.of(res, { anchoredTo: _anchoredRoutes(res, "rootCertificates") });
415
414
  });
416
415
  }
417
416
 
@@ -425,7 +424,7 @@ function _safetyNetAnchored(res) {
425
424
 
426
425
  function _anchoredRoutes(res, base) {
427
426
  var routes = base ? base.split("+") : [];
428
- if (_safetyNetAnchored(res) && routes.indexOf("safetyNetRoots") < 0) routes.push("safetyNetRoots");
427
+ if (_safetyNetAnchored(res) && routes.indexOf("safetyNetRoots") < 0) guard.list.append(routes, "safetyNetRoots");
429
428
  return routes.length ? routes.join("+") : null;
430
429
  }
431
430
 
@@ -502,13 +501,13 @@ function _readX5c(attStmt) {
502
501
  try { return x509.parse(der); } catch (e) { throw _err("webauthn/bad-att-stmt", "an x5c certificate is not a well-formed X.509 certificate", e); }
503
502
  });
504
503
  }
505
- var _exts = { find: _findExt, decode: _decodeExt };
504
+ var _exts = intrinsic.assign(intrinsic.create(null), { find: _findExt, decode: _decodeExt });
506
505
  function _requireV3(cert) { validator.attcert.requireV3(cert, WebauthnError, "webauthn/bad-att-cert"); }
507
506
  function _checkPackedCert(cert) { validator.attcert.packedCert(cert, _exts, WebauthnError, "webauthn/bad-att-cert"); }
508
507
  function _checkAikCert(cert) { validator.attcert.aikCert(cert, _exts, WebauthnError, "webauthn/bad-att-cert"); }
509
508
  function _checkAaguidExt(cert, aaguid) { validator.attcert.aaguidExt(cert, aaguid, _exts, WebauthnError, "webauthn/bad-att-cert", "webauthn/aaguid-mismatch"); }
510
509
 
511
- var VERIFIERS = {
510
+ var VERIFIERS = intrinsic.assign(intrinsic.create(null), {
512
511
  packed: function (att, clientDataHash) {
513
512
  var isX5c = !!cbor.read.mapGet(att.attStmt, "x5c");
514
513
  _requireAttShape(att.attStmt, isX5c ? ["alg", "sig", "x5c"] : ["alg", "sig"], isX5c ? ["alg", "sig", "x5c"] : ["alg", "sig"]);
@@ -604,9 +603,8 @@ var VERIFIERS = {
604
603
  _checkAikCert(aik);
605
604
  _checkAaguidExt(aik, att.authData.aaguid);
606
605
  validator.tpm.assertObjectAttributePolicy(pub, tpmPolicy, WebauthnError, "webauthn/tpm-policy", "webauthn/bad-tpm");
607
- var tpmRes = _result("tpm", "AttCA", chain, att);
608
- tpmRes.tpm = { objectAttributes: pub.objectAttributes, attributes: pub.attributes, authPolicy: pub.authPolicy };
609
- return tpmRes;
606
+ return guard.verdict.of(_result("tpm", "AttCA", chain, att),
607
+ { tpm: { objectAttributes: pub.objectAttributes, attributes: pub.attributes, authPolicy: pub.authPolicy } });
610
608
  });
611
609
  },
612
610
 
@@ -680,9 +678,8 @@ var VERIFIERS = {
680
678
  ? new Date(payload.timestampMs) : undefined);
681
679
  return _safetyNetChainTrusted(chain, roots, chainAt);
682
680
  }).then(function () {
683
- var res = _result("android-safetynet", "Basic", chain, att);
684
- res.safetyNet = signals;
685
- if (chainAt !== undefined) res.chainValidatedAt = chainAt;
681
+ var res = guard.verdict.of(_result("android-safetynet", "Basic", chain, att), { safetyNet: signals });
682
+ if (chainAt !== undefined) res = guard.verdict.of(res, { chainValidatedAt: chainAt });
686
683
  return res;
687
684
  });
688
685
  },
@@ -710,14 +707,12 @@ var VERIFIERS = {
710
707
  return elements.reduce(function (p, e) {
711
708
  return p.then(function () {
712
709
  return Promise.resolve().then(function () { return VERIFIERS[e.fmt](e.att, clientDataHash, opts); })
713
- .then(function (r) { out.push(r); }, function (err) {
710
+ .then(function (r) { guard.list.append(out, r); }, function (err) {
714
711
  throw _err("webauthn/compound-element-failed", "compound element " + e.index + " (format '" + e.fmt + "') did not verify", err);
715
712
  });
716
713
  });
717
714
  }, Promise.resolve()).then(function () {
718
- var res = _result("compound", "Compound", [], att);
719
- res.compound = out;
720
- return res;
715
+ return guard.verdict.of(_result("compound", "Compound", [], att), { compound: out });
721
716
  });
722
717
  },
723
718
 
@@ -727,7 +722,7 @@ var VERIFIERS = {
727
722
  }
728
723
  return Promise.resolve(_result("none", "None", [], att));
729
724
  },
730
- };
725
+ });
731
726
 
732
727
  function _isPlainObject(v) { return !!v && typeof v === "object" && !Array.isArray(v); }
733
728
 
@@ -761,7 +756,7 @@ function _safetyNetChainTrusted(chain, roots, time) {
761
756
  }
762
757
 
763
758
  function _result(fmt, attestationType, chain, att) {
764
- return {
759
+ return guard.verdict.of({
765
760
  valid: true, attestationVerified: true, fmt: fmt, attestationType: attestationType,
766
761
  trustPath: (chain || []).slice().reverse(),
767
762
  aaguid: att.authData.aaguid,
@@ -772,7 +767,7 @@ function _result(fmt, attestationType, chain, att) {
772
767
  flags: att.authData.flags,
773
768
  rpIdHash: att.authData.rpIdHash,
774
769
  extensions: att.authData.extensions,
775
- };
770
+ });
776
771
  }
777
772
 
778
773
  function _appleNonce(extValue) {
@@ -969,37 +964,41 @@ function verify(attestationObject, clientDataHash, opts) {
969
964
  } catch (e) { return Promise.reject(e); }
970
965
  return Promise.resolve().then(function () { return verifier(att, clientDataHash, vopts); })
971
966
  .then(function (res) {
972
- res.clientData = clientData;
973
- return res;
967
+ return guard.verdict.of(res, { clientData: clientData });
974
968
  })
975
969
  .then(function (res) {
976
970
  if (vopts.metadata === undefined) {
977
971
  if (vopts.rootCertificates !== undefined) return _applyCallerRoots(res, vopts.rootCertificates, vopts);
978
- res.anchoredTo = _anchoredRoutes(res, null);
979
- var sn = _safetyNetAnchored(res);
972
+ var anchored = guard.verdict.of(res, { anchoredTo: _anchoredRoutes(res, null) });
973
+ var sn = _safetyNetAnchored(anchored);
980
974
  if (sn) {
981
- res.anchoredElements = { total: (res.fmt === "compound" && Array.isArray(res.compound)) ? res.compound.length : 1,
982
- anchored: sn };
975
+ anchored = guard.verdict.of(anchored, { anchoredElements: {
976
+ total: (anchored.fmt === "compound" && Array.isArray(anchored.compound)) ? anchored.compound.length : 1,
977
+ anchored: sn } });
983
978
  }
984
- return res;
979
+ return anchored;
985
980
  }
986
981
  return Promise.resolve().then(function () { return _applyMetadata(res, att, vopts); })
987
- .then(function (out) { out.anchoredTo = _anchoredRoutes(out, "metadata"); return out; }, function (e) {
982
+ .then(function (out) { return guard.verdict.of(out, { anchoredTo: _anchoredRoutes(out, "metadata") }); }, function (e) {
988
983
  if (!e || e.code !== "webauthn/metadata-not-found" || vopts.rootCertificates === undefined) throw e;
989
984
  return Promise.resolve(_applyCallerRoots(res, vopts.rootCertificates, vopts, e.missedPaths))
990
- .then(function (out) {
985
+ .then(function (withRoots) {
986
+ /** @internal The element coverage the metadata attempt measured is the whole
987
+ * statement's, so it travels on the error rather than being recomputed from the
988
+ * fallback's own paths. */
989
+ var out = e.anchoredElements ? guard.verdict.of(withRoots, { anchoredElements: e.anchoredElements }) : withRoots;
991
990
  var applied = e.appliedEntries || [];
992
991
  if (!applied.length) return out;
993
992
  var primary = applied[0];
994
- out.metadata = { aaguid: primary.entry.aaguid, keyIdentifiers: primary.entry.keyIdentifiers || [],
993
+ var withMd = guard.verdict.of(out, { metadata: { aaguid: primary.entry.aaguid,
994
+ keyIdentifiers: primary.entry.keyIdentifiers || [],
995
995
  entry: primary.entry, entries: applied.map(function (a) { return a.entry; }),
996
- anchors: primary.anchors.length };
997
- out.anchoredTo = _anchoredRoutes(out, "metadata+rootCertificates");
998
- return out;
996
+ anchors: primary.anchors.length } });
997
+ return guard.verdict.of(withMd, { anchoredTo: _anchoredRoutes(withMd, "metadata+rootCertificates") });
999
998
  });
1000
999
  });
1001
1000
  })
1002
- .then(function (res) { res.bindingChecked = bindingChecked; return res; });
1001
+ .then(function (res) { return guard.verdict.of(res, { bindingChecked: bindingChecked }); });
1003
1002
  }
1004
1003
 
1005
1004
  function _applyMetadata(res, att, opts) {
@@ -1011,8 +1010,9 @@ function _applyMetadata(res, att, opts) {
1011
1010
  ? res.compound.filter(function (el) { return el.trustPath && el.trustPath.length; })
1012
1011
  .map(function (el) { return { tp: el.trustPath, fmt: el.fmt, at: el.chainValidatedAt }; })
1013
1012
  : (res.trustPath && res.trustPath.length ? [{ tp: res.trustPath, fmt: res.fmt, at: res.chainValidatedAt }] : []);
1014
- res.anchoredElements = { total: (res.fmt === "compound" && Array.isArray(res.compound)) ? res.compound.length : 1,
1015
- anchored: paths.length };
1013
+ res = guard.verdict.of(res, { anchoredElements: {
1014
+ total: (res.fmt === "compound" && Array.isArray(res.compound)) ? res.compound.length : 1,
1015
+ anchored: paths.length } });
1016
1016
  if (!paths.length) {
1017
1017
  throw _err("webauthn/metadata-not-applicable", "opts.metadata was supplied, but this attestation carries no trust path to anchor (format '" + res.fmt + "')");
1018
1018
  }
@@ -1036,7 +1036,7 @@ function _applyMetadata(res, att, opts) {
1036
1036
  }
1037
1037
  var anchors = mds.metadataAnchors(entry, { metadata: md, time: at, certificate: tp[tp.length - 1] });
1038
1038
  if (!anchors.length) throw _err("webauthn/metadata-no-anchor", "the metadata entry for " + identifier + " supplies no attestation root certificate");
1039
- applied.push({ entry: entry, anchors: anchors, identifier: identifier });
1039
+ guard.list.append(applied, { entry: entry, anchors: anchors, identifier: identifier });
1040
1040
  return { anchors: anchors, identifier: identifier };
1041
1041
  }
1042
1042
  var at = opts.time !== undefined ? opts.time : new Date();
@@ -1046,13 +1046,17 @@ function _applyMetadata(res, att, opts) {
1046
1046
  var missedPaths = [];
1047
1047
  for (var gi = 0; gi < paths.length; gi++) {
1048
1048
  try {
1049
- governed.push({ info: paths[gi], g: govern(paths[gi]) });
1049
+ guard.list.append(governed, { info: paths[gi], g: govern(paths[gi]) });
1050
1050
  } catch (ge) {
1051
- if (ge && ge.code === "webauthn/metadata-not-found") { missed = missed || ge; missedPaths.push(paths[gi]); continue; }
1051
+ if (ge && ge.code === "webauthn/metadata-not-found") { missed = missed || ge; guard.list.append(missedPaths, paths[gi]); continue; }
1052
1052
  throw ge;
1053
1053
  }
1054
1054
  }
1055
- if (missed) { missed.missedPaths = missedPaths; missed.appliedEntries = applied; }
1055
+ if (missed) {
1056
+ guard.verdict.set(missed, "missedPaths", missedPaths);
1057
+ guard.verdict.set(missed, "appliedEntries", applied);
1058
+ guard.verdict.set(missed, "anchoredElements", res.anchoredElements);
1059
+ }
1056
1060
  return governed.reduce(function (p, item) {
1057
1061
  return p.then(function () {
1058
1062
  var g = item.g, info = item.info;
@@ -1064,10 +1068,10 @@ function _applyMetadata(res, att, opts) {
1064
1068
  .then(function () {
1065
1069
  if (missed) throw missed;
1066
1070
  var primary = applied[0];
1067
- res.metadata = { aaguid: primary.entry.aaguid, keyIdentifiers: primary.entry.keyIdentifiers || [],
1071
+ return guard.verdict.of(res, { metadata: { aaguid: primary.entry.aaguid,
1072
+ keyIdentifiers: primary.entry.keyIdentifiers || [],
1068
1073
  entry: primary.entry, entries: applied.map(function (a) { return a.entry; }),
1069
- anchors: primary.anchors.length };
1070
- return res;
1074
+ anchors: primary.anchors.length } });
1071
1075
  });
1072
1076
  }
1073
1077
 
@@ -1469,7 +1473,7 @@ var _ASSERT_OPTS = Object.assign(Object.create(null), {
1469
1473
  function _snapshotAssertion(input) {
1470
1474
  if (!_isPlainObject(input)) throw _err("webauthn/bad-input", "pki.webauthn.verifyAssertion takes an options object");
1471
1475
  guard.identifier.assertKnownKeys(input, _ASSERT_OPTS, _err, "webauthn/bad-input", "verifyAssertion input has an unknown key ");
1472
- var out = {}, k;
1476
+ var out = intrinsic.create(null), k;
1473
1477
  for (k in input) { if (_hasOwn(input, k)) out[k] = input[k]; }
1474
1478
  ["authenticatorData", "clientDataJSON", "clientDataHash", "signature", "expectedChallenge"].forEach(function (f) {
1475
1479
  if (_isBufferSource(out[f])) out[f] = guard.bytes.snapshotSource(out[f], WebauthnError, "webauthn/bad-input", f);
@@ -1478,7 +1482,7 @@ function _snapshotAssertion(input) {
1478
1482
  out.credentialPublicKey = guard.bytes.snapshotSource(out.credentialPublicKey, WebauthnError,
1479
1483
  "webauthn/bad-input", "credentialPublicKey");
1480
1484
  } else if (_isPlainObject(out.credentialPublicKey)) {
1481
- var key = {}, kk;
1485
+ var key = intrinsic.create(null), kk;
1482
1486
  for (kk in out.credentialPublicKey) {
1483
1487
  if (!_hasOwn(out.credentialPublicKey, kk)) continue;
1484
1488
  var v;
@@ -1558,7 +1562,7 @@ function verifyAssertion(input) {
1558
1562
  signCountChecked = true;
1559
1563
  }
1560
1564
  }
1561
- return {
1565
+ return guard.verdict.of({
1562
1566
  valid: true,
1563
1567
  signatureVerified: true,
1564
1568
  signCount: authData.signCount,
@@ -1568,7 +1572,7 @@ function verifyAssertion(input) {
1568
1572
  extensions: authData.extensions,
1569
1573
  clientData: clientData,
1570
1574
  bindingChecked: bindingChecked,
1571
- };
1575
+ });
1572
1576
  });
1573
1577
  });
1574
1578
  }
package/lib/webcrypto.js CHANGED
@@ -116,7 +116,7 @@ function _normalizeAlg(algorithm, who) {
116
116
  if (!alg || typeof alg.name !== "string") {
117
117
  throw new WebCryptoError("webcrypto/syntax", (who || "operation") + ": algorithm must be a string or an object with a name");
118
118
  }
119
- var out = {};
119
+ var out = intrinsic.create(null);
120
120
  for (var k in alg) { if (_hasOwn(alg, k)) out[k] = alg[k]; }
121
121
  out.name = _toUpperCase(alg.name);
122
122
  return out;
@@ -125,7 +125,7 @@ function _normalizeAlg(algorithm, who) {
125
125
  var _STD_ALG_NAME = intrinsic.assign(intrinsic.create(null), { "RSASSA-PKCS1-V1_5": "RSASSA-PKCS1-v1_5", "ED25519": "Ed25519", "ED448": "Ed448" });
126
126
  function _stdName(name) { return _STD_ALG_NAME[name] || name; }
127
127
 
128
- var HASH_NODE = {
128
+ var HASH_NODE = intrinsic.assign(intrinsic.create(null), {
129
129
  "SHA-1": "sha1",
130
130
  "SHA-224": "sha224",
131
131
  "SHA-256": "sha256",
@@ -134,12 +134,12 @@ var HASH_NODE = {
134
134
  "SHA3-256": "sha3-256",
135
135
  "SHA3-384": "sha3-384",
136
136
  "SHA3-512": "sha3-512",
137
- };
137
+ });
138
138
 
139
- var XOF_NODE = {
139
+ var XOF_NODE = intrinsic.assign(intrinsic.create(null), {
140
140
  "SHAKE128": { node: "shake128", length: 32 },
141
141
  "SHAKE256": { node: "shake256", length: 64 },
142
- };
142
+ });
143
143
 
144
144
  function _hashNode(h, who) {
145
145
  var name = (typeof h === "string") ? h : (h && h.name);
@@ -148,10 +148,10 @@ function _hashNode(h, who) {
148
148
  return node;
149
149
  }
150
150
 
151
- var HMAC_BLOCK_BITS = {
151
+ var HMAC_BLOCK_BITS = intrinsic.assign(intrinsic.create(null), {
152
152
  "SHA-1": 512, "SHA-256": 512, "SHA-384": 1024, "SHA-512": 1024,
153
153
  "SHA3-256": 1088, "SHA3-384": 832, "SHA3-512": 576,
154
- };
154
+ });
155
155
 
156
156
  function _hmacLengthBits(alg, who) {
157
157
  var name = (typeof alg.hash === "string") ? alg.hash : (alg.hash && alg.hash.name);
@@ -859,7 +859,7 @@ function _nodeKey(fn, who) {
859
859
  }
860
860
  }
861
861
 
862
- var ML_KEM_INNER = {};
862
+ var ML_KEM_INNER = intrinsic.create(null);
863
863
  ["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"].forEach(function (n) {
864
864
  var row = oid.kemParams(n);
865
865
  ML_KEM_INNER[oid.byName(n)] = { ek: row.ek, dk: row.dk };
@@ -891,7 +891,7 @@ function _validateMlKemInner(innerBytes, sizes) {
891
891
  throw new WebCryptoError("webcrypto/data", "an ML-KEM private key must be the seed, expandedKey, or both CHOICE (RFC 9935 sec. 6)");
892
892
  }
893
893
 
894
- var PKCS8_INNER_VALIDATORS = {};
894
+ var PKCS8_INNER_VALIDATORS = intrinsic.create(null);
895
895
  _forEach(_keys(ML_KEM_INNER), function (o) { PKCS8_INNER_VALIDATORS[o] = function (inner) { _validateMlKemInner(inner, ML_KEM_INNER[o]); }; });
896
896
 
897
897
  function _preValidatePkcs8(p8, name) {
@@ -974,14 +974,22 @@ function _importRawPublic(name, alg, raw, extractable, usages) {
974
974
  throw new WebCryptoError("webcrypto/not-supported", "importKey raw: unsupported public-key algorithm " + _stringify(name));
975
975
  }
976
976
 
977
+ /** @internal Each inner set is asked whether it holds the key's own type, so it answers from its own
978
+ * entries alone: a type naming an Object.prototype member would otherwise resolve to a truthy
979
+ * inherited value and pass a key the algorithm does not accept. */
980
+ function _typeSet(names) {
981
+ var t = intrinsic.create(null);
982
+ _forEach(names, function (n) { t[n] = 1; });
983
+ return t;
984
+ }
977
985
  var IMPORT_KEY_TYPE = intrinsic.assign(intrinsic.create(null), {
978
- "RSASSA-PKCS1-V1_5": { rsa: 1 }, "RSA-PSS": { rsa: 1, "rsa-pss": 1 }, "RSA-OAEP": { rsa: 1 },
979
- "ECDSA": { ec: 1 }, "ECDH": { ec: 1 },
980
- "ED25519": { ed25519: 1 }, "ED448": { ed448: 1 },
981
- "X25519": { x25519: 1 }, "X448": { x448: 1 },
986
+ "RSASSA-PKCS1-V1_5": _typeSet(["rsa"]), "RSA-PSS": _typeSet(["rsa", "rsa-pss"]), "RSA-OAEP": _typeSet(["rsa"]),
987
+ "ECDSA": _typeSet(["ec"]), "ECDH": _typeSet(["ec"]),
988
+ "ED25519": _typeSet(["ed25519"]), "ED448": _typeSet(["ed448"]),
989
+ "X25519": _typeSet(["x25519"]), "X448": _typeSet(["x448"]),
982
990
  });
983
991
  [ML_DSA_NODE, ML_KEM_NODE, SLH_DSA_NODE].forEach(function (m) {
984
- _forEach(_keys(m), function (webName) { var t = {}; t[m[webName]] = 1; IMPORT_KEY_TYPE[webName] = t; });
992
+ _forEach(_keys(m), function (webName) { IMPORT_KEY_TYPE[webName] = _typeSet([m[webName]]); });
985
993
  });
986
994
  function _algFromImport(name, alg, keyObject) {
987
995
  var wantType = IMPORT_KEY_TYPE[name];
package/lib/x509-sign.js CHANGED
@@ -40,18 +40,18 @@ function O(n) { return oid.byName(n); }
40
40
 
41
41
  var OID_SKI = O("subjectKeyIdentifier");
42
42
 
43
- var KNOWN_SPEC_KEYS = {
43
+ var KNOWN_SPEC_KEYS = intrinsic.assign(intrinsic.create(null), {
44
44
  subject: 1, subjectPublicKey: 1, notBefore: 1, notAfter: 1, serialNumber: 1, extensions: 1,
45
- };
46
- var KNOWN_ISSUER_CERT_KEYS = { key: 1, cert: 1 };
47
- var KNOWN_ISSUER_EXPLICIT_KEYS = { key: 1, name: 1, publicKey: 1 };
48
- var KNOWN_SIGN_OPTS = { digestAlgorithm: 1, pem: 1, pss: 1 };
45
+ });
46
+ var KNOWN_ISSUER_CERT_KEYS = intrinsic.assign(intrinsic.create(null), { key: 1, cert: 1 });
47
+ var KNOWN_ISSUER_EXPLICIT_KEYS = intrinsic.assign(intrinsic.create(null), { key: 1, name: 1, publicKey: 1 });
48
+ var KNOWN_SIGN_OPTS = intrinsic.assign(intrinsic.create(null), { digestAlgorithm: 1, pem: 1, pss: 1 });
49
49
 
50
- var KNOWN_EXT_KEYS = {
50
+ var KNOWN_EXT_KEYS = intrinsic.assign(intrinsic.create(null), {
51
51
  subjectKeyIdentifier: 1, authorityKeyIdentifier: 1, keyUsage: 1, keyUsageCritical: 1,
52
52
  extendedKeyUsage: 1, extendedKeyUsageCritical: 1, basicConstraints: 1, subjectAltName: 1,
53
53
  certificatePolicies: 1, certificatePoliciesCritical: 1,
54
- };
54
+ });
55
55
 
56
56
  var _b = pkiBuild.makeBuilder({ ErrorClass: CertificateError, prefix: "x509", O: O, NS: NS, NAME_SCHEMA: NAME_SCHEMA, SPKI_SCHEMA: SPKI_SCHEMA, EXT_DECODERS: EXT_DECODERS });
57
57
  var _encodeName = _b.encodeName, _isEmptyName = _b.isEmptyName, _reqDer = _b.reqDer,
@@ -80,7 +80,7 @@ function _akiKeyId(val, ctx) {
80
80
  function _buildExtensions(extSpec, ctx) {
81
81
  if (extSpec == null) return [];
82
82
  if (_isArray(extSpec)) {
83
- var seenExt = {}, arrCa = false, arrKeyCertSign = false, arrPathLen = false;
83
+ var seenExt = intrinsic.create(null), arrCa = false, arrKeyCertSign = false, arrPathLen = false;
84
84
  var oidBc = O("basicConstraints"), oidKu = O("keyUsage");
85
85
  var arr = extSpec.map(function (e, i) {
86
86
  var der = _reqDer(e, "extension");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.6.39",
3
+ "version": "0.6.41",
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:b1c86284-d109-4852-8e85-dc5992b74178",
5
+ "serialNumber": "urn:uuid:c14ed2d9-f3d5-4322-88e1-51afbe3a3fbe",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-05T11:25:26.514Z",
8
+ "timestamp": "2026-09-06T02:19:25.175Z",
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.6.39",
22
+ "bom-ref": "@blamejs/pki@0.6.41",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.6.39",
25
+ "version": "0.6.41",
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.6.39",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.6.41",
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.6.39",
57
+ "ref": "@blamejs/pki@0.6.41",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]