@blamejs/pki 0.7.12 → 0.7.13

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/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `@blamejs/pki` are documented here. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this
5
5
  project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## v0.7.13 — 2026-09-10
8
+
9
+ The certificate signer refuses a pre-encoded extension whose criticality RFC 5280 fixes.
10
+
11
+ ### Changed
12
+
13
+ - A call that supplied one of the nine fixed-criticality extensions with the wrong flag now throws where it previously produced a certificate or a request. Set the flag the clause requires: omit the critical BOOLEAN for the non-critical set, and encode it TRUE for the critical set. The extensions and extensionRequest object forms already emitted the correct flag and are unaffected, as are the CRL and attribute-certificate signers, which enforce the criticality their own profiles fix.
14
+
15
+ ### Fixed
16
+
17
+ - pki.x509.sign and pki.csr.sign now refuse a pre-encoded extension carrying a criticality RFC 5280 does not permit, throwing x509/bad-input or csr/bad-input with the governing clause in the message. Nine extensions leave the issuer no choice. authorityKeyIdentifier (section 4.2.1.1), subjectKeyIdentifier (section 4.2.1.2), subjectDirectoryAttributes (section 4.2.1.8), freshestCRL (section 4.2.1.15), authorityInfoAccess (section 4.2.2.1) and subjectInfoAccess (section 4.2.2.2) must be non-critical. nameConstraints (section 4.2.1.10), policyConstraints (section 4.2.1.11) and inhibitAnyPolicy (section 4.2.1.14) must be critical. The check covers the pre-encoded array form on both verbs, which is the only way to supply these six extensions.
18
+
7
19
  ## v0.7.12 — 2026-09-10
8
20
 
9
21
  An issuer can draw a certificate serial number before signing with it.
package/lib/pki-build.js CHANGED
@@ -273,6 +273,17 @@ function reqDenseArrayImpl(list, what, E, code) {
273
273
  return out;
274
274
  }
275
275
 
