@blamejs/pki 0.7.24 → 0.7.26
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 +34 -0
- package/README.md +3 -3
- package/lib/attrcert-sign.js +3 -3
- package/lib/cmp-build.js +3 -3
- package/lib/cms-sign.js +3 -3
- package/lib/crl-sign.js +2 -2
- package/lib/crmf-sign.js +1 -1
- package/lib/guard-time.js +20 -0
- package/lib/lint.js +538 -14
- package/lib/ocsp.js +80 -5
- package/lib/pki-build.js +1 -1
- package/lib/schema-crl.js +5 -0
- package/lib/schema-ocsp.js +76 -2
- package/lib/tsp-sign.js +1 -1
- package/lib/x509-sign.js +3 -3
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/ocsp.js
CHANGED
|
@@ -222,6 +222,14 @@ function _normCertDer(cert, what) {
|
|
|
222
222
|
* DER (RFC 6960 sec. 4.2.1: no CMS wrapper, no signed attributes). The responder certificate is
|
|
223
223
|
* embedded in `certs [0]` so a relying party can find it. Returns the response DER, or PEM.
|
|
224
224
|
*
|
|
225
|
+
* Each response may carry `singleExtensions`, as an object or as an array of pre-encoded Extension
|
|
226
|
+
* DER. The object form takes `archiveCutoff`, the Date before which the responder no longer holds
|
|
227
|
+
* status (RFC 6960 sec. 4.4.4), and `crlReferences`, a `{ crlUrl, crlNum, crlTime }` naming the CRL
|
|
228
|
+
* the status was drawn from (sec. 4.4.2), any subset of the three. A pre-encoded entry is read with
|
|
229
|
+
* the parser's own singleExtensions reader before it is emitted, so a response this verb signs is
|
|
230
|
+
* one `pki.schema.ocsp.parseResponse` reads back, and a malformed archiveCutoff or CrlID is refused
|
|
231
|
+
* here with the code the parser would have raised.
|
|
232
|
+
*
|
|
225
233
|
* @opts
|
|
226
234
|
* nonce a request nonce Buffer to echo back in responseExtensions (RFC 9654).
|
|
227
235
|
* extendedRevoke emit the id-pkix-ocsp-extended-revoke extension (RFC 6960 sec. 4.4.8).
|
|
@@ -280,7 +288,7 @@ function _signResponse(responseData, responder, respCert, respCertDer, responder
|
|
|
280
288
|
|
|
281
289
|
return _responderID(responseData.responderID, respCert).then(function (ridNode) {
|
|
282
290
|
return Promise.all(responses.map(function (r) { return _buildSingleResponse(r, opts); })).then(function (srNodes) {
|
|
283
|
-
var rdChildren = [ridNode, b.generalizedTime(
|
|
291
|
+
var rdChildren = [ridNode, b.generalizedTime(_asEncodableDate(responseData.producedAt, "producedAt") || new Date()), b.sequence(srNodes)];
|
|
284
292
|
var respExts = [];
|
|
285
293
|
if (opts.nonce != null) { _assertNonce(opts.nonce); respExts.push(_nonceExt(opts.nonce)); }
|
|
286
294
|
if (opts.extendedRevoke) respExts.push(b.sequence([b.oid(OID_EXTENDED_REVOKE), b.octetString(b.nullValue())]));
|
|
@@ -303,6 +311,13 @@ function _asDate(d) {
|
|
|
303
311
|
if (isNaN(guard.time.instantOf(dt))) throw _err("ocsp/bad-input", "an invalid date value " + guard.text.showValue(d));
|
|
304
312
|
return dt;
|
|
305
313
|
}
|
|
314
|
+
/** @internal `_asDate` for a Date this verb WRITES as a GeneralizedTime (producedAt, thisUpdate,
|
|
315
|
+
* nextUpdate, a revocation time): the encodable year range is held here so the fault stays in this
|
|
316
|
+
* verb's domain. The verify clock is only compared and stays on `_asDate`. */
|
|
317
|
+
function _asEncodableDate(d, which) {
|
|
318
|
+
var dt = _asDate(d);
|
|
319
|
+
return dt === null ? null : guard.time.assertEncodable(dt, _err, "ocsp/bad-input", which);
|
|
320
|
+
}
|
|
306
321
|
function _snapshotSignerKey(key, owned) {
|
|
307
322
|
if (Buffer.isBuffer(key) || key instanceof Uint8Array) { // allow:byte-source-narrow -- responder private key on the key-ownership contract (Buffer / Uint8Array / PEM / CryptoKey); widening keys is a separate root decision
|
|
308
323
|
var copy = guard.bytes.snapshot(key, OcspError, "ocsp/bad-input", "the responder key");
|
|
@@ -331,8 +346,8 @@ function _buildSingleResponse(r, opts) {
|
|
|
331
346
|
* attached handlers, and an earlier entry's rejection would be orphaned: the caller catches
|
|
332
347
|
* sign()'s failure and the process still sees an unhandled rejection. */
|
|
333
348
|
return certIdP.then(function (certID) {
|
|
334
|
-
var thisUpdate =
|
|
335
|
-
var nextUpdate = r.nextUpdate === null ? null : (
|
|
349
|
+
var thisUpdate = _asEncodableDate(r.thisUpdate, "thisUpdate") || new Date();
|
|
350
|
+
var nextUpdate = r.nextUpdate === null ? null : (_asEncodableDate(r.nextUpdate, "nextUpdate") || _defaultNextUpdate());
|
|
336
351
|
/** @internal RFC 6960 sec. 4.2.2.1 makes thisUpdate and nextUpdate a validity interval, and says
|
|
337
352
|
* it corresponds to the {thisUpdate, nextUpdate} interval in CRLs. An interval whose end
|
|
338
353
|
* precedes its start states a status window that closed before it opened, and pki.ocsp.verify
|
|
@@ -353,16 +368,76 @@ function _buildSingleResponse(r, opts) {
|
|
|
353
368
|
var statusNode = _certStatusNode(r.status, opts);
|
|
354
369
|
var srChildren = [certID, statusNode, b.generalizedTime(thisUpdate)];
|
|
355
370
|
if (nextUpdate !== null) srChildren.push(b.explicit(0, b.generalizedTime(nextUpdate)));
|
|
356
|
-
if (r.singleExtensions
|
|
371
|
+
if (r.singleExtensions != null) {
|
|
372
|
+
var singleDer = _singleExtensionsDer(r.singleExtensions);
|
|
373
|
+
if (singleDer.length) srChildren.push(b.explicit(1, b.sequence(singleDer)));
|
|
374
|
+
}
|
|
357
375
|
return b.sequence(srChildren);
|
|
358
376
|
});
|
|
359
377
|
}
|
|
360
378
|
function _defaultNextUpdate() { return new Date(Date.now() + constants.TIME.days(7)); }
|
|
379
|
+
var _SINGLE_EXT_KEYS = Object.assign(Object.create(null), { archiveCutoff: 1, crlReferences: 1 });
|
|
380
|
+
var _CRL_ID_KEYS = Object.assign(Object.create(null), { crlUrl: 1, crlNum: 1, crlTime: 1 });
|
|
381
|
+
|
|
382
|
+
/** @internal RFC 6960 sec. 4.4.2 and sec. 4.4.4 put archiveCutoff and the CRL references in a
|
|
383
|
+
* SingleResponse's singleExtensions. The object form names them as fields; the array form carries
|
|
384
|
+
* pre-encoded Extension DER, and each entry is run through the parser's own singleExtensions reader
|
|
385
|
+
* first, so this verb never emits an entry pki.schema.ocsp.parseResponse would refuse. */
|
|
386
|
+
function _singleExtensionsDer(spec) {
|
|
387
|
+
if (Array.isArray(spec)) {
|
|
388
|
+
var dense = pkiBuild.reqDenseArray(spec, "singleExtensions", _err, "ocsp/bad-input");
|
|
389
|
+
var ders = dense.map(function (d, i) {
|
|
390
|
+
return guard.bytes.snapshotSource(d, OcspError, "ocsp/bad-input", "singleExtensions[" + i + "]");
|
|
391
|
+
});
|
|
392
|
+
if (ders.length) ocspSchema.readSingleExtensionsDer(ders);
|
|
393
|
+
return ders;
|
|
394
|
+
}
|
|
395
|
+
if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) {
|
|
396
|
+
throw _err("ocsp/bad-input", "singleExtensions must be an object { archiveCutoff?, crlReferences? } or an array of pre-encoded Extension DER");
|
|
397
|
+
}
|
|
398
|
+
guard.identifier.assertKnownKeys(spec, _SINGLE_EXT_KEYS, _err, "ocsp/bad-input", function (k) {
|
|
399
|
+
return "unknown singleExtensions field " + guard.text.showValue(k) + " (accepted: archiveCutoff, crlReferences)";
|
|
400
|
+
});
|
|
401
|
+
var out = [];
|
|
402
|
+
if (spec.archiveCutoff != null) {
|
|
403
|
+
guard.time.assertEncodable(spec.archiveCutoff, _err, "ocsp/bad-input", "singleExtensions archiveCutoff");
|
|
404
|
+
out.push(b.sequence([b.oid(oid.byName("ocspArchiveCutoff")), b.octetString(b.generalizedTime(spec.archiveCutoff))]));
|
|
405
|
+
}
|
|
406
|
+
if (spec.crlReferences != null) {
|
|
407
|
+
var c = spec.crlReferences;
|
|
408
|
+
if (!c || typeof c !== "object" || Array.isArray(c) || Buffer.isBuffer(c)) {
|
|
409
|
+
throw _err("ocsp/bad-input", "singleExtensions crlReferences must be an object { crlUrl?, crlNum?, crlTime? }");
|
|
410
|
+
}
|
|
411
|
+
guard.identifier.assertKnownKeys(c, _CRL_ID_KEYS, _err, "ocsp/bad-input", function (k) {
|
|
412
|
+
return "unknown crlReferences field " + guard.text.showValue(k) + " (accepted: crlUrl, crlNum, crlTime)";
|
|
413
|
+
});
|
|
414
|
+
var fields = [];
|
|
415
|
+
if (c.crlUrl != null) {
|
|
416
|
+
if (typeof c.crlUrl !== "string" || !c.crlUrl.length) throw _err("ocsp/bad-input", "crlReferences crlUrl must be a non-empty string");
|
|
417
|
+
for (var j = 0; j < c.crlUrl.length; j++) {
|
|
418
|
+
if (c.crlUrl.charCodeAt(j) > 0x7f) throw _err("ocsp/bad-input", "crlReferences crlUrl must be 7-bit ASCII (an IA5String, RFC 6960 sec. 4.4.2)");
|
|
419
|
+
}
|
|
420
|
+
fields.push(b.explicit(0, b.ia5(c.crlUrl)));
|
|
421
|
+
}
|
|
422
|
+
if (c.crlNum != null) {
|
|
423
|
+
var num = guard.range.authoredInteger(c.crlNum, _err, "ocsp/bad-input", "crlReferences crlNum");
|
|
424
|
+
if (num < 0n) throw _err("ocsp/bad-input", "crlReferences crlNum must be non-negative (it is a cRLNumber, RFC 5280 sec. 5.2.3)");
|
|
425
|
+
fields.push(b.explicit(1, b.integer(num)));
|
|
426
|
+
}
|
|
427
|
+
if (c.crlTime != null) {
|
|
428
|
+
guard.time.assertEncodable(c.crlTime, _err, "ocsp/bad-input", "crlReferences crlTime");
|
|
429
|
+
fields.push(b.explicit(2, b.generalizedTime(c.crlTime)));
|
|
430
|
+
}
|
|
431
|
+
out.push(b.sequence([b.oid(oid.byName("ocspCrl")), b.octetString(b.sequence(fields))]));
|
|
432
|
+
}
|
|
433
|
+
return out;
|
|
434
|
+
}
|
|
435
|
+
|
|
361
436
|
function _certStatusNode(status, opts) {
|
|
362
437
|
if (status == null || status === "good") return b.contextPrimitive(0, Buffer.alloc(0));
|
|
363
438
|
if (status === "unknown") return b.contextPrimitive(2, Buffer.alloc(0));
|
|
364
439
|
if (typeof status === "object" && status.revoked != null) {
|
|
365
|
-
var ri = [b.generalizedTime(
|
|
440
|
+
var ri = [b.generalizedTime(_asEncodableDate(status.revoked, "the revocation time"))];
|
|
366
441
|
if (status.revocationReason != null) {
|
|
367
442
|
var code = typeof status.revocationReason === "number" ? status.revocationReason : REASON_CODE[guard.text.keyOf(status.revocationReason)];
|
|
368
443
|
if (code == null) throw _err("ocsp/bad-input", "unknown revocationReason " + guard.text.showValue(status.revocationReason));
|
package/lib/pki-build.js
CHANGED
|
@@ -344,7 +344,7 @@ function makeBuilder(ctx) {
|
|
|
344
344
|
function rawErr(fullCode, message, cause) { return new ErrorClass(fullCode, message, cause); }
|
|
345
345
|
|
|
346
346
|
function timeDer(date, which) {
|
|
347
|
-
guard.time.
|
|
347
|
+
guard.time.assertEncodable(date, rawErr, code("bad-input"), which);
|
|
348
348
|
var y = date.getUTCFullYear();
|
|
349
349
|
return (y >= 1950 && y <= 2049) ? b.utcTime(date) : b.generalizedTime(date);
|
|
350
350
|
}
|
package/lib/schema-crl.js
CHANGED
|
@@ -239,4 +239,9 @@ module.exports = {
|
|
|
239
239
|
pemDecode: pemDecode,
|
|
240
240
|
pemEncode: pemEncode,
|
|
241
241
|
matches: matches,
|
|
242
|
+
/** @internal The reader this parser applies to a CRL entry extension (reasonCode, invalidityDate),
|
|
243
|
+
* for a consumer that meets the same extension elsewhere: RFC 6960 sec. 4.4.5 carries every CRL
|
|
244
|
+
* entry extension into an OCSP SingleResponse, and the linter reads it with this rather than a
|
|
245
|
+
* second one. Not on the curated `pki.schema.crl` surface. */
|
|
246
|
+
decodeExtension: decodeExt,
|
|
242
247
|
};
|
package/lib/schema-ocsp.js
CHANGED
|
@@ -41,6 +41,7 @@ var constants = require("./constants");
|
|
|
41
41
|
var frameworkError = require("./framework-error");
|
|
42
42
|
var intrinsic = require("./guard-intrinsic");
|
|
43
43
|
var _hasOwn = intrinsic.hasOwn;
|
|
44
|
+
var _String = intrinsic.String;
|
|
44
45
|
|
|
45
46
|
var OcspError = frameworkError.OcspError;
|
|
46
47
|
var PemError = frameworkError.PemError;
|
|
@@ -56,6 +57,8 @@ var VERSION = pkix.versionReader(NS, {});
|
|
|
56
57
|
var OID_OCSP_BASIC = oid.byName("ocspBasic");
|
|
57
58
|
|
|
58
59
|
var OID_OCSP_NONCE = oid.byName("ocspNonce");
|
|
60
|
+
var OID_OCSP_ARCHIVE_CUTOFF = oid.byName("ocspArchiveCutoff");
|
|
61
|
+
var OID_OCSP_CRL = oid.byName("ocspCrl");
|
|
59
62
|
|
|
60
63
|
var STATUS_NAMES = constants.NAMES.OCSP_STATUS;
|
|
61
64
|
|
|
@@ -92,10 +95,69 @@ function _rawSignature(field) {
|
|
|
92
95
|
|
|
93
96
|
var CERTS = schema.seqOf(certificateBytes(), { assert: "sequence", code: "ocsp/bad-certs", what: "certs", max: constants.LIMITS.OCSP_MAX_CERTS, maxCode: "ocsp/too-many-certs" });
|
|
94
97
|
|
|
98
|
+
/** @internal RFC 6960 sec. 4.4.4: ArchiveCutoff ::= GeneralizedTime, carried as a singleExtension. */
|
|
99
|
+
function _readArchiveCutoff(ext) {
|
|
100
|
+
var node;
|
|
101
|
+
try { node = asn1.decode(ext.value); }
|
|
102
|
+
catch (e) { throw NS.E("ocsp/bad-archive-cutoff", "the archiveCutoff extension value did not decode: " + ((e && e.message) || _String(e)), e); }
|
|
103
|
+
if (!(node.tagClass === "universal" && node.tagNumber === asn1.TAGS.GENERALIZED_TIME)) {
|
|
104
|
+
throw NS.E("ocsp/bad-archive-cutoff", "the archiveCutoff extension value must be a GeneralizedTime (RFC 6960 sec. 4.4.4)");
|
|
105
|
+
}
|
|
106
|
+
try { return asn1.read.time(node); }
|
|
107
|
+
catch (e) { throw NS.E("ocsp/bad-archive-cutoff", "the archiveCutoff GeneralizedTime is malformed", e); }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** @internal RFC 6960 sec. 4.4.2: CrlID ::= SEQUENCE { crlUrl [0] EXPLICIT IA5String OPTIONAL,
|
|
111
|
+
* crlNum [1] EXPLICIT INTEGER OPTIONAL, crlTime [2] EXPLICIT GeneralizedTime OPTIONAL }. Every
|
|
112
|
+
* field is optional and each may appear at most once, in tag order. */
|
|
113
|
+
function _readCrlId(ext) {
|
|
114
|
+
var C = "ocsp/bad-crl-id";
|
|
115
|
+
var node;
|
|
116
|
+
try { node = asn1.decode(ext.value); }
|
|
117
|
+
catch (e) { throw NS.E(C, "the CRL references extension value did not decode: " + ((e && e.message) || _String(e)), e); }
|
|
118
|
+
if (!(node.tagClass === "universal" && node.tagNumber === asn1.TAGS.SEQUENCE && node.children)) {
|
|
119
|
+
throw NS.E(C, "CrlID must be a SEQUENCE (RFC 6960 sec. 4.4.2)");
|
|
120
|
+
}
|
|
121
|
+
var out = { crlUrl: null, crlNum: null, crlTime: null }, last = -1;
|
|
122
|
+
for (var i = 0; i < node.children.length; i++) {
|
|
123
|
+
var k = node.children[i];
|
|
124
|
+
if (k.tagClass !== "context" || !k.constructed || !k.children || k.children.length !== 1) {
|
|
125
|
+
throw NS.E(C, "each CrlID member must be one EXPLICIT [0], [1] or [2] tag (RFC 6960 sec. 4.4.2)");
|
|
126
|
+
}
|
|
127
|
+
if (k.tagNumber <= last) throw NS.E(C, "CrlID members must appear at most once, in tag order");
|
|
128
|
+
last = k.tagNumber;
|
|
129
|
+
var inner = k.children[0];
|
|
130
|
+
try {
|
|
131
|
+
if (k.tagNumber === 0) {
|
|
132
|
+
if (inner.tagClass !== "universal" || inner.tagNumber !== asn1.TAGS.IA5_STRING) throw NS.E(C, "crlUrl must be an IA5String");
|
|
133
|
+
out.crlUrl = asn1.read.string(inner);
|
|
134
|
+
} else if (k.tagNumber === 1) {
|
|
135
|
+
if (inner.tagClass !== "universal" || inner.tagNumber !== asn1.TAGS.INTEGER) throw NS.E(C, "crlNum must be an INTEGER");
|
|
136
|
+
out.crlNum = asn1.read.integer(inner);
|
|
137
|
+
if (out.crlNum < 0n) throw NS.E(C, "crlNum must be non-negative (it is a cRLNumber, RFC 5280 sec. 5.2.3)");
|
|
138
|
+
} else if (k.tagNumber === 2) {
|
|
139
|
+
if (inner.tagClass !== "universal" || inner.tagNumber !== asn1.TAGS.GENERALIZED_TIME) throw NS.E(C, "crlTime must be a GeneralizedTime");
|
|
140
|
+
out.crlTime = asn1.read.time(inner);
|
|
141
|
+
} else {
|
|
142
|
+
throw NS.E(C, "CrlID has no member tagged [" + k.tagNumber + "] (RFC 6960 sec. 4.4.2)");
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
if (e && e.code === C) throw e;
|
|
146
|
+
throw NS.E(C, "CrlID member [" + k.tagNumber + "] is malformed", e);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** @internal The extensions this profile reads are decoded onto their entry beside the raw value,
|
|
153
|
+
* so a consumer gets the value by name and a malformed one is refused here rather than passed
|
|
154
|
+
* through as opaque bytes. The nonce is RFC 9654; the other two are RFC 6960 sec. 4.4. */
|
|
95
155
|
function _validateOcspExtensions(list) {
|
|
96
156
|
if (!list) return list;
|
|
97
157
|
for (var i = 0; i < list.length; i++) {
|
|
98
158
|
var ext = list[i];
|
|
159
|
+
if (ext.oid === OID_OCSP_ARCHIVE_CUTOFF) { ext.archiveCutoff = _readArchiveCutoff(ext); continue; }
|
|
160
|
+
if (ext.oid === OID_OCSP_CRL) { ext.crlReferences = _readCrlId(ext); continue; }
|
|
99
161
|
if (ext.oid !== OID_OCSP_NONCE) continue;
|
|
100
162
|
var node;
|
|
101
163
|
try { node = asn1.decode(ext.value); }
|
|
@@ -235,6 +297,7 @@ var BASIC_OCSP_RESPONSE = schema.seq([
|
|
|
235
297
|
signatureAlgorithm: m.fields.signatureAlgorithm.value.result,
|
|
236
298
|
signature: _rawSignature(m.fields.signature),
|
|
237
299
|
certs: m.fields.certs.present ? m.fields.certs.value.items.map(function (it) { return it.value; }) : [],
|
|
300
|
+
certsPresent: m.fields.certs.present,
|
|
238
301
|
};
|
|
239
302
|
},
|
|
240
303
|
});
|
|
@@ -397,8 +460,10 @@ var parseRequest = pkix.makeParser({ pemLabel: "OCSP REQUEST", PemError: PemErro
|
|
|
397
460
|
* Parse a DER `Buffer` or a PEM (`OCSP RESPONSE`) string into a structured
|
|
398
461
|
* OCSPResponse: `{ responseStatus, responseBytes, basicResponse }`. For a successful
|
|
399
462
|
* basic response, `basicResponse` carries `{ tbsResponseDataBytes, responderID,
|
|
400
|
-
* producedAt, responses, signatureAlgorithm, signature, certs }`; each
|
|
401
|
-
* `responses[i].certStatus` is `{ type: "good" | "revoked" | "unknown" }`.
|
|
463
|
+
* producedAt, responses, signatureAlgorithm, signature, certs, certsPresent }`; each
|
|
464
|
+
* `responses[i].certStatus` is `{ type: "good" | "revoked" | "unknown" }`. `certs` is the
|
|
465
|
+
* embedded certificate list, empty when the field is absent, and `certsPresent` says
|
|
466
|
+
* whether the response carried the field at all. A
|
|
402
467
|
* non-successful status carries no `responseBytes`. A malformed structure throws a
|
|
403
468
|
* typed `OcspError` (`ocsp/*`); an unsupported `responseType` throws
|
|
404
469
|
* `ocsp/unsupported-response-type`.
|
|
@@ -500,4 +565,13 @@ module.exports = {
|
|
|
500
565
|
pemEncode: pemEncode,
|
|
501
566
|
matchesRequest: matchesRequest,
|
|
502
567
|
matchesResponse: matchesResponse,
|
|
568
|
+
/** @internal Reads a list of pre-encoded Extension DER the way this parser reads a SingleResponse's
|
|
569
|
+
* singleExtensions, shared with pki.ocsp.sign so an entry the signer emits is one the parser
|
|
570
|
+
* reads. Throws the parser's own ocsp/* code for a malformed entry. */
|
|
571
|
+
readSingleExtensionsDer: function (derList) {
|
|
572
|
+
var node;
|
|
573
|
+
try { node = asn1.decode(asn1.build.sequence(intrinsic.map(derList, function (d) { return asn1.build.raw(d); }))); }
|
|
574
|
+
catch (e) { throw NS.E("ocsp/bad-single-response", "a pre-encoded singleExtension is not DER", e); }
|
|
575
|
+
return _validateOcspExtensions(schema.walk(EXTENSIONS, node, NS).result);
|
|
576
|
+
},
|
|
503
577
|
};
|
package/lib/tsp-sign.js
CHANGED
|
@@ -167,7 +167,7 @@ function _sign(messageImprint, tsa, opts) {
|
|
|
167
167
|
if (!NODE_DIGEST[guard.text.keyOf(certHashAlg)]) throw _err("tsp/unsupported-algorithm", "unsupported certHashAlgorithm " + guard.text.showValue(certHashAlg));
|
|
168
168
|
|
|
169
169
|
var imprint = b.sequence([_hashAlgId(mi.hashAlgorithm), b.octetString(guard.bytes.source(mi.hashedMessage, TspError, "tsp/bad-input", "messageImprint.hashedMessage"))]);
|
|
170
|
-
if (opts.genTime != null) guard.time.
|
|
170
|
+
if (opts.genTime != null) guard.time.assertEncodable(opts.genTime, _err, "tsp/bad-input", "genTime");
|
|
171
171
|
var genTime = guard.time.isDate(opts.genTime) ? opts.genTime : new Date();
|
|
172
172
|
var serial = guard.range.authoredInteger(opts.serialNumber, _err, "tsp/bad-input", "serialNumber");
|
|
173
173
|
var fields = [b.integer(1n), _policy(opts.policy), imprint, b.integer(serial), b.generalizedTime(genTime)];
|
package/lib/x509-sign.js
CHANGED
|
@@ -504,9 +504,9 @@ function _sign(spec, issuer, opts) {
|
|
|
504
504
|
var scheme = signScheme.resolveSignScheme(_certLikeFromSpki(issuerSpki), { combinedRsaSig: true, pss: opts.pss, digestAlgorithm: opts.digestAlgorithm }, true, _signE);
|
|
505
505
|
|
|
506
506
|
var serialTlv = _serialInteger(spec.serialNumber);
|
|
507
|
-
guard.time.
|
|
508
|
-
guard.time.
|
|
509
|
-
// allow:nan-date-comparison-unguarded -- both operands are guard.time.
|
|
507
|
+
guard.time.assertEncodable(spec.notBefore, _err, "x509/bad-input", "notBefore");
|
|
508
|
+
guard.time.assertEncodable(spec.notAfter, _err, "x509/bad-input", "notAfter");
|
|
509
|
+
// allow:nan-date-comparison-unguarded -- both operands are guard.time.assertEncodable'd on the two lines above (an Invalid Date throws before this comparison).
|
|
510
510
|
if (guard.time.instantOf(spec.notBefore) > guard.time.instantOf(spec.notAfter)) throw _err("x509/bad-input", "notBefore must not be after notAfter (RFC 5280 sec. 4.1.2.5)");
|
|
511
511
|
var validityDer = b.sequence([_timeDer(spec.notBefore, "notBefore"), _timeDer(spec.notAfter, "notAfter")]);
|
|
512
512
|
|
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:4d386905-4bf6-44a7-b504-c8e9fe74646d",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-09-
|
|
8
|
+
"timestamp": "2026-09-12T03:45:28.477Z",
|
|
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.26",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "pki",
|
|
25
|
-
"version": "0.7.
|
|
25
|
+
"version": "0.7.26",
|
|
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.26",
|
|
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.26",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|