@blamejs/pki 0.8.0 → 0.8.2

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.
@@ -280,10 +280,10 @@ function pbkdf2Params(ns) {
280
280
  var keyLength = guard.range.positiveInt31(m.fields.keyLength.value, ctx.E, ctx.prefix + "/bad-mac-data", "PBKDF2 keyLength");
281
281
  var prf = m.fields.prf.present ? m.fields.prf.value.result : null;
282
282
  var pp = prf ? prf.parameters : null;
283
- if (prf && prf.oid === hmacSha1 && pp !== null && pp.length === 2 && pp[0] === 0x05 && pp[1] === 0x00) {
283
+ if (prf && prf.oid === hmacSha1 && pp !== null && guard.der.isNull(pp)) {
284
284
  throw ctx.E(ctx.prefix + "/bad-mac-data", "a PBKDF2 prf equal to its DEFAULT algid-hmacWithSHA1 must be omitted (X.690 sec. 11.5, RFC 8018 sec. 5.2)");
285
285
  }
286
- if (prf && pp !== null && !(pp.length === 2 && pp[0] === 0x05 && pp[1] === 0x00)) {
286
+ if (prf && pp !== null && !guard.der.isNull(pp)) {
287
287
  throw ctx.E(ctx.prefix + "/bad-mac-data", "the PBKDF2 prf parameters must be absent or NULL (RFC 8018 App. B.1)");
288
288
  }
289
289
  return {
@@ -313,7 +313,7 @@ function pbmac1Params(ns) {
313
313
  }
314
314
  var scheme = m.fields.messageAuthScheme.value.result;
315
315
  var sp = scheme.parameters;
316
- if (sp !== null && !(sp.length === 2 && sp[0] === 0x05 && sp[1] === 0x00)) {
316
+ if (sp !== null && !guard.der.isNull(sp)) {
317
317
  throw ctx.E(ctx.prefix + "/bad-mac-data", "the PBMAC1 messageAuthScheme parameters must be absent or NULL (RFC 8018 App. B.1)");
318
318
  }
319
319
  return {
@@ -403,7 +403,8 @@ function name(ns, opts) {
403
403
  _forEach(rdnItem.value.items, function (atvItem) {
404
404
  var a = atvItem.value.result;
405
405
  _push(atvs, a);
406
- var label = (a.name && _hasOwn(DN_SHORT, a.name) && DN_SHORT[a.name]) || a.name || a.type;
406
+ var label = (a.name && _hasOwn(DN_SHORT, a.name) && DN_SHORT[a.name]) ||
407
+ (guard.name.isAttributeDescriptor(a.name) ? a.name : a.type);
407
408
  _push(atvParts, label + "=" + _dnDisplayValue(a.value));
408
409
  });
409
410
  _push(rdns, atvs);
package/lib/x509-sign.js CHANGED
@@ -23,6 +23,9 @@ var signScheme = require("./sign-scheme");
23
23
  var guard = require("./guard-all");
24
24
  var intrinsic = require("./guard-intrinsic");
25
25
  var _isArray = intrinsic.isArray, _bufferEquals = intrinsic.bufferEquals;
26
+ var _dnCharCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
27
+ var _dnKeys = intrinsic.keys;
28
+ var _dnHasOwn = intrinsic.hasOwn;
26
29
  var frameworkError = require("./framework-error");
27
30
  var schema = require("./schema-engine");
28
31
  var pkix = require("./schema-pkix");
@@ -788,4 +791,100 @@ function _extension(name, value, opts) {
788
791
  return _ext(row.oid, critical, valueDer);
789
792
  }
790
793
 
791
- module.exports = { sign: sign, randomSerial: randomSerial, extension: extension };
794
+ /**
795
+ * @primitive pki.x509.parseDn
796
+ * @signature pki.x509.parseDn(dn) -> { rdns, dn, bytes }
797
+ * @since 0.8.2
798
+ * @status stable
799
+ * @spec RFC 4514
800
+ * @related pki.x509.sign, pki.schema.x509.parse
801
+ *
802
+ * Read a distinguished-name string into the `Name` a builder takes, using the attribute names
803
+ * and value escaping of RFC 4514 sec. 2.4 and sec. 3. It is the inverse of the `dn` string
804
+ * every parsed name carries: `bytes` is the encoded `Name`, ready to hand to `pki.x509.sign`
805
+ * as a `subject` or `issuer`, and `dn` is the string re-emitted from what was read, which for
806
+ * a string this toolkit produced is the string it was given.
807
+ *
808
+ * Components are read in the order they are written, so the first one written is the first
809
+ * element of the encoded `Name`. That is the order every `dn` here is emitted in, and the
810
+ * order `openssl x509 -subject` prints. RFC 4514 sec. 2.1 specifies the opposite order, so a
811
+ * string from a directory tool that follows it names the components from last to first;
812
+ * reverse them before parsing one.
813
+ *
814
+ * The string form does not carry the ASN.1 string type of each value, so a parsed value takes
815
+ * the type this toolkit encodes that attribute with: `PrintableString` for `countryName`,
816
+ * `IA5String` for `emailAddress`, `UTF8String` otherwise. A name written by something that
817
+ * chose different types will re-encode to different bytes, which is why RFC 4514 sec. 2.4
818
+ * defines the `#`-prefixed hex form: a value given that way is the exact DER of the
819
+ * `AttributeValue` and round-trips byte for byte.
820
+ *
821
+ * Malformed input throws `x509/bad-dn`. A non-string throws `x509/bad-input`.
822
+ *
823
+ * `bytes` is raw `Name` DER, the form `spec.subject` and `spec.issuer` take alongside a string
824
+ * or an array of RDNs, so a name read from a string can be signed without rebuilding it.
825
+ *
826
+ * @example
827
+ * var name = pki.x509.parseDn("C=US, O=Example Inc, CN=leaf");
828
+ * name.rdns.length; // -> 3
829
+ * name.rdns[0][0].name; // -> "countryName"
830
+ * name.dn; // -> "C=US, O=Example Inc, CN=leaf"
831
+ * Buffer.isBuffer(name.bytes); // -> true
832
+ */
833
+ function parseDn(dn) {
834
+ if (typeof dn !== "string") throw _err("x509/bad-input", "pki.x509.parseDn takes a distinguished-name string");
835
+ var components = guard.name.parseDnString(dn, _err, "x509/bad-dn", "the distinguished name");
836
+ var spec = [];
837
+ for (var i = 0; i < components.length; i++) {
838
+ var rdn = components[i], out = intrinsic.create(null);
839
+ for (var j = 0; j < rdn.length; j++) {
840
+ var atv = rdn[j];
841
+ var attrName;
842
+ try { attrName = _dnAttrName(atv.type); }
843
+ catch (e) {
844
+ if (e instanceof CertificateError && e.code === "x509/bad-dn") throw e;
845
+ throw _err("x509/bad-dn", "the distinguished name has an attribute type that does not resolve: " + guard.text.showValue(atv.type), e);
846
+ }
847
+ if (_dnHasOwn(out, attrName)) {
848
+ throw _err("x509/bad-dn", "the distinguished name repeats " + attrName + " inside one relative distinguished name");
849
+ }
850
+ out[attrName] = atv.hex === null ? _dnLiteralValue(atv.value) : "#" + atv.hex;
851
+ }
852
+ guard.list.append(spec, out);
853
+ }
854
+ var bytes, read;
855
+ try {
856
+ bytes = _b.encodeName(spec);
857
+ read = schema.walk(NAME_SCHEMA, asn1.decode(bytes), NS).result;
858
+ } catch (e) {
859
+ throw _err("x509/bad-dn", "the distinguished name does not encode: " + (e && e.message), e);
860
+ }
861
+ return { rdns: read.rdns, dn: read.dn, bytes: bytes };
862
+ }
863
+
864
+ function _dnAttrName(type) {
865
+ if (oid.isDottedDecimal(type)) {
866
+ var byOid = oid.name(type);
867
+ if (!byOid) throw _err("x509/bad-dn", "the distinguished name names an unregistered attribute OID " + type);
868
+ return byOid;
869
+ }
870
+ var wanted = guard.name.lowerAscii(type);
871
+ var shortNames = pkix.DN_SHORT;
872
+ var keys = _dnKeys(shortNames);
873
+ for (var i = 0; i < keys.length; i++) {
874
+ if (guard.name.lowerAscii(shortNames[keys[i]]) === wanted || guard.name.lowerAscii(keys[i]) === wanted) return keys[i];
875
+ }
876
+ var table = oid.all();
877
+ var dotted = _dnKeys(table);
878
+ for (var j = 0; j < dotted.length; j++) {
879
+ var registered = table[dotted[j]];
880
+ if (guard.name.lowerAscii(registered) === wanted) return registered;
881
+ }
882
+ throw _err("x509/bad-dn", "the distinguished name names an unknown attribute " + guard.text.showValue(type));
883
+ }
884
+
885
+ function _dnLiteralValue(value) {
886
+ var first = _dnCharCodeAt(value, 0);
887
+ return (first === 0x23 || first === 0x5c) ? "\\" + value : value;
888
+ }
889
+
890
+ module.exports = { sign: sign, randomSerial: randomSerial, extension: extension, parseDn: parseDn };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
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",
@@ -68,7 +68,9 @@
68
68
  "test": "node test/smoke.js",
69
69
  "lint": "eslint --max-warnings 0 .",
70
70
  "fuzz": "npm ci --prefix fuzz && npx --prefix fuzz jazzer fuzz/asn1-der.fuzz.js -- -max_total_time=60",
71
- "gates": "node test/layer-0-primitives/codebase-patterns.test.js && node scripts/validate-source-comment-blocks.js && node scripts/check-api-snapshot.js && node scripts/check-spelling-consistency.js && node scripts/check-engine-floor.js",
71
+ "gates": "node test/layer-0-primitives/codebase-patterns.test.js && node scripts/validate-source-comment-blocks.js && node scripts/check-api-snapshot.js && node scripts/check-spelling-consistency.js && node scripts/check-engine-floor.js && node scripts/check-cve-vectors.js && node scripts/check-rfc-currency.js",
72
+ "check:cve-vectors": "node scripts/check-cve-vectors.js",
73
+ "check:rfc-currency": "node scripts/check-rfc-currency.js",
72
74
  "check:engine-floor": "node scripts/check-engine-floor.js",
73
75
  "check:spelling": "node scripts/check-spelling-consistency.js",
74
76
  "coverage": "c8 --include=lib/** --include=index.js --reporter=text-summary --reporter=lcov node test/smoke.js",
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:3474a203-558f-4bf4-8d04-ca4aec66e1f7",
5
+ "serialNumber": "urn:uuid:b0bab233-a055-413d-8f5b-3ed8a3f7a8c4",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-19T19:43:19.653Z",
8
+ "timestamp": "2026-09-20T02:50:18.934Z",
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.8.0",
22
+ "bom-ref": "@blamejs/pki@0.8.2",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.8.0",
25
+ "version": "0.8.2",
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.8.0",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.8.2",
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.8.0",
57
+ "ref": "@blamejs/pki@0.8.2",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]