276
+ /** @internal RFC 5280 sec. 4.2 fixes the criticality of these certificate extensions. Each entry maps
277
+ * the extension OID to the flag the RFC requires and the clause that sets it. */
278
+ var CERT_FIXED_CRITICALITY = intrinsic.create(null);
279
+ [["authorityKeyIdentifier", false, "RFC 5280 sec. 4.2.1.1"], ["subjectKeyIdentifier", false, "RFC 5280 sec. 4.2.1.2"],
280
+ ["subjectDirectoryAttributes", false, "RFC 5280 sec. 4.2.1.8"], ["nameConstraints", true, "RFC 5280 sec. 4.2.1.10"],
281
+ ["policyConstraints", true, "RFC 5280 sec. 4.2.1.11"], ["inhibitAnyPolicy", true, "RFC 5280 sec. 4.2.1.14"],
282
+ ["freshestCRL", false, "RFC 5280 sec. 4.2.1.15"], ["authorityInfoAccess", false, "RFC 5280 sec. 4.2.2.1"],
283
+ ["subjectInfoAccess", false, "RFC 5280 sec. 4.2.2.2"]].forEach(function (r) {
284
+ CERT_FIXED_CRITICALITY[oid.byName(r[0])] = { critical: r[1], citation: r[2] };
285
+ });
286
+
276
287
  function makeBuilder(ctx) {
277
288
  var ErrorClass = ctx.ErrorClass, O = ctx.O, NS = ctx.NS;
278
289
  var NAME_SCHEMA = ctx.NAME_SCHEMA, SPKI_SCHEMA = ctx.SPKI_SCHEMA;
@@ -498,6 +509,15 @@ function makeBuilder(ctx) {
498
509
  var last = n.children[n.children.length - 1];
499
510
  if (last.tagNumber !== asn1.TAGS.OCTET_STRING || last.tagClass !== "universal") throw E("bad-input", "pre-encoded extension [" + idx + "] extnValue must be an OCTET STRING");
500
511
  }
512
+ /** @internal Applies the certificate profile's fixed-criticality table. The CRL, CRL-entry and
513
+ * attribute-certificate profiles set their own criticality in their own signers. */
514
+ function assertCertCriticality(extnId, isCritical, label) {
515
+ if (!intrinsic.hasOwn(CERT_FIXED_CRITICALITY, extnId)) return;
516
+ var req = CERT_FIXED_CRITICALITY[extnId];
517
+ if (isCritical === req.critical) return;
518
+ throw E("bad-input", label + " " + (oid.name(extnId) || extnId) + " extension must be marked " +
519
+ (req.critical ? "critical" : "non-critical") + " (" + req.citation + ")");
520
+ }
501
521
  var BC_KEYS = { cA: 1, pathLen: 1, critical: 1 };
502
522
  var REQ_EXT_KEYS = {
503
523
  subjectAltName: 1, keyUsage: 1, keyUsageCritical: 1, extendedKeyUsage: 1, extendedKeyUsageCritical: 1,
@@ -515,6 +535,7 @@ function makeBuilder(ctx) {
515
535
  var extnId = asn1.read.oid(n.children[0]);
516
536
  if (seen[extnId]) throw E("bad-input", "duplicate requested extension " + extnId + " (RFC 5280 sec. 4.2)");
517
537
  seen[extnId] = true;
538
+ assertCertCriticality(extnId, n.children.length === 3, "requested");
518
539
  var dec = EXT_DECODERS && EXT_DECODERS[extnId];
519
540
  if (dec) {
520
541
  try { dec(asn1.read.octetString(n.children[n.children.length - 1])); }
@@ -607,6 +628,7 @@ function makeBuilder(ctx) {
607
628
  extSan: extSan, extCertPolicies: extCertPolicies, ext: ext,
608
629
  spkiKeyId: spkiKeyId, skiKeyId: skiKeyId,
609
630
  reqDer: reqDer, reqDenseArray: reqDenseArray, reqDerSequence: reqDerSequence, assertValidSpki: assertValidSpki, assertValidExtension: assertValidExtension,
631
+ assertCertCriticality: assertCertCriticality,
610
632
  certLikeFromSpki: certLikeFromSpki, assertSignatureVerifies: assertSignatureVerifies,
611
633
  samePublicKey: samePublicKey,
612
634
  };
package/lib/x509-sign.js CHANGED
@@ -56,6 +56,7 @@ var KNOWN_EXT_KEYS = intrinsic.assign(intrinsic.create(null), {
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,
58
58
  _assertValidSpki = _b.assertValidSpki, _assertValidExtension = _b.assertValidExtension,
59
+ _assertCertCriticality = _b.assertCertCriticality,
59
60
  _certLikeFromSpki = _b.certLikeFromSpki, _assertCertVerifies = _b.assertSignatureVerifies,
60
61
  _ext = _b.ext, _extBasicConstraints = _b.extBasicConstraints, _validateBcSpec = _b.validateBcSpec,
61
62
  _extKeyUsage = _b.extKeyUsage, _extExtKeyUsage = _b.extExtKeyUsage, _extSki = _b.extSki,
@@ -89,6 +90,7 @@ function _buildExtensions(extSpec, ctx) {
89
90
  var extnId = asn1.read.oid(n.children[0]);
90
91
  if (seenExt[extnId]) throw _err("x509/bad-input", "duplicate extension " + extnId + " in the extensions array (RFC 5280 sec. 4.2 -- at most one instance of an extension)");
91
92
  seenExt[extnId] = true;
93
+ _assertCertCriticality(extnId, n.children.length === 3, "pre-encoded");
92
94
  var dec = EXT_DECODERS[extnId];
93
95
  if (dec) {
94
96
  var decoded;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.7.12",
3
+ "version": "0.7.13",
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:4cd44552-2dd6-48c5-b89d-d0f03d957e45",
5
+ "serialNumber": "urn:uuid:32a9603e-875f-4326-b00f-f40f8927e720",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-11T00:21:46.779Z",
8
+ "timestamp": "2026-09-11T01:36:27.751Z",
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.7.12",
22
+ "bom-ref": "@blamejs/pki@0.7.13",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.7.12",
25
+ "version": "0.7.13",
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.7.12",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.7.13",
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.7.12",
57
+ "ref": "@blamejs/pki@0.7.13",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]