@blamejs/pki 0.7.35 → 0.7.37

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/cms-sign.js CHANGED
@@ -84,8 +84,11 @@ function _buildSignedAttrs(pairs) {
84
84
  return { setOf: setOf, wire: wire };
85
85
  }
86
86
 
87
+ var KNOWN_ATTRIBUTE_KEYS = intrinsic.assign(intrinsic.create(null), { type: 1, values: 1 });
87
88
  function _resolveAttrPairs(list, what) {
88
89
  return intrinsic.map(list || [], function (a) {
90
+ if (!a || typeof a !== "object") throw _err("cms/bad-input", "an attribute must be { type, values }");
91
+ guard.identifier.assertKnownKeys(a, KNOWN_ATTRIBUTE_KEYS, _err, "cms/bad-input", "unknown attribute field (an attribute is { type, values }): ");
89
92
  var vals = intrinsic.map(a.values || [], function (v) { return _toBuf(v, what); });
90
93
  if (!vals.length) throw _err("cms/bad-input", "a signed attribute must carry at least one value (RFC 5652 -- Attribute values is SET SIZE (1..MAX))");
91
94
  return { type: oid.isDottedDecimal(a.type) ? a.type : O(a.type), values: vals };
package/lib/crl-sign.js CHANGED
@@ -72,8 +72,6 @@ function _assertExtensionValueDecodes(node, extnId, what) {
72
72
  }
73
73
  }
74
74
 
75
- var OID_SKI = O("subjectKeyIdentifier");
76
-
77
75
  var CRL_REASON = constants.NAMES.CRL_REASON;
78
76
  var REASON_BY_NAME = intrinsic.create(null);
79
77
  Object.keys(CRL_REASON).forEach(function (v) { REASON_BY_NAME[CRL_REASON[v]] = Number(v); });
@@ -146,14 +144,8 @@ function _resolveReason(reason, isDelta) {
146
144
  return codeNum;
147
145
  }
148
146
 
149
- function _issuerSkiOf(ctx) {
150
- if (!ctx.issuerCert) return null;
151
- var ski = (ctx.issuerCert.extensions || []).filter(function (e) { return e.oid === OID_SKI; })[0];
152
- if (ski) { try { return asn1.read.octetString(asn1.decode(ski.value)); } catch (_e) { } } // allow:swallow-unverified -- a malformed issuer SKI is read as absent; the authorityKeyIdentifier keyIdentifier is then derived from the issuer public key
153
- return null;
154
- }
155
147
  function _akiKeyId(val, ctx) {
156
- var issuerSki = _issuerSkiOf(ctx);
148
+ var issuerSki = ctx.issuerCert ? _b.skiValueOf(ctx.issuerCert) : null;
157
149
  if (guard.bytes.isByteSource(val)) {
158
150
  var given = guard.bytes.snapshotSource(val, CrlError, "crl/bad-input", "the authorityKeyIdentifier keyIdentifier");
159
151
  /** @internal Sec. 5.2.1 names the CRL signer certificate's subject key identifier as the value,
package/lib/csr-sign.js CHANGED
@@ -34,6 +34,7 @@ var KNOWN_SPEC_KEYS = Object.assign(Object.create(null), { subject: 1, subjectPu
34
34
  * them was accepted and dropped, so asking for PEM and misspelling the option returned DER and
35
35
  * reported nothing. */
36
36
  var KNOWN_SIGN_OPTS = Object.assign(Object.create(null), { digestAlgorithm: 1, pem: 1, pss: 1 });
37
+ var KNOWN_KEY_WRAPPER_KEYS = Object.assign(Object.create(null), { key: 1 });
37
38
  var b = asn1.build;
38
39
  function _err(code, message, cause) { return new CsrError(code, message, cause); }
39
40
  function _signE(kind, message, cause) { return new CsrError("csr/" + kind, message, cause); }
@@ -109,7 +110,9 @@ function _sign(spec, key, opts) {
109
110
  if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("csr/bad-input", "the certification-request spec must be an object");
110
111
  guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, _err, "csr/bad-input", "unknown spec field ");
111
112
  guard.identifier.assertKnownKeys(opts, KNOWN_SIGN_OPTS, _err, "csr/bad-input", "pki.csr.sign has an unknown option ");
112
- var signingKey = (key && typeof key === "object" && !Buffer.isBuffer(key) && !(key instanceof Uint8Array) && key.type == null && "key" in key) ? key.key : key;
113
+ var wrapped = key && typeof key === "object" && !Buffer.isBuffer(key) && !(key instanceof Uint8Array) && key.type == null && "key" in key;
114
+ if (wrapped) guard.identifier.assertKnownKeys(key, KNOWN_KEY_WRAPPER_KEYS, _err, "csr/bad-input", "unknown field in the { key } wrapper (a signing option belongs in the third argument): ");
115
+ var signingKey = wrapped ? key.key : key;
113
116
  if (signingKey == null) throw _err("csr/bad-input", "a signing key (the subject's private key) is required");
114
117
 
115
118
  var subjectSpki = _b.reqDer(spec.subjectPublicKey, "spec.subjectPublicKey (the SPKI DER of the requested key)");
package/lib/ct.js CHANGED
@@ -255,12 +255,19 @@ function _u24Bytes(n) {
255
255
  * var preimage = pki.ct.reconstructSignedData({ entryType: 0, leafCert: der }, sct);
256
256
  * // hash `preimage` + verify against the log's public key at the verify layer
257
257
  */
258
+ /** @internal The two log-entry arms read different fields, and a field belonging to the other arm
259
+ * is refused the same way a misspelled one is: a value the arm never reads cannot be in the entry. */
260
+ var _X509_ENTRY_KEYS = intrinsic.assign(intrinsic.create(null), { entryType: 1, leafCert: 1 });
261
+ var _PRECERT_ENTRY_KEYS = intrinsic.assign(intrinsic.create(null), { entryType: 1, tbsCertificate: 1, issuerKeyHash: 1 });
258
262
  function reconstructSignedData(entry, sct) {
259
263
  entry = entry || {};
264
+ if (typeof entry !== "object") throw new CtError("ct/bad-input", "the log entry must be an object { entryType, ... } (RFC 6962 sec. 3.1)");
260
265
  var entryType = entry.entryType;
261
266
  if (entryType !== 0 && entryType !== 1) {
262
267
  throw new CtError("ct/bad-entry-type", "entryType must be x509_entry(0) or precert_entry(1), got " + guard.text.showValue(entryType) + " (RFC 6962 sec. 3.1)");
263
268
  }
269
+ guard.identifier.assertKnownKeys(entry, entryType === 0 ? _X509_ENTRY_KEYS : _PRECERT_ENTRY_KEYS, _ctErr, "ct/bad-input",
270
+ entryType === 0 ? "unknown x509_entry field (accepted: entryType, leafCert): " : "unknown precert_entry field (accepted: entryType, tbsCertificate, issuerKeyHash): ");
264
271
  if (!sct || typeof sct.timestamp !== "bigint" || sct.version !== 0) {
265
272
  throw new CtError("ct/bad-input", "reconstructSignedData expects a decoded v1 SCT from parseSctList().scts[]");
266
273
  }
@@ -522,8 +529,10 @@ function _logKeyMaterial(logKey) {
522
529
  * var sct = await pki.ct.signSct({ entryType: 0, leafCert: der }, signerKeyPkcs8);
523
530
  * var ext = pki.ct.encodeSctList([sct]);
524
531
  */
532
+ var _SIGN_SCT_OPTS = intrinsic.assign(intrinsic.create(null), { timestamp: 1, extensions: 1, logId: 1 });
525
533
  async function signSct(entry, logKey, opts) {
526
- opts = opts || {};
534
+ opts = guard.identifier.optionsObject(opts, _ctErr, "ct/bad-input", "pki.ct.signSct options");
535
+ guard.identifier.assertKnownKeys(opts, _SIGN_SCT_OPTS, _ctErr, "ct/bad-input", "unknown pki.ct.signSct option (accepted: timestamp, extensions, logId): ");
527
536
  var mat = _logKeyMaterial(logKey);
528
537
  var alg = _spkiAlg(mat.spki);
529
538
  var hashAlg = 4, sigAlg, imp, sign, ecdsaDer = false, coordLen;
package/lib/guard-name.js CHANGED
@@ -218,6 +218,15 @@ function _allCharsIn(s, table) {
218
218
 
219
219
  function stripTrailingDot(s) { return _charAt(s, s.length - 1) === "." ? _strSlice(s, 0, -1) : s; }
220
220
 
221
+ /** @internal Whether `s` opens with `scheme` followed by a colon, the scheme compared without
222
+ * regard to ASCII case (RFC 3986 sec. 3.1). `scheme` is given in lower case. */
223
+ // @enforced-by behavioral -- a scheme comparison has no rename-proof code shape; the vectors refusing a location under the wrong scheme are the guard
224
+ function uriSchemeIs(s, scheme) {
225
+ if (typeof s !== "string" || s.length <= scheme.length) return false;
226
+ if (_charCodeAt(s, scheme.length) !== 0x3a) return false;
227
+ return lowerAscii(_strSlice(s, 0, scheme.length)) === scheme;
228
+ }
229
+
221
230
  /** @internal A host name of two or more labels that is not an address, which is the form a URI
222
231
  * name constraint is compared by (RFC 5280 sec. 4.2.1.10). */
223
232
  function isFqdnHost(host) {
@@ -527,7 +536,7 @@ module.exports = intrinsic.freeze({
527
536
  assertNoControlBytes: assertNoControlBytes, assertPrintableIa5: assertPrintableIa5,
528
537
  dnEqual: dnEqual, rdnEqual: rdnEqual, emailEqual: emailEqual, dpnCorresponds: dpnCorresponds,
529
538
  escapeControlBytes: escapeControlBytes, escapeDnValue: escapeDnValue,
530
- lowerAscii: lowerAscii,
539
+ lowerAscii: lowerAscii, uriSchemeIs: uriSchemeIs,
531
540
  stripTrailingDot: stripTrailingDot, isFqdnHost: isFqdnHost, splitMailbox: splitMailbox,
532
541
  constraintBaseRefusal: constraintBaseRefusal,
533
542
  constraintBaseUnreadable: constraintBaseUnreadable,
package/lib/lint.js CHANGED
@@ -749,18 +749,6 @@ function _crlDecodedExtension(crl, name) {
749
749
  }
750
750
  }
751
751
 
752
- /** @internal Whether a string opens with the given URI scheme followed by a colon, compared
753
- * without regard to case by scanning character codes. */
754
- function _uriSchemeIs(s, scheme) {
755
- if (typeof s !== "string" || s.length <= scheme.length) return false;
756
- for (var i = 0; i < scheme.length; i++) {
757
- var c = s.charCodeAt(i);
758
- if (c >= 65 && c <= 90) c += 32;
759
- if (c !== scheme.charCodeAt(i)) return false;
760
- }
761
- return s.charCodeAt(scheme.length) === 58;
762
- }
763
-
764
752
  /** @internal The schemes that satisfy the section 5.2.7 recommendation. The secured forms count:
765
753
  * warning about an https or ldaps location would report the more protected spelling of the two the
766
754
  * clause names. */
@@ -1201,7 +1189,7 @@ var RFC5280_CRL_RULES = [
1201
1189
  var reachable = descs.some(function (d) {
1202
1190
  var loc = d.accessLocation;
1203
1191
  if (!loc || loc.tag !== 6) return false;
1204
- return AIA_RECOMMENDED_SCHEMES.some(function (s) { return _uriSchemeIs(loc.value, s); });
1192
+ return AIA_RECOMMENDED_SCHEMES.some(function (s) { return guard.name.uriSchemeIs(loc.value, s); });
1205
1193
  });
1206
1194
  return reachable ? null : true;
1207
1195
  },
package/lib/ocsp.js CHANGED
@@ -84,11 +84,15 @@ function _toDer(input, what) {
84
84
  }
85
85
  function _keyValue(spkiDer) { return ocspVerify.ocspKeyValue(spkiDer); }
86
86
  function _nonceExt(nonceBytes) { return b.sequence([b.oid(OID_OCSP_NONCE), b.octetString(b.octetString(nonceBytes))]); }
87
- function _assertNonce(nonceBytes) {
88
- if (!Buffer.isBuffer(nonceBytes) || nonceBytes.length < 1 || nonceBytes.length > 128) {
89
- throw _err("ocsp/bad-input", "a nonce must be a Buffer of 1..128 octets (RFC 9654 sec. 2.1)");
87
+ /** @internal RFC 9654 sec. 2.1 bounds a nonce at 1..128 octets, and adds for the requester: "An OCSP
88
+ * requester that implements the extension in this document MUST use a minimum length of 32
89
+ * octets". A responder echoes what it was sent, so its floor stays at the section's 1. */
90
+ function _assertNonce(nonceBytes, floor) {
91
+ if (!Buffer.isBuffer(nonceBytes) || nonceBytes.length < floor || nonceBytes.length > 128) {
92
+ throw _err("ocsp/bad-input", "a nonce must be a Buffer of " + floor + "..128 octets (RFC 9654 sec. 2.1)");
90
93
  }
91
94
  }
95
+ var REQUESTER_NONCE_FLOOR = 32, RESPONDER_NONCE_FLOOR = 1;
92
96
  function _buildCertID(cert, issuer, hashName) {
93
97
  var wc = HASH_WC[guard.text.keyOf(hashName)];
94
98
  if (!wc) throw _err("ocsp/bad-input", "unsupported CertID hashAlgorithm " + guard.text.showValue(hashName) + " (sha1 / sha256 / sha384 / sha512)");
@@ -122,9 +126,12 @@ function _buildCertID(cert, issuer, hashName) {
122
126
  *
123
127
  * @opts
124
128
  * hashAlgorithm `"sha1"` (default) / `"sha256"` / `"sha384"` / `"sha512"`; the CertID identity hash.
125
- * nonce `true` for a fresh 32-octet CSPRNG nonce (RFC 9654), or a caller Buffer (1..128 octets).
126
- * requestorName a Name (RDN array) placed in the [1] requestorName as a directoryName.
127
- * signer `{ cert, key }` to sign the request (requires requestorName).
129
+ * nonce `true` for a fresh 32-octet CSPRNG nonce (RFC 9654), or a caller Buffer of 32..128
130
+ * octets (RFC 9654 sec. 2.1: a requester MUST use at least 32).
131
+ * requestorName a Name (DER `BufferSource`, or a parsed Name) placed in the [1] requestorName as a
132
+ * directoryName. With `signer`, the signer certificate's subject is taken when none
133
+ * is stated (RFC 6960 sec. 4.1.2: a requestor that signs SHALL specify its name).
134
+ * signer `{ cert, key }` to sign the request.
128
135
  * profile `"lightweight"`: one Request, SHA-1 CertID, nonce-only extensions (RFC 5019).
129
136
  * pem emit a PEM `OCSP REQUEST` string instead of DER.
130
137
  * @example
@@ -148,6 +155,8 @@ function buildRequest(query, opts) {
148
155
  var _BUILD_REQUEST_OPTS = Object.assign(Object.create(null), {
149
156
  hashAlgorithm: 1, nonce: 1, pem: 1, profile: 1, requestorName: 1, signer: 1
150
157
  });
158
+ var _QUERY_KEYS = Object.assign(Object.create(null), { cert: 1, issuer: 1, singleRequestExtensions: 1 });
159
+ var _REQUEST_SIGNER_KEYS = Object.assign(Object.create(null), { cert: 1, key: 1 });
151
160
 
152
161
  function _buildRequest(query, opts) {
153
162
  opts = guard.identifier.optionsObject(opts, _err, "ocsp/bad-input", "pki.ocsp.buildRequest options");
@@ -159,10 +168,27 @@ function _buildRequest(query, opts) {
159
168
  var queries = Array.isArray(query) ? pkiBuild.reqDenseArray(query, "queries", _err, "ocsp/bad-input") : [query];
160
169
  if (!queries.length) throw _err("ocsp/bad-input", "buildRequest needs at least one { cert, issuer } query");
161
170
  if (lightweight && queries.length !== 1) throw _err("ocsp/bad-input", "the lightweight profile permits exactly one Request (RFC 5019 sec. 2.1.1)");
162
- if (opts.signer && !opts.requestorName) throw _err("ocsp/bad-input", "a signed OCSP request MUST carry requestorName (RFC 6960 sec. 4.1.2)");
171
+ var signerCertDer = null, signerCert = null;
172
+ if (opts.signer) {
173
+ guard.identifier.assertKnownKeys(opts.signer, _REQUEST_SIGNER_KEYS, _err, "ocsp/bad-input", "unknown request signer field (the signer is { cert, key }): ");
174
+ signerCertDer = _normCertDer(opts.signer.cert, "the request signer certificate");
175
+ signerCert = _certOf(signerCertDer, "the request signer certificate");
176
+ }
177
+ /** @internal Sec. 4.1.2: "If the request is signed, the requestor SHALL specify its name in the
178
+ * requestorName field." The signer certificate names the requestor, so its subject is the name
179
+ * when none is stated. A certificate with an empty subject names its holder in a critical
180
+ * subjectAltName (RFC 5280 sec. 4.1.2.6); an empty Name names nobody, so it is not derived. */
181
+ var requestorNameDer = null;
182
+ if (opts.requestorName != null) requestorNameDer = _nameDer(opts.requestorName);
183
+ else if (signerCert !== null) {
184
+ if (!signerCert.subject.rdns.length) throw _err("ocsp/bad-input", "the request signer certificate has an empty subject, so no requestorName can be taken from it; state requestorName (RFC 6960 sec. 4.1.2)");
185
+ requestorNameDer = signerCert.subject.bytes;
186
+ }
163
187
 
164
188
  return Promise.all(queries.map(function (q) {
165
- if (!q || q.cert == null || q.issuer == null) throw _err("ocsp/bad-input", "each query must be { cert, issuer }");
189
+ if (!q || typeof q !== "object") throw _err("ocsp/bad-input", "each query must be { cert, issuer }");
190
+ guard.identifier.assertKnownKeys(q, _QUERY_KEYS, _err, "ocsp/bad-input", "unknown query field (a query is { cert, issuer, singleRequestExtensions? }): ");
191
+ if (q.cert == null || q.issuer == null) throw _err("ocsp/bad-input", "each query must be { cert, issuer }");
166
192
  var cert = _certOf(q.cert, "the query certificate");
167
193
  var issuer = _certOf(q.issuer, "the issuer certificate");
168
194
  return _buildCertID(cert, issuer, hashName).then(function (certID) {
@@ -175,22 +201,17 @@ function _buildRequest(query, opts) {
175
201
  });
176
202
  })).then(function (requests) {
177
203
  var tbsChildren = [];
178
- if (opts.requestorName) {
179
- var nameDer = _nameDer(opts.requestorName);
180
- tbsChildren.push(b.explicit(1, b.contextConstructed(4, nameDer)));
181
- }
204
+ if (requestorNameDer !== null) tbsChildren.push(b.explicit(1, b.contextConstructed(4, requestorNameDer)));
182
205
  tbsChildren.push(b.sequence(requests));
183
206
  var reqExts = [];
184
207
  if (opts.nonce) {
185
208
  var nonceBytes = opts.nonce === true ? nodeCrypto.randomBytes(32) : opts.nonce;
186
- _assertNonce(nonceBytes);
209
+ _assertNonce(nonceBytes, REQUESTER_NONCE_FLOOR);
187
210
  reqExts.push(_nonceExt(nonceBytes));
188
211
  }
189
212
  if (reqExts.length) tbsChildren.push(b.explicit(2, b.sequence(reqExts)));
190
213
  var tbsRequest = b.sequence(tbsChildren);
191
- if (!opts.signer) return _emitReq(b.sequence([tbsRequest]), opts);
192
- var signerCertDer = _normCertDer(opts.signer.cert, "the request signer certificate");
193
- var signerCert = _certOf(signerCertDer, "the request signer certificate");
214
+ if (signerCert === null) return _emitReq(b.sequence([tbsRequest]), opts);
194
215
  var scheme = signScheme.resolveSignScheme(signerCert, { combinedRsaSig: true }, true, _signE);
195
216
  return signScheme.signOverTbs(scheme, opts.signer.key, tbsRequest, _signE).then(function (sig) {
196
217
  var optionalSignature = b.sequence([scheme.sigAlgId, b.bitString(sig, 0), b.explicit(0, b.sequence([b.raw(signerCertDer)]))]);
@@ -275,13 +296,21 @@ function sign(responseData, responder, opts) {
275
296
  }
276
297
 
277
298
  var _SIGN_OPTS = Object.assign(Object.create(null), { embedCert: 1, extendedRevoke: 1, nonce: 1, pem: 1 });
299
+ var _RESPONSE_DATA_KEYS = Object.assign(Object.create(null), { responderID: 1, responses: 1, producedAt: 1 });
300
+ var _SINGLE_RESPONSE_KEYS = Object.assign(Object.create(null), { cert: 1, issuer: 1, certID: 1, hashAlgorithm: 1, status: 1, thisUpdate: 1, nextUpdate: 1, singleExtensions: 1 });
301
+ var _RESPONDER_KEYS = Object.assign(Object.create(null), { cert: 1, key: 1 });
302
+ var _STATUS_KEYS = Object.assign(Object.create(null), { revoked: 1, revocationReason: 1 });
278
303
 
279
304
  function _sign(responseData, responder, opts) {
280
305
  opts = guard.identifier.optionsObject(opts, _err, "ocsp/bad-input", "pki.ocsp.sign options");
281
306
  guard.identifier.assertKnownKeys(opts, _SIGN_OPTS, _err, "ocsp/bad-input",
282
307
  "pki.ocsp.sign has an unknown option (the nonce to echo back is `nonce`): ");
283
308
  responseData = responseData || {};
284
- if (!responder || responder.cert == null || responder.key == null) throw _err("ocsp/bad-input", "a responder must be { cert, key }");
309
+ if (typeof responseData !== "object") throw _err("ocsp/bad-input", "the responseData must be an object { responderID, responses, producedAt? }");
310
+ guard.identifier.assertKnownKeys(responseData, _RESPONSE_DATA_KEYS, _err, "ocsp/bad-input", "unknown responseData field (accepted: responderID, responses, producedAt): ");
311
+ if (!responder || typeof responder !== "object") throw _err("ocsp/bad-input", "a responder must be { cert, key }");
312
+ guard.identifier.assertKnownKeys(responder, _RESPONDER_KEYS, _err, "ocsp/bad-input", "unknown responder field (the responder is { cert, key }; a signing option belongs in the third argument): ");
313
+ if (responder.cert == null || responder.key == null) throw _err("ocsp/bad-input", "a responder must be { cert, key }");
285
314
  var respCertDer = _normCertDer(responder.cert, "the responder certificate");
286
315
  var respCert = _certOf(respCertDer, "the responder certificate");
287
316
  var ownedKeyBytes = [];
@@ -314,7 +343,7 @@ function _signResponse(responseData, responder, respCert, respCertDer, responder
314
343
  }
315
344
  var rdChildren = [ridNode, b.generalizedTime(_asEncodableDate(responseData.producedAt, "producedAt") || new Date()), b.sequence(srNodes)];
316
345
  var respExts = [];
317
- if (opts.nonce != null) { _assertNonce(opts.nonce); respExts.push(_nonceExt(opts.nonce)); }
346
+ if (opts.nonce != null) { _assertNonce(opts.nonce, RESPONDER_NONCE_FLOOR); respExts.push(_nonceExt(opts.nonce)); }
318
347
  if (opts.extendedRevoke || anyNonIssued) respExts.push(b.sequence([b.oid(OID_EXTENDED_REVOKE), b.octetString(b.nullValue())]));
319
348
  if (respExts.length) rdChildren.push(b.explicit(1, b.sequence(respExts)));
320
349
  var responseDataDer = b.sequence(rdChildren);
@@ -362,6 +391,9 @@ function _responderID(rid, respCert) {
362
391
  function _buildSingleResponse(r, opts) {
363
392
  r = r || {};
364
393
  var certIdP;
394
+ if (typeof r !== "object") return Promise.reject(_err("ocsp/bad-input", "each response entry must be an object"));
395
+ try { guard.identifier.assertKnownKeys(r, _SINGLE_RESPONSE_KEYS, _err, "ocsp/bad-input", "unknown response entry field (accepted: cert, issuer, certID, hashAlgorithm, status, thisUpdate, nextUpdate, singleExtensions): "); }
396
+ catch (e) { return Promise.reject(e); }
365
397
  if (r.certID != null) certIdP = Promise.resolve(b.raw(guard.bytes.view(r.certID, OcspError, "ocsp/bad-input", "a response entry's certID")));
366
398
  else if (r.cert != null && r.issuer != null) certIdP = _buildCertID(_certOf(r.cert, "a response certificate"), _certOf(r.issuer, "a response issuer"), r.hashAlgorithm || "sha1");
367
399
  else return Promise.reject(_err("ocsp/bad-input", "each response entry needs { certID } or { cert, issuer }"));
@@ -505,6 +537,7 @@ function _certStatusNode(status, opts) {
505
537
  if (status == null || status === "good") return b.contextPrimitive(0, Buffer.alloc(0));
506
538
  if (status === "unknown") return b.contextPrimitive(2, Buffer.alloc(0));
507
539
  if (typeof status === "object" && status.revoked != null) {
540
+ guard.identifier.assertKnownKeys(status, _STATUS_KEYS, _err, "ocsp/bad-input", "unknown revoked status field (a revoked status is { revoked, revocationReason? }): ");
508
541
  var ri = [b.generalizedTime(_asEncodableDate(status.revoked, "the revocation time"))];
509
542
  if (status.revocationReason != null) {
510
543
  var code = typeof status.revocationReason === "number" ? status.revocationReason : REASON_CODE[guard.text.keyOf(status.revocationReason)];
@@ -638,8 +671,8 @@ function _requestFromBytes(request) {
638
671
  }
639
672
  function _reqVerdict(parsed, extra) {
640
673
  return guard.verdict.of({
641
- valid: extra.signed === true && extra.signatureValid === true,
642
- signed: extra.signed, signatureValid: extra.signatureValid,
674
+ valid: extra.signed === true && extra.signatureValid === true && extra.requestorNamed === true,
675
+ signed: extra.signed, signatureValid: extra.signatureValid, requestorNamed: extra.requestorNamed === true,
643
676
  signerCert: extra.signerCert != null ? extra.signerCert : null,
644
677
  signerCerts: extra.signerCerts != null ? extra.signerCerts : [],
645
678
  certs: extra.certs != null ? extra.certs : [],
@@ -664,18 +697,44 @@ async function _findRequestSigners(candidates, strict, parsed, sig, sigBits) {
664
697
  }
665
698
  return { matches: matches, parseable: parseable };
666
699
  }
700
+ /** @internal RFC 6960 sec. 4.1.2: "If the request is signed, the requestor SHALL specify its name
701
+ * in the requestorName field." The requestor is whoever holds the key that signed, so the name is
702
+ * held to the subject of a certificate that verified the signature, compared as a distinguished
703
+ * name (RFC 5280 sec. 7.1). The parser refuses a signed request that names nobody
704
+ * (ocsp/missing-requestor-name); one naming its requestor by a GeneralName form other than
705
+ * directoryName leaves the check unperformed and never a pass. */
706
+ function _requestorNamed(parsed, matches) {
707
+ var rn = parsed.requestorName;
708
+ if (rn.tagNumber !== 4) {
709
+ return { named: [], reason: "the signed OCSP request names its requestor by a GeneralName form [" + rn.tagNumber + "] this responder does not compare to a certificate subject; a directoryName is compared (RFC 6960 sec. 4.1.2)" };
710
+ }
711
+ if (!rn.value.rdns.length) return { named: [], reason: "the signed OCSP request's requestorName is an empty distinguished name, which names nobody (RFC 6960 sec. 4.1.2)" };
712
+ var named = [];
713
+ for (var i = 0; i < matches.length; i++) {
714
+ if (guard.name.dnEqual(matches[i].subject.rdns, rn.value.rdns, _err, "ocsp/bad-input", "the requestorName")) named.push(matches[i]);
715
+ }
716
+ if (named.length) return { named: named, reason: null };
717
+ return { named: [], reason: "the requestorName " + guard.text.showValue(rn.value.dn) + " is not the subject of a certificate that signed the request (RFC 6960 sec. 4.1.2)" };
718
+ }
719
+ /** @internal Several certificates can carry the signing key (a renewal beside the certificate it
720
+ * replaced), and one of them may carry another subject. The signer the verdict names, and the set
721
+ * the responder builds its trusted path from, are the certificates that both verified the signature
722
+ * AND carry the name the request states; a same-key certificate under another name is not the
723
+ * requestor, whatever order the request embeds them in. */
667
724
  function _signerVerdict(parsed, found, failReason) {
668
725
  if (!found.matches.length) return _reqVerdict(parsed, { signed: true, signatureValid: false, certs: found.parseable, reason: failReason });
726
+ var bound = _requestorNamed(parsed, found.matches);
727
+ var signers = bound.named.length ? bound.named : found.matches;
669
728
  return _reqVerdict(parsed, {
670
- signed: true, signatureValid: true, signerCert: found.matches[0].der,
671
- signerCerts: found.matches.map(function (m) { return m.der; }), certs: found.parseable,
672
- signerSubject: { dn: found.matches[0].subject.dn, rdns: found.matches[0].subject.rdns }, reason: null,
729
+ signed: true, signatureValid: true, requestorNamed: bound.reason === null, signerCert: signers[0].der,
730
+ signerCerts: signers.map(function (m) { return m.der; }), certs: found.parseable,
731
+ signerSubject: { dn: signers[0].subject.dn, rdns: signers[0].subject.rdns }, reason: bound.reason,
673
732
  });
674
733
  }
675
734
 
676
735
  /**
677
736
  * @primitive pki.ocsp.verifyRequest
678
- * @signature pki.ocsp.verifyRequest(request, opts?) -> Promise<{ valid, signed, signatureValid, signerCert, signerCerts, certs, signerSubject, requestorName, requestList, requestExtensions, version, reason }>
737
+ * @signature pki.ocsp.verifyRequest(request, opts?) -> Promise<{ valid, signed, signatureValid, requestorNamed, signerCert, signerCerts, certs, signerSubject, requestorName, requestList, requestExtensions, version, reason }>
679
738
  * @since 0.6.0
680
739
  * @status stable
681
740
  * @spec RFC 6960
@@ -692,18 +751,24 @@ function _signerVerdict(parsed, found, failReason) {
692
751
  *
693
752
  * `signatureValid` means only that a certificate's key made this signature over this request. It
694
753
  * says nothing about whether that certificate is trusted: `signerCerts` is every certificate the
695
- * request carries whose key verified the signature (RFC 6960 sec. 4.1.1 certs is unordered, and a
696
- * key may appear under an expired certificate beside its renewal), so the responder builds a trusted
697
- * path to one of them rather than depend on ordering. `signerCert` and the decoded `signerSubject`
698
- * are the first of those, the common single-signer case. `certs` is every parseable certificate the
754
+ * request carries whose key verified the signature AND whose subject is the `requestorName` the
755
+ * request states (RFC 6960 sec. 4.1.1 certs is unordered, and a key may appear under an expired
756
+ * certificate beside its renewal; a same-key certificate under another name is not the requestor),
757
+ * so the responder builds a trusted path to one of them rather than depend on ordering. `signerCert`
758
+ * and the decoded `signerSubject` are the first of those, the common single-signer case; when no
759
+ * verifying certificate carries the name, they fall back to the verifying ones and `valid` is
760
+ * false. `certs` is every parseable certificate the
699
761
  * request carried (or opts.certs supplied), including intermediates that do not sign and so are absent
700
762
  * from `signerCerts`: the responder passes it as the `opts.candidates` pool to `pki.path.build`, which
701
763
  * discovers and validates the ordered path from a `signerCerts` entry (leaf) up to a trust anchor.
702
764
  * The responder then confirms that certificate is authorized to sign the request: its `keyUsage`,
703
765
  * where present, must assert `digitalSignature` (RFC 5280 sec. 4.2.1.3, since the certificate signed
704
- * the request). It also compares the certificate's subject to the `requestorName` it expects. The decoded
705
- * `requestList`, `requestExtensions` and `version` are
706
- * returned so the CertIDs being asked about need no re-parse.
766
+ * the request). The `requestorName` a signed request carries (RFC 6960 sec. 4.1.2: a requestor that
767
+ * signs SHALL specify its name) is held to the subject of a certificate that verified the signature,
768
+ * compared as a distinguished name (RFC 5280 sec. 7.1): `requestorNamed` is true when it is, `valid`
769
+ * requires it, and a name given as a GeneralName form other than directoryName is not compared and
770
+ * never passes. The decoded `requestorName` (with its `value` for a directoryName), `requestList`,
771
+ * `requestExtensions` and `version` are returned so the CertIDs being asked about need no re-parse.
707
772
  *
708
773
  * @opts
709
774
  * - `certs` An array of certificates (DER `Buffer` / `Uint8Array` or PEM strings) supplying the
package/lib/pki-build.js CHANGED
@@ -28,6 +28,7 @@ var _isBufferChk = intrinsic.isBuffer;
28
28
  var _stringify = intrinsic.stringify;
29
29
  var _mapIntrinsic = intrinsic.map;
30
30
  var _bufferConcatIntrinsic = intrinsic.bufferConcat;
31
+ var OID_SKI = oid.byName("subjectKeyIdentifier");
31
32
 
32
33
  function _isAlphaCode(c) { return (c >= 65 && c <= 90) || (c >= 97 && c <= 122); }
33
34
  function _isDigitCode(c) { return c >= 48 && c <= 57; }
@@ -81,14 +82,14 @@ function _componentBytesOk(s, from, to, byteOk) {
81
82
  return true;
82
83
  }
83
84
 
84
- function _validUriHost(s, from, to) {
85
+ function _validUriHost(s, from, to, singleLabel) {
85
86
  if (to <= from) return false;
86
87
  var host = _sliceStr(s, from, to), len = host.length;
87
88
  if (_looksLikeIPv4Shape(host)) return _packIpLiteral(host) !== null;
88
89
  var end = _charCodeAt(host, len - 1) === 46 ? len - 1 : len;
89
90
  if (end > 253) return false;
90
91
  var firstDot = _stringIndexOf(host, ".", 0);
91
- if (firstDot === -1 || firstDot >= end) return false;
92
+ if (!singleLabel && (firstDot === -1 || firstDot >= end)) return false;
92
93
  return _labelsValid(host, 0, len, _isHostLabelRange, true);
93
94
  }
94
95
 
@@ -98,11 +99,11 @@ function _validUriIp6Host(s, from, to) {
98
99
  return packed !== null && intrinsic.sizeOf(packed) === 16;
99
100
  }
100
101
 
101
- function _validUriAuthority(s, from, to) {
102
+ function _validUriAuthority(s, from, to, shape) {
102
103
  var i, c, at = -1;
103
104
  for (i = from; i < to; i += 1) {
104
105
  c = _charCodeAt(s, i);
105
- if (c === 64) { if (at !== -1) return false; at = i; }
106
+ if (c === 64) { if (at !== -1 || !shape.userinfo) return false; at = i; }
106
107
  }
107
108
  var hostStart = at === -1 ? from : at + 1;
108
109
  if (at !== -1 && !_componentBytesOk(s, from, at, _isUserinfoByte)) return false;
@@ -120,14 +121,31 @@ function _validUriAuthority(s, from, to) {
120
121
  var colon = -1;
121
122
  for (i = hostStart; i < to; i += 1) { if (_charCodeAt(s, i) === 58) { colon = i; break; } }
122
123
  var hostEnd = colon === -1 ? to : colon;
123
- if (!_validUriHost(s, hostStart, hostEnd)) return false;
124
+ var portAlone = hostEnd === hostStart && colon !== -1 && shape.emptyHost;
125
+ if (!portAlone && !_validUriHost(s, hostStart, hostEnd, shape.singleLabel)) return false;
124
126
  if (colon !== -1) {
125
127
  for (i = colon + 1; i < to; i += 1) { if (!_isDigitCode(_charCodeAt(s, i))) return false; }
126
128
  }
127
129
  return true;
128
130
  }
129
131
 
130
- function _looksLikeUri(s) {
132
+ /** @internal The shape a bare string must have to be read as a URI GeneralName without being told:
133
+ * a scheme, "//", an authority naming a multi-label host (a single label reads as a dNSName), and
134
+ * a well-formed remainder, a fragment included. */
135
+ var _URI_SHAPE = intrinsic.assign(intrinsic.create(null), { singleLabel: false, userinfo: true, emptyAuthority: false, emptyHost: false, queryNeedsPath: false, fragment: true });
136
+ /** @internal An HTTP URL (RFC 2616 sec. 3.2.2: "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]):
137
+ * no userinfo, a host of one label or many, a query only after an absolute path, no fragment. */
138
+ var _HTTP_URL_SHAPE = intrinsic.assign(intrinsic.create(null), { singleLabel: true, userinfo: false, emptyAuthority: false, emptyHost: false, queryNeedsPath: true, fragment: false });
139
+ /** @internal An LDAP URL (RFC 4516 sec. 2: scheme "://" [host [":" port]] ["/" dn ...]): no
140
+ * userinfo, a host of any label count that may be left out, with or without a port, and no
141
+ * fragment. The dn, attributes, scope and filter after the "/" are not parsed. */
142
+ var _LDAP_URL_SHAPE = intrinsic.assign(intrinsic.create(null), { singleLabel: true, userinfo: false, emptyAuthority: true, emptyHost: true, queryNeedsPath: false, fragment: false });
143
+
144
+ function _looksLikeUri(s) { return _uriShape(s, _URI_SHAPE); }
145
+ function isHttpUrl(s) { return typeof s === "string" && guard.name.uriSchemeIs(s, "http") && _uriShape(s, _HTTP_URL_SHAPE); }
146
+ function isLdapUrl(s) { return typeof s === "string" && guard.name.uriSchemeIs(s, "ldap") && _uriShape(s, _LDAP_URL_SHAPE); }
147
+
148
+ function _uriShape(s, shape) {
131
149
  var n = s.length, i, c;
132
150
  if (n === 0 || !_isAlphaCode(_charCodeAt(s, 0))) return false;
133
151
  i = 1;
@@ -140,8 +158,9 @@ function _looksLikeUri(s) {
140
158
  i += 3;
141
159
  var authStart = i, authEnd = n;
142
160
  for (; i < n; i += 1) { c = _charCodeAt(s, i); if (c === 47 || c === 63 || c === 35) { authEnd = i; break; } }
143
- if (authEnd === authStart) return false;
144
- if (!_validUriAuthority(s, authStart, authEnd)) return false;
161
+ if (authEnd === authStart) { if (!shape.emptyAuthority) return false; }
162
+ else if (!_validUriAuthority(s, authStart, authEnd, shape)) return false;
163
+ if (authEnd < n && shape.queryNeedsPath && _charCodeAt(s, authEnd) === 63) return false;
145
164
  var sawHash = false;
146
165
  i = authEnd;
147
166
  while (i < n) {
@@ -151,7 +170,7 @@ function _looksLikeUri(s) {
151
170
  i += 3;
152
171
  continue;
153
172
  }
154
- if (c === 35) { if (sawHash) return false; sawHash = true; }
173
+ if (c === 35) { if (sawHash || !shape.fragment) return false; sawHash = true; }
155
174
  if (!_isUriByte(c)) return false;
156
175
  i += 1;
157
176
  }
@@ -1268,7 +1287,7 @@ function makeBuilder(ctx) {
1268
1287
  extSubjectInfoAccess: extSubjectInfoAccess, extSubjectDirectoryAttributes: extSubjectDirectoryAttributes,
1269
1288
  extMsCertificateTemplate: extMsCertificateTemplate, extMsCaVersion: extMsCaVersion,
1270
1289
  extMsPreviousCertHash: extMsPreviousCertHash, extMsEnrollCertType: extMsEnrollCertType,
1271
- spkiKeyId: spkiKeyId, skiKeyId: skiKeyId,
1290
+ spkiKeyId: spkiKeyId, skiKeyId: skiKeyId, skiValueOf: skiValueOf,
1272
1291
  reqDer: reqDer, reqDenseArray: reqDenseArray, reqDerSequence: reqDerSequence, assertValidSpki: assertValidSpki, assertValidExtension: assertValidExtension,
1273
1292
  assertExtnValueIsDer: assertExtnValueIsDer,
1274
1293
  assertCertCriticality: assertCertCriticality,
@@ -1289,4 +1308,15 @@ function tbsSerialNumber(cert) {
1289
1308
  return asn1.read.integer(tbs.children[hasVersion ? 1 : 0]);
1290
1309
  }
1291
1310
 
1292
- module.exports = intrinsic.freeze({ makeBuilder: makeBuilder, reqDenseArray: reqDenseArrayImpl, KU_BIT: KU_BIT, tbsNameField: tbsNameField, tbsSerialNumber: tbsSerialNumber, randomSerial: randomSerial });
1311
+ /** @internal The subjectKeyIdentifier a parsed certificate carries, or null without one. RFC 5280
1312
+ * sec. 4.2.1.1 names it as the authorityKeyIdentifier keyIdentifier of everything issued under
1313
+ * that certificate, so a signer reads it here before deriving one from the key, and a verifier
1314
+ * matches a signer by it. */
1315
+ function skiValueOf(parsedCert) {
1316
+ var exts = intrinsic.filter(parsedCert.extensions, function (e) { return e.oid === OID_SKI; });
1317
+ if (!exts.length) return null;
1318
+ try { return asn1.read.octetString(asn1.decode(exts[0].value)); }
1319
+ catch (_e) { return null; } // allow:swallow-unverified -- a malformed SKI is read as absent; a signer then derives the authorityKeyIdentifier keyIdentifier from the public key, and a verifier matches on nothing
1320
+ }
1321
+
1322
+ module.exports = intrinsic.freeze({ makeBuilder: makeBuilder, reqDenseArray: reqDenseArrayImpl, KU_BIT: KU_BIT, tbsNameField: tbsNameField, tbsSerialNumber: tbsSerialNumber, randomSerial: randomSerial, skiValueOf: skiValueOf, isHttpUrl: isHttpUrl, isLdapUrl: isLdapUrl });
@@ -577,6 +577,13 @@ _AC_EXT_DECODERS[_Oav("targetInformation")] = _targetInformation;
577
577
  _AC_EXT_DECODERS[_Oav("noRevAvail")] = _noRevAvail;
578
578
  _AC_EXT_DECODERS[_Oav("aaControls")] = _aaControls;
579
579
  _AC_EXT_DECODERS[_Oav("acProxying")] = _acProxying;
580
+ /** @internal The three RFC 5280 extensions RFC 5755 sec. 4.3.3 to 4.3.5 profile for an AC are read
581
+ * through the certificate decoders, so a relying party running the sec. 6 "pointer in AC" scheme
582
+ * reads the distribution point and the OCSP location off the parse rather than off raw bytes. */
583
+ var _CERT_EXT_DECODERS = pkix.certExtensionDecoders(NS).byOid;
584
+ _AC_EXT_DECODERS[_Oav("authorityKeyIdentifier")] = _CERT_EXT_DECODERS[_Oav("authorityKeyIdentifier")];
585
+ _AC_EXT_DECODERS[_Oav("authorityInfoAccess")] = _CERT_EXT_DECODERS[_Oav("authorityInfoAccess")];
586
+ _AC_EXT_DECODERS[_Oav("cRLDistributionPoints")] = _CERT_EXT_DECODERS[_Oav("cRLDistributionPoints")];
580
587
 
581
588
  // @internal
582
589
  function validateAttributeValue(type, valueDer) {
@@ -85,7 +85,9 @@ function certificateBytes() {
85
85
  return pkix.rawNonEmptySequence(NS, { code: "ocsp/bad-certs", message: "each certs element must be a non-empty Certificate SEQUENCE (RFC 6960 sec. 4.1.1/sec. 4.2.1)" });
86
86
  }
87
87
 
88
- var GENERAL_NAME_RAW = pkix.generalName(NS, { code: "ocsp/bad-requestor-name" });
88
+ /** @internal The requestorName is read with its value decoded, so a responder compares a
89
+ * directoryName to the signer certificate's subject (RFC 6960 sec. 4.1.2) off the parse. */
90
+ var GENERAL_NAME_RAW = pkix.generalName(NS, { code: "ocsp/bad-requestor-name", decodeValue: true });
89
91
 
90
92
  function _rawSignature(field) {
91
93
  var sig = field.value;
@@ -388,7 +390,7 @@ var TBS_REQUEST = schema.seq([
388
390
  var rn = m.fields.requestorName;
389
391
  return {
390
392
  version: m.fields.version.value,
391
- requestorName: rn.present ? { bytes: rn.value.bytes, tagClass: rn.value.tagClass, tagNumber: rn.value.tagNumber } : null,
393
+ requestorName: rn.present ? { bytes: rn.value.bytes, tagClass: rn.value.tagClass, tagNumber: rn.value.tagNumber, value: rn.value.value } : null,
392
394
  requestList: m.fields.requestList.value.items.map(function (it) { return it.value.result; }),
393
395
  requestExtensions: m.fields.requestExtensions.present ? _validateOcspExtensions(m.fields.requestExtensions.value.result) : null,
394
396
  };
package/lib/x509-sign.js CHANGED
@@ -39,8 +39,6 @@ function _err(code, message, cause) { return new CertificateError(code, message,
39
39
  function _signE(kind, message, cause) { return new CertificateError("x509/" + kind, message, cause); }
40
40
  function O(n) { return oid.byName(n); }
41
41
 
42
- var OID_SKI = O("subjectKeyIdentifier");
43
-
44
42
  var KNOWN_SPEC_KEYS = intrinsic.assign(intrinsic.create(null), {
45
43
  subject: 1, subjectPublicKey: 1, notBefore: 1, notAfter: 1, serialNumber: 1, extensions: 1,
46
44
  });
@@ -77,13 +75,8 @@ var _encodeName = _b.encodeName, _isEmptyName = _b.isEmptyName, _reqDer = _b.req
77
75
  _skiKeyId = _b.skiKeyId, _spkiKeyId = _b.spkiKeyId, _serialInteger = _b.serialInteger;
78
76
 
79
77
 
80
- function _skiValueOf(caCert) {
81
- var ext = (caCert.extensions || []).filter(function (e) { return e.oid === OID_SKI; })[0];
82
- if (ext) { try { return asn1.read.octetString(asn1.decode(ext.value)); } catch (_e) { } } // allow:swallow-unverified -- a malformed CA SKI is read as absent; _akiKeyId then derives the authorityKeyIdentifier keyIdentifier from the issuer public key
83
- return null;
84
- }
85
78
  function _akiKeyId(val, ctx) {
86
- var issuerSki = ctx.issuerCert ? _skiValueOf(ctx.issuerCert) : null;
79
+ var issuerSki = ctx.issuerCert ? _b.skiValueOf(ctx.issuerCert) : null;
87
80
  if (guard.bytes.isByteSource(val)) {
88
81
  var given = guard.bytes.snapshotSource(val, CertificateError, "x509/bad-input", "the authorityKeyIdentifier keyIdentifier");
89
82
  /** @internal Sec. 4.2.1.2: the issuer certificate's subjectKeyIdentifier MUST be the value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/pki",
3
- "version": "0.7.35",
3
+ "version": "0.7.37",
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:ad5ed621-8770-42d9-80be-736cc92092a0",
5
+ "serialNumber": "urn:uuid:6602edcd-778a-4204-8e53-1bc40ccb396c",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-12T11:00:49.561Z",
8
+ "timestamp": "2026-09-12T13:27:30.472Z",
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.35",
22
+ "bom-ref": "@blamejs/pki@0.7.37",
23
23
  "type": "application",
24
24
  "name": "pki",
25
- "version": "0.7.35",
25
+ "version": "0.7.37",
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.35",
29
+ "purl": "pkg:npm/%40blamejs/pki@0.7.37",
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.35",
57
+ "ref": "@blamejs/pki@0.7.37",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]