@blamejs/pki 0.6.51 → 0.6.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/schema-cmp.js CHANGED
@@ -359,7 +359,7 @@ var ENCRYPTED_KEY = schema.choice([
359
359
  if (ct === null || ct.length === 0) {
360
360
  throw ctx.E("cmp/bad-cert-response", "an EncryptedKey envelopedData must carry non-empty attached ciphertext -- its encryptedContent is the certificate/key payload (RFC 9810 sec. 5.2.2)");
361
361
  }
362
- return { envelopedData: env };
362
+ return { envelopedData: env, bytes: asn1.sequenceTlv(n) };
363
363
  }) },
364
364
  ], { code: "cmp/bad-cert-response", what: "EncryptedKey" });
365
365
 
@@ -539,6 +539,44 @@ function keyUsageOf(ns, cert, E, code, label) {
539
539
  return null;
540
540
  }
541
541
 
542
+ /** @internal The extendedKeyUsage purposes a certificate asserts, or null when it carries no such
543
+ * extension. A malformed extension throws through the caller's ErrorClass; it never reads as an
544
+ * empty set. */
545
+ var _EKU_DECODER = new _WeakMapI();
546
+ function extKeyUsageOf(ns, cert, E, code, label) {
547
+ var exts = (cert && cert.extensions) || [];
548
+ var want = ns.oid.byName("extKeyUsage");
549
+ for (var i = 0; i < exts.length; i++) {
550
+ if (exts[i].oid !== want || exts[i].value == null) continue;
551
+ var dec = _weakGet(_EKU_DECODER, ns);
552
+ if (!dec) { dec = certExtensionDecoders(ns).byOid[want]; _weakSet(_EKU_DECODER, ns, dec); }
553
+ try { return dec(exts[i].value); }
554
+ catch (e) { throw E(code, "the " + label + " extendedKeyUsage extension is malformed", e); }
555
+ }
556
+ return null;
557
+ }
558
+
559
+ /**
560
+ * @internal Whether a certificate ASSERTS a key purpose, for a rule that requires the assertion to be
561
+ * present. RFC 5280 sec. 4.2.1.12 constrains a certificate only when the extension is there, so an
562
+ * absent extendedKeyUsage permits every purpose and satisfies `pki.path.validate`'s `requiredEku`. A
563
+ * profile that reads the purpose as an authorization statement (RFC 6960's id-kp-OCSPSigning
564
+ * responder, RFC 9483 sec. 4.1.6's id-kp-cmKGA key generation authority) needs the opposite reading:
565
+ * the certificate must say so. This returns false for an absent, empty, malformed, or
566
+ * differently-purposed extension, and true only when the named purpose is listed.
567
+ *
568
+ * @enforced-by behavioral -- an absent extension answering an authorization question has no
569
+ * rename-proof code shape; each consumer's RED conformance vector drives the shipped verb on a
570
+ * certificate with no extendedKeyUsage and asserts the refusal.
571
+ */
572
+ function assertsPurpose(ns, cert, purposeOid) {
573
+ var purposes;
574
+ try { purposes = extKeyUsageOf(ns, cert, ns.E, ns.prefix + "/bad-extension-value", "certificate"); }
575
+ catch (_e) { return false; }
576
+ if (!purposes) return false;
577
+ return guard.list.contains(purposes, purposeOid);
578
+ }
579
+
542
580
  function issuingDistributionPoint(code) {
543
581
  return schema.seq([
544
582
  schema.trailing([
@@ -676,7 +714,7 @@ function certExtensionDecoders(ns) {
676
714
  for (var z = 0; z < bs.bytes.length; z++) { if (bs.bytes[z] !== 0) { anyBit = true; break; } }
677
715
  if (!anyBit) throw ns.E(C, "KeyUsage must assert at least one bit (RFC 5280 sec. 4.2.1.3)");
678
716
  schema.assertMinimalNamedBits(bs.unusedBits, bs.bytes, function (m) { throw ns.E(C, m); });
679
- // allow:registry-table-inherits-object-prototype -- the decoded KeyUsage record, whose keys are the fixed KU_BITS names the schema declares rather than anything the certificate supplies
717
+ // allow:registry-table-inherits-object-prototype -- the decoded KeyUsage record, whose keys are the fixed KU_BITS names the schema declares; the certificate supplies none of them
680
718
  var out = {};
681
719
  _forEach(KU_BITS, function (nm, bit) {
682
720
  var byte = bit >> 3, mask = 0x80 >> (bit & 7);
@@ -822,7 +860,7 @@ function certExtensionDecoders(ns) {
822
860
  function authorityKeyIdentifier(buf) {
823
861
  var C = ns.prefix + "/bad-extension-value";
824
862
  var kids = seqChildren(buf, C, "AuthorityKeyIdentifier");
825
- // allow:registry-table-inherits-object-prototype -- the decoded AuthorityKeyIdentifier record, read by the three field names the schema declares rather than by anything the certificate supplies
863
+ // allow:registry-table-inherits-object-prototype -- the decoded AuthorityKeyIdentifier record, read by the three field names the schema declares; the certificate supplies none of them
826
864
  var out = { keyIdentifier: null, authorityCertIssuer: null, authorityCertSerialNumber: null };
827
865
  var lastTag = -1;
828
866
  _forEach(kids, function (k) {
@@ -869,7 +907,7 @@ function certExtensionDecoders(ns) {
869
907
  if (dp.tagClass !== "universal" || dp.tagNumber !== _T.SEQUENCE || !dp.children) {
870
908
  throw ns.E(C, "DistributionPoint must be a SEQUENCE { distributionPoint?, reasons?, cRLIssuer? }");
871
909
  }
872
- // allow:registry-table-inherits-object-prototype -- the decoded DistributionPoint record, read by the three field names the schema declares rather than by anything the certificate supplies
910
+ // allow:registry-table-inherits-object-prototype -- the decoded DistributionPoint record, read by the three field names the schema declares; the certificate supplies none of them
873
911
  var out = { distributionPoint: null, reasons: null, cRLIssuer: null };
874
912
  var lastTag = -1;
875
913
  _forEach(dp.children, function (f) {
@@ -1247,6 +1285,8 @@ module.exports = {
1247
1285
  distributionPointName: distributionPointName,
1248
1286
  issuingDistributionPoint: issuingDistributionPoint,
1249
1287
  keyUsageOf: keyUsageOf,
1288
+ extKeyUsageOf: extKeyUsageOf,
1289
+ assertsPurpose: assertsPurpose,
1250
1290
  generalizedTime: generalizedTime,
1251
1291
  utf8Text: utf8Text,
1252
1292
  rawNonEmptySequence: rawNonEmptySequence,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.6.51",
3
+ "version": "0.6.52",
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:d9015ac6-f8a1-409f-9e1f-5ae1fc7491a1",
5
+ "serialNumber": "urn:uuid:5de9cc32-97b6-4f34-a868-7ad628091d11",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-07T06:27:34.397Z",
8
+ "timestamp": "2026-09-07T15:01:14.383Z",
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.51",
22
+ "bom-ref": "@blamejs/pki@0.6.52",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.6.51",
25
+ "version": "0.6.52",
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.51",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.6.52",
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.51",
57
+ "ref": "@blamejs/pki@0.6.52",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]