@blamejs/pki 0.1.20 → 0.1.21
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 +15 -0
- package/lib/oid.js +59 -4
- package/lib/path-validate.js +50 -12
- package/lib/schema-pkix.js +9 -0
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ 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.1.21 — 2026-07-09
|
|
8
|
+
|
|
9
|
+
SLH-DSA signatures verify in certification-path validation, and the post-quantum / EdDSA parameters-absent rule is enforced across every format.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- SLH-DSA signature verification in pki.path.validate — all twelve FIPS 205 parameter sets (id-slh-dsa-sha2-{128,192,256}{s,f} and the SHAKE sets). A certificate or CRL signed with SLH-DSA now verifies by importing the issuer's SLH-DSA public key and checking the one-shot signature over the raw signed region; the same rows serve both the certificate signature check and the CRL revocation checker. ML-DSA and the classical RSA / ECDSA / EdDSA set were already wired.
|
|
14
|
+
- pki.oid.paramsMustBeAbsent(oid) — a predicate that reports whether an AlgorithmIdentifier bearing the given OID must encode its parameters field as absent (the ML-DSA and SLH-DSA families and the RFC 8410 Edwards / Montgomery curves). It is the single source the shared AlgorithmIdentifier decoder consults.
|
|
15
|
+
- The OID registry now names the twelve pre-hash HashSLH-DSA identifiers (id-hash-slh-dsa-*, RFC 9909 §3), so a certificate or CRL that carries a HashSLH-DSA algorithm resolves to a name and is covered by the parameters-absent rule.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- The shared AlgorithmIdentifier decoder now rejects a present parameters field on the algorithms whose parameters MUST be absent — ML-DSA, SLH-DSA, Ed25519, Ed448, X25519, and X448 (RFC 9909 §3, RFC 9814 §4, RFC 9881 §2, RFC 8410 §3) — failing closed with a <format>/bad-algorithm-parameters code. Previously a stray explicit NULL or arbitrary bytes in that field were surfaced raw. The rule is enforced once in the shared decoder, so every format that names an algorithm inherits it; a conforming identifier, which omits the field, is unaffected.
|
|
20
|
+
- Certification-path validation now enforces issuer-key / signature-algorithm consistency for the one-shot families whose public-key OID equals the signature OID — EdDSA, ML-DSA, and SLH-DSA — rejecting a mismatch with a path/algorithm-mismatch reason (RFC 9814 §4). Because the underlying WebCrypto import binds a public key of a different type to the requested algorithm name and verifies with the real key, a certificate or CRL signed by one key type but labelling its signatureAlgorithm as another one-shot type could otherwise validate; the check closes that algorithm-confusion path for both the certificate signature and the CRL revocation checker.
|
|
21
|
+
|
|
7
22
|
## v0.1.20 — 2026-07-09
|
|
8
23
|
|
|
9
24
|
An RFC 6962 Certificate Transparency SCT-list parser joins the toolkit.
|
package/lib/oid.js
CHANGED
|
@@ -217,9 +217,10 @@ var FAMILIES = {
|
|
|
217
217
|
sha256: 1, sha384: 2, sha512: 3, "sha3-256": 8, "sha3-512": 10, shake256: 12 } },
|
|
218
218
|
|
|
219
219
|
// NIST signature algorithms — FIPS 204 ML-DSA + FIPS 205 SLH-DSA share the
|
|
220
|
-
// signature arc 2.16.840.1.101.3.4.3.
|
|
221
|
-
//
|
|
222
|
-
// sets .
|
|
220
|
+
// signature arc 2.16.840.1.101.3.4.3. RFC 9909 §3 assigns the 12 Pure SLH-DSA
|
|
221
|
+
// sets .20-.31 (SHA-2 .20-.25, SHAKE .26-.31) and the 12 pre-hash HashSLH-DSA
|
|
222
|
+
// sets .35-.46, each pairing a parameter set with its message-digest hash. The
|
|
223
|
+
// parameters MUST be absent for every one of them (enforced via paramsMustBeAbsent).
|
|
223
224
|
nistSig: { base: [2, 16, 840, 1, 101, 3, 4, 3], of: {
|
|
224
225
|
"id-ml-dsa-44": 17, "id-ml-dsa-65": 18, "id-ml-dsa-87": 19,
|
|
225
226
|
"id-slh-dsa-sha2-128s": 20, "id-slh-dsa-sha2-128f": 21,
|
|
@@ -227,7 +228,13 @@ var FAMILIES = {
|
|
|
227
228
|
"id-slh-dsa-sha2-256s": 24, "id-slh-dsa-sha2-256f": 25,
|
|
228
229
|
"id-slh-dsa-shake-128s": 26, "id-slh-dsa-shake-128f": 27,
|
|
229
230
|
"id-slh-dsa-shake-192s": 28, "id-slh-dsa-shake-192f": 29,
|
|
230
|
-
"id-slh-dsa-shake-256s": 30, "id-slh-dsa-shake-256f": 31
|
|
231
|
+
"id-slh-dsa-shake-256s": 30, "id-slh-dsa-shake-256f": 31,
|
|
232
|
+
"id-hash-slh-dsa-sha2-128s-with-sha256": 35, "id-hash-slh-dsa-sha2-128f-with-sha256": 36,
|
|
233
|
+
"id-hash-slh-dsa-sha2-192s-with-sha512": 37, "id-hash-slh-dsa-sha2-192f-with-sha512": 38,
|
|
234
|
+
"id-hash-slh-dsa-sha2-256s-with-sha512": 39, "id-hash-slh-dsa-sha2-256f-with-sha512": 40,
|
|
235
|
+
"id-hash-slh-dsa-shake-128s-with-shake128": 41, "id-hash-slh-dsa-shake-128f-with-shake128": 42,
|
|
236
|
+
"id-hash-slh-dsa-shake-192s-with-shake256": 43, "id-hash-slh-dsa-shake-192f-with-shake256": 44,
|
|
237
|
+
"id-hash-slh-dsa-shake-256s-with-shake256": 45, "id-hash-slh-dsa-shake-256f-with-shake256": 46 } },
|
|
231
238
|
|
|
232
239
|
// NIST KEM — FIPS 203 ML-KEM (arc 2.16.840.1.101.3.4.4).
|
|
233
240
|
nistKem: { base: [2, 16, 840, 1, 101, 3, 4, 4], of: {
|
|
@@ -402,10 +409,58 @@ function fromDER(input) {
|
|
|
402
409
|
return asn1.read.oid(node);
|
|
403
410
|
}
|
|
404
411
|
|
|
412
|
+
// Algorithm identifiers whose `parameters` field MUST be absent — no explicit
|
|
413
|
+
// NULL, no bytes. The FIPS 204 ML-DSA and FIPS 205 SLH-DSA signature families
|
|
414
|
+
// and the RFC 8410 Edwards / Montgomery curves each carry this MUST: RFC 9909 §3
|
|
415
|
+
// (SLH-DSA in X.509), RFC 9814 §4 (SLH-DSA in CMS), RFC 9881 §2 (ML-DSA in X.509),
|
|
416
|
+
// RFC 8410 §3 (Ed25519 / Ed448 / X25519 / X448). Built by NAME through the same
|
|
417
|
+
// registry every caller uses, so a typo fails closed at load rather than silently
|
|
418
|
+
// dropping a member. One set drives the single shared AlgorithmIdentifier reject
|
|
419
|
+
// (schema-pkix), so every format consumer inherits the rule with no per-format code.
|
|
420
|
+
var _PARAMS_ABSENT = new Set();
|
|
421
|
+
[
|
|
422
|
+
"id-ml-dsa-44", "id-ml-dsa-65", "id-ml-dsa-87",
|
|
423
|
+
"id-slh-dsa-sha2-128s", "id-slh-dsa-sha2-128f", "id-slh-dsa-sha2-192s",
|
|
424
|
+
"id-slh-dsa-sha2-192f", "id-slh-dsa-sha2-256s", "id-slh-dsa-sha2-256f",
|
|
425
|
+
"id-slh-dsa-shake-128s", "id-slh-dsa-shake-128f", "id-slh-dsa-shake-192s",
|
|
426
|
+
"id-slh-dsa-shake-192f", "id-slh-dsa-shake-256s", "id-slh-dsa-shake-256f",
|
|
427
|
+
// Pre-hash HashSLH-DSA sets (RFC 9909 §3) — parameters MUST be absent too.
|
|
428
|
+
"id-hash-slh-dsa-sha2-128s-with-sha256", "id-hash-slh-dsa-sha2-128f-with-sha256",
|
|
429
|
+
"id-hash-slh-dsa-sha2-192s-with-sha512", "id-hash-slh-dsa-sha2-192f-with-sha512",
|
|
430
|
+
"id-hash-slh-dsa-sha2-256s-with-sha512", "id-hash-slh-dsa-sha2-256f-with-sha512",
|
|
431
|
+
"id-hash-slh-dsa-shake-128s-with-shake128", "id-hash-slh-dsa-shake-128f-with-shake128",
|
|
432
|
+
"id-hash-slh-dsa-shake-192s-with-shake256", "id-hash-slh-dsa-shake-192f-with-shake256",
|
|
433
|
+
"id-hash-slh-dsa-shake-256s-with-shake256", "id-hash-slh-dsa-shake-256f-with-shake256",
|
|
434
|
+
"Ed25519", "Ed448", "X25519", "X448",
|
|
435
|
+
].forEach(function (nm) { _PARAMS_ABSENT.add(byName(nm)); });
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @primitive pki.oid.paramsMustBeAbsent
|
|
439
|
+
* @signature pki.oid.paramsMustBeAbsent(dotted) -> boolean
|
|
440
|
+
* @since 0.1.21
|
|
441
|
+
* @status experimental
|
|
442
|
+
* @spec RFC 9909, RFC 9814, RFC 9881, RFC 8410
|
|
443
|
+
* @related pki.oid.name, pki.oid.byName
|
|
444
|
+
*
|
|
445
|
+
* True when an AlgorithmIdentifier bearing this OID MUST encode its `parameters`
|
|
446
|
+
* field as ABSENT (not an explicit NULL, not any bytes): the FIPS 204 ML-DSA and
|
|
447
|
+
* FIPS 205 SLH-DSA signature families and the RFC 8410 Edwards / Montgomery
|
|
448
|
+
* curves. The shared AlgorithmIdentifier decoder consults this and fails closed
|
|
449
|
+
* on a present-parameters violation, so every format inherits the rule.
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* pki.oid.paramsMustBeAbsent(pki.oid.byName("id-slh-dsa-sha2-128s")); // -> true
|
|
453
|
+
* pki.oid.paramsMustBeAbsent(pki.oid.byName("rsaEncryption")); // -> false
|
|
454
|
+
*/
|
|
455
|
+
function paramsMustBeAbsent(dotted) {
|
|
456
|
+
return _PARAMS_ABSENT.has(dotted);
|
|
457
|
+
}
|
|
458
|
+
|
|
405
459
|
module.exports = {
|
|
406
460
|
name: name,
|
|
407
461
|
byName: byName,
|
|
408
462
|
has: has,
|
|
463
|
+
paramsMustBeAbsent: paramsMustBeAbsent,
|
|
409
464
|
register: register,
|
|
410
465
|
registerFamily: registerFamily,
|
|
411
466
|
all: all,
|
package/lib/path-validate.js
CHANGED
|
@@ -86,9 +86,16 @@ var SIG_ALGS = {};
|
|
|
86
86
|
// NULL must be present — RSASSA-PKCS1-v1_5, RFC 4055 §5) or "absent" (parameters
|
|
87
87
|
// must be omitted — ECDSA/EdDSA/ML-DSA, RFC 5758/8410). A cert deviating from
|
|
88
88
|
// its algorithm's required shape is malformed and rejected before verify.
|
|
89
|
-
|
|
89
|
+
// `sameKeyOid` marks the one-shot families whose PUBLIC-KEY algorithm OID is the
|
|
90
|
+
// SAME as the signature algorithm OID — EdDSA, ML-DSA, SLH-DSA. For these, Node's
|
|
91
|
+
// WebCrypto imports an SPKI of ANOTHER type under the requested name and verifies
|
|
92
|
+
// with the real key (it does NOT reject a mismatched SPKI the way it does for
|
|
93
|
+
// RSA/ECDSA), so the issuer-key <-> signature-algorithm consistency (RFC 9814 §4)
|
|
94
|
+
// must be checked structurally: the SPKI OID must equal the signature OID.
|
|
95
|
+
function _sig(name, verify, imp, params, ecdsa, sameKeyOid) {
|
|
90
96
|
var entry = { verify: verify, imp: imp, params: params };
|
|
91
97
|
if (ecdsa) entry.ecdsa = true;
|
|
98
|
+
if (sameKeyOid) entry.sameKeyOid = true;
|
|
92
99
|
SIG_ALGS[oid.byName(name)] = entry;
|
|
93
100
|
}
|
|
94
101
|
// RSASSA-PKCS1-v1_5 — parameters MUST be NULL.
|
|
@@ -99,13 +106,22 @@ _sig("sha512WithRSAEncryption", { name: "RSASSA-PKCS1-v1_5", hash: "SHA-512" },
|
|
|
99
106
|
_sig("ecdsaWithSHA256", { name: "ECDSA", hash: "SHA-256" }, { name: "ECDSA" }, "absent", true);
|
|
100
107
|
_sig("ecdsaWithSHA384", { name: "ECDSA", hash: "SHA-384" }, { name: "ECDSA" }, "absent", true);
|
|
101
108
|
_sig("ecdsaWithSHA512", { name: "ECDSA", hash: "SHA-512" }, { name: "ECDSA" }, "absent", true);
|
|
102
|
-
// EdDSA (one-shot, no hash parameter) — params absent.
|
|
103
|
-
_sig("Ed25519", { name: "Ed25519" }, { name: "Ed25519" }, "absent");
|
|
104
|
-
_sig("Ed448", { name: "Ed448" }, { name: "Ed448" }, "absent");
|
|
105
|
-
// ML-DSA (FIPS 204) — params absent.
|
|
106
|
-
_sig("id-ml-dsa-44", { name: "ML-DSA-44" }, { name: "ML-DSA-44" }, "absent");
|
|
107
|
-
_sig("id-ml-dsa-65", { name: "ML-DSA-65" }, { name: "ML-DSA-65" }, "absent");
|
|
108
|
-
_sig("id-ml-dsa-87", { name: "ML-DSA-87" }, { name: "ML-DSA-87" }, "absent");
|
|
109
|
+
// EdDSA (one-shot, no hash parameter) — params absent; key OID == sig OID.
|
|
110
|
+
_sig("Ed25519", { name: "Ed25519" }, { name: "Ed25519" }, "absent", false, true);
|
|
111
|
+
_sig("Ed448", { name: "Ed448" }, { name: "Ed448" }, "absent", false, true);
|
|
112
|
+
// ML-DSA (FIPS 204) — params absent; key OID == sig OID.
|
|
113
|
+
_sig("id-ml-dsa-44", { name: "ML-DSA-44" }, { name: "ML-DSA-44" }, "absent", false, true);
|
|
114
|
+
_sig("id-ml-dsa-65", { name: "ML-DSA-65" }, { name: "ML-DSA-65" }, "absent", false, true);
|
|
115
|
+
_sig("id-ml-dsa-87", { name: "ML-DSA-87" }, { name: "ML-DSA-87" }, "absent", false, true);
|
|
116
|
+
// SLH-DSA (FIPS 205) — params absent; key OID == sig OID. The twelve pure sets;
|
|
117
|
+
// the RFC 9909 §3 OID name maps to the WebCrypto set name by id-slh-dsa-<set> ->
|
|
118
|
+
// SLH-DSA-<SET> (the webcrypto SLH_DSA_NODE keys). One-shot verify like ML-DSA.
|
|
119
|
+
["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
120
|
+
"shake-128s", "shake-128f", "shake-192s", "shake-192f", "shake-256s", "shake-256f"
|
|
121
|
+
].forEach(function (set) {
|
|
122
|
+
var wc = "SLH-DSA-" + set.toUpperCase();
|
|
123
|
+
_sig("id-slh-dsa-" + set, { name: wc }, { name: wc }, "absent", false, true);
|
|
124
|
+
});
|
|
109
125
|
|
|
110
126
|
// RSASSA-PSS resolves its hash + salt from the AlgorithmIdentifier parameters.
|
|
111
127
|
var OID_RSA_PSS = oid.byName("rsassaPss");
|
|
@@ -238,6 +254,24 @@ function resolveDescriptor(sigAlg) {
|
|
|
238
254
|
return d;
|
|
239
255
|
}
|
|
240
256
|
|
|
257
|
+
// RFC 9814 §4 issuer-key <-> signature-algorithm consistency (algorithm-confusion
|
|
258
|
+
// defense). For the one-shot families whose public key shares the signature OID
|
|
259
|
+
// (EdDSA, ML-DSA, SLH-DSA), Node's WebCrypto imports an SPKI of a DIFFERENT type
|
|
260
|
+
// under the requested name and verifies with the real key — so an Ed25519-signed
|
|
261
|
+
// certificate labelled SLH-DSA would otherwise validate. Enforce structurally:
|
|
262
|
+
// the issuer SPKI's algorithm OID MUST equal the signature algorithm OID. (For
|
|
263
|
+
// RSA/ECDSA — different key vs signature OIDs — WebCrypto's import already rejects
|
|
264
|
+
// a mismatched key type, so `sameKeyOid` is not set and this is a no-op.)
|
|
265
|
+
function assertKeyMatchesSigAlg(spkiBytes, sigOid, d) {
|
|
266
|
+
if (!d || !d.sameKeyOid) return;
|
|
267
|
+
var keyOid;
|
|
268
|
+
try { keyOid = asn1.read.oid(asn1.decode(spkiBytes).children[0].children[0]); }
|
|
269
|
+
catch (e) { throw E("path/algorithm-mismatch", "cannot read the issuer public-key algorithm identifier", e); }
|
|
270
|
+
if (keyOid !== sigOid) {
|
|
271
|
+
throw E("path/algorithm-mismatch", "issuer public-key algorithm " + keyOid + " does not match the signature algorithm " + sigOid + " (RFC 9814 §4 - algorithm confusion)");
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
241
275
|
// DER Ecdsa-Sig-Value SEQUENCE { r, s } -> fixed-width r||s (P1363), rejecting
|
|
242
276
|
// r or s outside [1, n-1] (CVE-2022-21449 "Psychic Signatures").
|
|
243
277
|
function ecdsaDerToP1363(der, curve) {
|
|
@@ -270,8 +304,10 @@ function ecdsaDerToP1363(der, curve) {
|
|
|
270
304
|
// Verify cert.signatureValue over cert.tbsBytes with the working public key.
|
|
271
305
|
function builtinVerify(state, cert) {
|
|
272
306
|
var d;
|
|
273
|
-
try {
|
|
274
|
-
|
|
307
|
+
try {
|
|
308
|
+
d = resolveDescriptor(cert.signatureAlgorithm);
|
|
309
|
+
assertKeyMatchesSigAlg(state.workingPublicKey, cert.signatureAlgorithm.oid, d);
|
|
310
|
+
} catch (e) { return Promise.resolve({ ok: false, code: pathCode(e, "path/unsupported-algorithm"), error: e }); }
|
|
275
311
|
// The signature is an octet-aligned BIT STRING (no unused bits) for every
|
|
276
312
|
// supported algorithm; a non-zero unused-bit count is malformed.
|
|
277
313
|
if (cert.signatureValue.unusedBits !== 0) return Promise.resolve({ ok: false, code: "path/bad-signature" });
|
|
@@ -1387,8 +1423,10 @@ function crlEntryReason(entry) {
|
|
|
1387
1423
|
|
|
1388
1424
|
function verifyCrlSignature(theCrl, issuer) {
|
|
1389
1425
|
var d;
|
|
1390
|
-
try {
|
|
1391
|
-
|
|
1426
|
+
try {
|
|
1427
|
+
d = resolveDescriptor(theCrl.signatureAlgorithm);
|
|
1428
|
+
assertKeyMatchesSigAlg(issuer.workingPublicKey, theCrl.signatureAlgorithm.oid, d);
|
|
1429
|
+
} catch (_e) { return Promise.resolve(false); }
|
|
1392
1430
|
if (theCrl.signatureValue.unusedBits !== 0) return Promise.resolve(false); // non-octet-aligned signature
|
|
1393
1431
|
var key;
|
|
1394
1432
|
return subtle.importKey("spki", issuer.workingPublicKey, d.imp, false, ["verify"]).then(function (k) {
|
package/lib/schema-pkix.js
CHANGED
|
@@ -156,6 +156,15 @@ function algorithmIdentifier(ns, opts) {
|
|
|
156
156
|
arity: { min: 1 }, code: ns.prefix + "/bad-algorithm-identifier", what: "AlgorithmIdentifier",
|
|
157
157
|
build: function (m, ctx) {
|
|
158
158
|
var dotted = m.fields.algorithm.value;
|
|
159
|
+
// RFC 9909 §3 / RFC 9814 §4 / RFC 9881 §2 / RFC 8410 §3: for the PQC
|
|
160
|
+
// signature families (ML-DSA, SLH-DSA) and the Edwards/Montgomery curves,
|
|
161
|
+
// the `parameters` field MUST be absent — no explicit NULL, no bytes.
|
|
162
|
+
// Enforced ONCE here so every consumer of the shared AlgorithmIdentifier
|
|
163
|
+
// inherits the rule; the guard-parity bug class is structurally impossible.
|
|
164
|
+
if (m.fields.parameters.present && ctx.oid.paramsMustBeAbsent(dotted)) {
|
|
165
|
+
throw ctx.E(ctx.prefix + "/bad-algorithm-parameters",
|
|
166
|
+
"the " + (ctx.oid.name(dotted) || dotted) + " AlgorithmIdentifier parameters field MUST be absent (RFC 9909 §3 / RFC 9814 §4 / RFC 9881 §2 / RFC 8410 §3)");
|
|
167
|
+
}
|
|
159
168
|
return { oid: dotted, name: ctx.oid.name(dotted) || null, parameters: m.fields.parameters.present ? m.fields.parameters.node.bytes : null };
|
|
160
169
|
},
|
|
161
170
|
});
|
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:bcaea9d8-cd0d-4a9f-8ac3-72b3efecc8be",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-07-
|
|
8
|
+
"timestamp": "2026-07-09T15:12:46.820Z",
|
|
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.1.
|
|
22
|
+
"bom-ref": "@blamejs/pki@0.1.21",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "pki",
|
|
25
|
-
"version": "0.1.
|
|
25
|
+
"version": "0.1.21",
|
|
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.1.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/pki@0.1.21",
|
|
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.1.
|
|
57
|
+
"ref": "@blamejs/pki@0.1.21",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|