@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 +12 -0
- package/lib/pki-build.js +22 -0
- package/lib/x509-sign.js +2 -0
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
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
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:
|
|
5
|
+
"serialNumber": "urn:uuid:32a9603e-875f-4326-b00f-f40f8927e720",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-09-
|
|
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.
|
|
22
|
+
"bom-ref": "@blamejs/pki@0.7.13",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "pki",
|
|
25
|
-
"version": "0.7.
|
|
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.
|
|
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.
|
|
57
|
+
"ref": "@blamejs/pki@0.7.13",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|