@blamejs/pki 0.3.17 → 0.3.19

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/pki-build.js CHANGED
@@ -15,10 +15,16 @@ var schema = require("./schema-engine");
15
15
  var compositeSig = require("./composite-sig");
16
16
  var guard = require("./guard-all");
17
17
  var oid = require("./oid");
18
+ var ipUtils = require("./ip-utils");
18
19
  var nodeCrypto = require("crypto");
19
20
 
20
21
  var b = asn1.build;
21
22
 
23
+ // A well-formed dotted-decimal OID: a first arc 0-2 followed by one or more non-leading-zero arcs. Used to
24
+ // accept a raw OID string (an unregistered KeyPurposeId / policy OID) where a registered name would go; the
25
+ // encoder (encodeOidContent) remains the authoritative validator of the arc-value bounds.
26
+ var DOTTED_OID_RE = /^[0-2](?:\.(?:0|[1-9]\d*))+$/;
27
+
22
28
  // KeyUsage named-bit positions (RFC 5280 sec. 4.2.1.3); contentCommitment is the RFC 5280 rename of the
23
29
  // X.509 nonRepudiation bit (1).
24
30
  var KU_BIT = {
@@ -112,8 +118,16 @@ function makeBuilder(ctx) {
112
118
  case "dNSName": return b.contextPrimitive(2, ia5Content(v));
113
119
  case "uniformResourceIdentifier": case "uri": return b.contextPrimitive(6, ia5Content(v));
114
120
  case "iPAddress":
115
- if (!Buffer.isBuffer(v) || (v.length !== 4 && v.length !== 16)) throw E("bad-input", "iPAddress must be a 4- or 16-octet Buffer");
116
- return b.contextPrimitive(7, v);
121
+ // Accept a dotted-quad / colon-hex string (packed to its 4/16 network octets) as well as a
122
+ // pre-packed Buffer, so an iPAddress SAN reads like dNSName/URI rather than forcing the caller
123
+ // to pack octets by hand (RFC 5280 sec. 4.2.1.6 -- a GeneralName iPAddress is a bare host address).
124
+ var ipBuf = v;
125
+ if (typeof v === "string") {
126
+ ipBuf = ipUtils.packIpLiteral(v);
127
+ if (ipBuf === null) throw E("bad-input", "iPAddress string is not a valid IPv4 or IPv6 literal: " + JSON.stringify(v));
128
+ }
129
+ if (!Buffer.isBuffer(ipBuf) || (ipBuf.length !== 4 && ipBuf.length !== 16)) throw E("bad-input", "iPAddress must be a 4- or 16-octet Buffer or an IPv4/IPv6 string");
130
+ return b.contextPrimitive(7, ipBuf);
117
131
  case "directoryName": return b.explicit(4, encodeName(v)); // Name is a CHOICE -> the context tag is EXPLICIT
118
132
  default: throw E("bad-input", "unsupported GeneralName form " + JSON.stringify(k) + " (supported: rfc822Name, dNSName, uniformResourceIdentifier, iPAddress, directoryName)");
119
133
  }
@@ -129,13 +143,26 @@ function makeBuilder(ctx) {
129
143
  });
130
144
  return b.namedBitString(positions);
131
145
  }
146
+ // Resolve an OID token to a dotted-decimal OID: a registered name via the registry, OR a raw dotted-OID
147
+ // string accepted directly (an unregistered KeyPurposeId / policy OID -- BIMI, document-signing, vendor
148
+ // purposes -- is a common valid input). A token that is neither fails closed (never silently accept a
149
+ // typo'd name); a dotted string that passes the shape check is still arc-validated by b.oid's encoder.
150
+ function _resolveOid(n, label) {
151
+ var dotted = O(n);
152
+ if (dotted != null) return dotted;
153
+ if (typeof n === "string" && DOTTED_OID_RE.test(n)) {
154
+ // The regex fixes the general shape; b.oid's encoder is the authoritative X.660 arc-bounds check
155
+ // (a first arc 0/1 caps the second at 39; an arc must DER-encode). A failure there is THIS producer's
156
+ // bad-input, not a leaked oid/* code, so every shared-builder consumer keeps its own error contract.
157
+ try { b.oid(n); }
158
+ catch (e) { throw E("bad-input", "invalid " + label + " OID " + JSON.stringify(n) + " (violates the X.660 arc bounds)", e); }
159
+ return n;
160
+ }
161
+ throw E("bad-input", "unknown " + label + " " + JSON.stringify(n) + " (expected a registered name or a dotted-decimal OID)");
162
+ }
132
163
  function extExtKeyUsage(names) {
133
164
  if (!Array.isArray(names) || !names.length) throw E("bad-input", "extendedKeyUsage must list at least one KeyPurposeId");
134
- return b.sequence(names.map(function (n) {
135
- var purposeOid = O(n);
136
- if (purposeOid == null) throw E("bad-input", "unknown extendedKeyUsage purpose " + JSON.stringify(n));
137
- return b.oid(purposeOid);
138
- }));
165
+ return b.sequence(names.map(function (n) { return b.oid(_resolveOid(n, "extendedKeyUsage purpose")); }));
139
166
  }
140
167
  function validateBcSpec(bc) {
141
168
  if (bc.cA != null && typeof bc.cA !== "boolean") throw E("bad-input", "basicConstraints cA must be a boolean");
@@ -173,8 +200,7 @@ function makeBuilder(ctx) {
173
200
  if (!Array.isArray(names) || !names.length) throw E("bad-input", "certificatePolicies must list at least one policy OID");
174
201
  var seen = {};
175
202
  return b.sequence(names.map(function (n) {
176
- var pOid = O(n);
177
- if (pOid == null) throw E("bad-input", "unknown certificate policy " + JSON.stringify(n));
203
+ var pOid = _resolveOid(n, "certificate policy");
178
204
  if (seen[pOid]) throw E("bad-input", "duplicate certificate policy " + JSON.stringify(n) + " (RFC 5280 sec. 4.2.1.4)");
179
205
  seen[pOid] = true;
180
206
  return b.sequence([b.oid(pOid)]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.3.17",
3
+ "version": "0.3.19",
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:d422e0bf-7707-4f70-8e04-0d467ade9599",
5
+ "serialNumber": "urn:uuid:5ea5efe8-4feb-403c-ab5c-154dfdb673c4",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-07-25T04:02:51.828Z",
8
+ "timestamp": "2026-07-26T02:33:15.202Z",
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.3.17",
22
+ "bom-ref": "@blamejs/pki@0.3.19",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.3.17",
25
+ "version": "0.3.19",
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.3.17",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.3.19",
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.3.17",
57
+ "ref": "@blamejs/pki@0.3.19",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]