@blamejs/pki 0.6.29 → 0.6.31

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +1 -1
  3. package/lib/acme.js +8 -7
  4. package/lib/asn1-der.js +9 -7
  5. package/lib/attrcert-sign.js +8 -8
  6. package/lib/byte-reader.js +1 -1
  7. package/lib/byte-writer.js +1 -1
  8. package/lib/cmc-verify.js +4 -4
  9. package/lib/cmp-build.js +3 -3
  10. package/lib/cmp-session.js +3 -3
  11. package/lib/cmp-verify.js +2 -1
  12. package/lib/cms-verify.js +22 -17
  13. package/lib/composite-kem.js +2 -2
  14. package/lib/crl-sign.js +5 -5
  15. package/lib/crmf-sign.js +3 -3
  16. package/lib/csr-sign.js +2 -2
  17. package/lib/ct.js +3 -3
  18. package/lib/est.js +40 -8
  19. package/lib/framework-error.js +2 -2
  20. package/lib/hpke.js +2 -2
  21. package/lib/http-transport.js +61 -14
  22. package/lib/inspect.js +1 -1
  23. package/lib/jose.js +1 -1
  24. package/lib/key.js +7 -7
  25. package/lib/lint.js +1 -1
  26. package/lib/merkle.js +2 -6
  27. package/lib/mime.js +2 -2
  28. package/lib/ocsp.js +6 -6
  29. package/lib/oid.js +1 -1
  30. package/lib/path-validate.js +13 -13
  31. package/lib/pkcs12-build.js +4 -4
  32. package/lib/rfc3339.js +2 -2
  33. package/lib/scep.js +2 -2
  34. package/lib/schema-all.js +1 -1
  35. package/lib/schema-attrcert.js +1 -1
  36. package/lib/schema-cmc.js +2 -2
  37. package/lib/schema-cmp.js +8 -9
  38. package/lib/schema-cms.js +3 -3
  39. package/lib/schema-crmf.js +3 -3
  40. package/lib/schema-csr.js +1 -1
  41. package/lib/schema-csrattrs.js +1 -1
  42. package/lib/schema-engine.js +4 -4
  43. package/lib/schema-ocsp.js +1 -1
  44. package/lib/schema-pkcs12.js +2 -2
  45. package/lib/schema-pkcs8.js +2 -2
  46. package/lib/schema-smime.js +1 -1
  47. package/lib/schema-tsp.js +6 -6
  48. package/lib/schema-x509.js +2 -2
  49. package/lib/shbs.js +3 -4
  50. package/lib/sign-scheme.js +1 -1
  51. package/lib/sigstore.js +2 -2
  52. package/lib/smime.js +16 -16
  53. package/lib/tls-cert-compress.js +7 -7
  54. package/lib/trust.js +5 -5
  55. package/lib/tsp-sign.js +8 -6
  56. package/lib/webauthn.js +23 -19
  57. package/lib/webcrypto.js +3 -3
  58. package/lib/x509-sign.js +5 -5
  59. package/package.json +1 -1
  60. package/sbom.cdx.json +6 -6
package/lib/est.js CHANGED
@@ -11,15 +11,15 @@
11
11
  *
12
12
  * @intro
13
13
  * Enrollment over Secure Transport (RFC 7030, updated by RFC 8951 and RFC 9908).
14
- * The network verbs -- `cacerts`, `simpleenroll`, `simplereenroll` -- run the thin
14
+ * The network verbs (`cacerts`, `simpleenroll`, `simplereenroll`) run the thin
15
15
  * RFC 7030 client: they compose the codecs below over the shared `pki.transport`
16
16
  * (a caller MAY inject `opts.transport`; the default is a fail-closed
17
17
  * `pki.transport.https`). This module opens no socket itself: the sole socket
18
18
  * choke point is `pki.transport`, so the verbs stay a thin, fail-closed shell:
19
19
  * https-only (`est/insecure-url`), an explicit trust anchor required
20
20
  * (`est/no-trust-anchors`), same-origin redirects followed but a downgrade / loop
21
- * refused, a 202 Retry-After SURFACED and never slept, HTTP Basic answered only
22
- * after the transport authenticated the server, and the issued certificate chosen
21
+ * refused, a 202 Retry-After SURFACED and never slept, HTTP Basic or Digest answered
22
+ * only after the transport authenticated the server, and the issued certificate chosen
23
23
  * by public-key match. Under them sit the transport-agnostic codecs, validators, and
24
24
  * request builders over the shipped CMS / CSR / PKCS#8 / X.509 parsers:
25
25
  * `transferDecode` / `transferEncode` are the RFC 8951
@@ -30,9 +30,9 @@
30
30
  * `parseServerKeygenResponse` dispatches the two-part key + certificate
31
31
  * response with recipient-arm coherence; `classifyResponse` is the HTTP status
32
32
  * / content-type / Retry-After state machine (202 accepted-not-ready surfaces
33
- * `retryAfterSeconds` -- never an internal sleep; 204/404 on /csrattrs is a
33
+ * `retryAfterSeconds`, never an internal sleep; 204/404 on /csrattrs is a
34
34
  * "none available" verdict, not an error). The builders assemble the CSR
35
- * attributes EST adds -- a channel-binding challengePassword, the
35
+ * attributes EST adds: a channel-binding challengePassword, the
36
36
  * out-of-band-key identifiers, SMIMECapabilities, and the RFC 9908
37
37
  * template-priority enroll plan.
38
38
  *
@@ -536,7 +536,7 @@ var NOT_IMPLEMENTED_OPS = { fullcmc: 1 };
536
536
  *
537
537
  * Classify an EST HTTP response into a verdict or a typed fault. A 200 requires
538
538
  * the operation's exact content-type (`est/bad-content-type`); a 202 requires a
539
- * Retry-After (absent -> `est/missing-retry-after`) -- a delay-seconds value is
539
+ * Retry-After (absent -> `est/missing-retry-after`): a delay-seconds value is
540
540
  * surfaced as bounded `retryAfterSeconds`, an HTTP-date as absolute
541
541
  * `retryAfterDate` (epoch ms; `retryAfterSeconds` too when `opts.now` is given),
542
542
  * and any other value is `est/bad-retry-after` (never slept on either way);
@@ -643,6 +643,38 @@ function paths(baseUrl, opts) {
643
643
 
644
644
  function _attr(typeOid, valueNodes) { return asn1.build.sequence([asn1.build.oid(typeOid), asn1.build.set(valueNodes)]); }
645
645
 
646
+ /**
647
+ * @primitive pki.est.challengePasswordFromTlsUnique
648
+ * @signature pki.est.challengePasswordFromTlsUnique(channelBinding) -> Buffer
649
+ * @since 0.6.31
650
+ * @originated 0.1.24
651
+ * @status stable
652
+ * @spec RFC 7030, RFC 5929, RFC 2985
653
+ * @related pki.csr.sign, pki.transport.https, pki.est.simpleenroll
654
+ *
655
+ * Encode RFC 5929 tls-unique channel-binding bytes as the RFC 7030 sec. 3.5
656
+ * challengePassword, binding an enrollment request to the TLS session it is sent over.
657
+ * The returned Buffer is a DER `Attribute` (`SEQUENCE { type OID, SET { PrintableString } }`)
658
+ * carrying the base64 of the binding, for a caller assembling certification-request
659
+ * attributes directly. Empty or non-byte input is `est/bad-input`; a base64 value longer
660
+ * than 255 octets is `est/tls-unique-too-long`.
661
+ *
662
+ * To sign a channel-bound request with `pki.csr.sign`, pass the base64 string as
663
+ * `spec.challengePassword` instead: that signer builds this same attribute itself and
664
+ * REFUSES a pre-encoded challengePassword in `spec.attributes` (`csr/bad-input`), so the
665
+ * two forms are alternatives, never combined. `pki.transport.https` supplies the binding
666
+ * as `tls.tlsUnique`, and a request body given as a function receives it before the body
667
+ * is written, which is the point at which the request can still be signed over it.
668
+ *
669
+ * @example
670
+ * // the binding comes from the connection; pki.transport surfaces it as tls.tlsUnique
671
+ * var binding = Buffer.from("9f86d081884c7d65", "hex");
672
+ * var attr = pki.est.challengePasswordFromTlsUnique(binding);
673
+ * attr[0] === 0x30; // a DER Attribute SEQUENCE
674
+ * // to SIGN a channel-bound request, hand pki.csr.sign the same value as a string
675
+ * // via spec.challengePassword; it builds this identical attribute itself.
676
+ * var challengePassword = binding.toString("base64");
677
+ */
646
678
  function challengePasswordFromTlsUnique(channelBinding) {
647
679
  if (!guard.bytes.isByteSource(channelBinding)) throw E("est/bad-input", "challengePasswordFromTlsUnique requires the channel-binding bytes");
648
680
  var _cb = guard.bytes.source(channelBinding, EstError, "est/bad-input", "the channel-binding bytes");
@@ -1006,7 +1038,7 @@ function _certsResult(op, res, opts, csrSpki) {
1006
1038
  * surfaced as `issuedCertificates` (with `certificate` the first), distinct from `certificates`,
1007
1039
  * which is the whole returned bag including any chain. Where the requested keys are distinct that
1008
1040
  * list is in request order; where several requests deliberately SHARE one key it is not, and does
1009
- * not claim to be -- the public key is the only identification sec. 4.1 sanctions, so when it is
1041
+ * not claim to be: the public key is the only identification sec. 4.1 sanctions, so when it is
1010
1042
  * shared nothing in the response says which of those requests a given certificate answers. That arm reports `signatureVerified: false`: a certs-only body is
1011
1043
  * a degenerate SignedData with no signers by definition, so its security rests on the authenticated
1012
1044
  * TLS channel, not on a signature.
@@ -1434,7 +1466,7 @@ function cacerts(baseUrl, opts) {
1434
1466
  * @opts
1435
1467
  * - `transport` / `tls` / `label` / `timeout` / `maxResponseBytes` / `maxRedirects` / `proxy` / `now`, as in pki.est.cacerts.
1436
1468
  * - `strict`: reject an enroll response that carries more than the single issued certificate.
1437
- * - `username` / `password` -- HTTP Basic credentials, answered only after server authorization (empty username allowed).
1469
+ * - `username` / `password` / `auth` -- HTTP credentials: top-level `username` / `password` mean Basic; `auth` (`{ scheme: "basic" | "digest", username, password, ... }`, as in pki.est.cacerts) selects Basic or Digest. Answered only after server authorization (empty username allowed).
1438
1470
  * - `allowCrossOriginRedirect` -- opt in to following a cross-origin redirect on this POST.
1439
1471
  * @example
1440
1472
  * var req = await pki.csr.sign({ subject: "device.example", subjectPublicKey: signerSpki }, { key: signerKeyPkcs8 });
@@ -90,8 +90,8 @@ class PkiError extends Error {
90
90
  * @status stable
91
91
  * @spec internal (design: error-class factory)
92
92
  *
93
- * Factory that produces a `PkiError` subclass with the standard shape --
94
- * eliminating the per-domain boilerplate. The returned constructor takes
93
+ * Factory that produces a `PkiError` subclass with the standard shape. The
94
+ * returned constructor takes
95
95
  * `(code, message)`, stamps `name`, sets an `is<Name>` flag, and exposes
96
96
  * a `.factory` static for the common `var _err = XxxError.factory` shape.
97
97
  * The `code` must be a `domain/reason` string (the base-class contract);
package/lib/hpke.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * @nav Protocols
7
7
  * @title HPKE
8
8
  * @fullname HPKE (Hybrid Public Key Encryption, RFC 9180)
9
- * @intro Hybrid Public Key Encryption (RFC 9180) -- the standard construction
9
+ * @intro Hybrid Public Key Encryption (RFC 9180): the standard construction
10
10
  * behind TLS Encrypted Client Hello, MLS, and OHTTP that turns a recipient KEM
11
11
  * public key into an encapsulated key plus an AEAD-encrypting context. This is
12
12
  * the RFC 9180 base construction: the DHKEM suites P-256, P-521, X25519, and
@@ -358,7 +358,7 @@ var suites = {
358
358
 
359
359
  /**
360
360
  * @primitive pki.hpke.setupS
361
- * @signature pki.hpke.setupS(suiteIds, recipientPublicKey, opts?) -> { enc, context }
361
+ * @signature pki.hpke.setupS(suiteIds, recipientPublicKey, opts?) -> { enc, context, sharedSecret }
362
362
  * @since 0.2.2
363
363
  * @status stable
364
364
  * @spec RFC 9180
@@ -16,15 +16,28 @@
16
16
  * composes it (or an injected substitute) through one contract:
17
17
  * `transport(request) -> Promise<{ status, headers, body, tls }>`. The first three are
18
18
  * exactly what a message layer's classifier consumes, so no protocol semantics leak
19
- * into the socket layer -- the transport owns socket lifecycle, the TLS trust policy,
19
+ * into the socket layer: the transport owns socket lifecycle, the TLS trust policy,
20
20
  * the streaming size cap, and the timeout budget; the caller owns HTTP status,
21
21
  * content-type, redirect, and authentication decisions. `tls` reports the negotiated
22
- * channel -- `{ protocol, cipher, peerCertificate }` -- which is the one fact a caller
23
- * cannot recover from the response bytes. An INJECTED substitute should return it too:
22
+ * channel, `{ protocol, cipher, peerCertificate, tlsUnique }`, facts a caller cannot
23
+ * recover from the response bytes. `tlsUnique` is the RFC 5929 channel binding (the first
24
+ * TLS Finished) on a TLS 1.2 connection, which `pki.est.challengePasswordFromTlsUnique`
25
+ * base64-encodes into an EST challengePassword (RFC 7030 sec. 3.5); it is `null` on TLS 1.3,
26
+ * where RFC 5929 defines no tls-unique. An INJECTED substitute should return these too:
24
27
  * `pki.est.serverkeygen` asserts the negotiated cipher can protect the private key it
25
28
  * is about to accept, and a transport that reports no cipher is trusted instead of
26
29
  * refused (so a loopback test channel works), which means omitting the field silently
27
- * skips that assertion.
30
+ * skips that assertion. Because `tlsUnique` on the response arrives after the request
31
+ * body was already sent, a request `body` MAY instead be a function `(tls) -> bytes`.
32
+ * The transport invokes it once the handshake completes and before it writes the body,
33
+ * passing the same `{ protocol, cipher, peerCertificate, tlsUnique }` object, so the
34
+ * caller builds the request body (a channel-bound CSR) from `tlsUnique` on the very
35
+ * connection the request is sent over. The callback returns bytes or a string, or a
36
+ * promise of either, so the CSR can be signed with the toolkit's own asynchronous
37
+ * signer while the connection is held open. A throw, a rejection, a missing return,
38
+ * `null`, or any other value fails the request closed, so a callback that forgets to
39
+ * return cannot post an empty enrollment to a CA. An explicit empty string is an
40
+ * intentional empty body, and the request budget still bounds the whole exchange.
28
41
  *
29
42
  * `pki.transport.https(defaults?)` binds TLS + budget defaults and returns a
30
43
  * transport. Trust is EXPLICIT and fail-closed: a request is refused unless it
@@ -40,7 +53,7 @@
40
53
  * @card
41
54
  * The shared fail-closed node:https transport (est / acme / cmp): explicit trust
42
55
  * anchors, rejectUnauthorized always on, a TLS floor, a streaming response-size cap,
43
- * and a timeout -- behind one `transport(request) -> {status, headers, body, tls}` seam.
56
+ * and a timeout, behind one `transport(request) -> {status, headers, body, tls}` seam.
44
57
  */
45
58
 
46
59
  var nodeHttps = require("node:https");
@@ -80,6 +93,17 @@ function _stripIpv6Brackets(s) {
80
93
  return (s.length >= 2 && s.charAt(0) === "[" && s.charAt(s.length - 1) === "]") ? s.slice(1, s.length - 1) : s;
81
94
  }
82
95
 
96
+ function _tlsInfo(socket) {
97
+ var proto = socket && socket.getProtocol ? socket.getProtocol() : null;
98
+ var cipher = socket && socket.getCipher ? socket.getCipher() : null;
99
+ var peer = socket && socket.getPeerCertificate ? socket.getPeerCertificate() : null;
100
+ var reused = socket && socket.isSessionReused ? socket.isSessionReused() : false;
101
+ var tlsUnique = (socket && socket.getFinished && socket.getPeerFinished && proto === "TLSv1.2")
102
+ ? (reused ? socket.getPeerFinished() : socket.getFinished()) : null;
103
+ if (tlsUnique != null && tlsUnique.length === 0) tlsUnique = null;
104
+ return { protocol: proto, cipher: cipher, peerCertificate: peer && peer.raw ? peer.raw : null, tlsUnique: tlsUnique };
105
+ }
106
+
83
107
  function _pemifyAnchor(a) {
84
108
  if (typeof a === "string") return a;
85
109
  if (Buffer.isBuffer(a)) {
@@ -351,7 +375,7 @@ function _proxyErrorClass(e, C) {
351
375
  * (`transport/server-auth-failed`) all fail closed; `rejectUnauthorized` is always on.
352
376
  * A protocol client passes its own error factory (`defaults.E`) + `defaults.errPrefix`
353
377
  * to surface domain codes (`est/...`). The transport owns no HTTP/redirect/auth
354
- * semantics -- those live in the message layer that consumes the response triple.
378
+ * semantics; those live in the message layer that consumes the response triple.
355
379
  *
356
380
  * @opts
357
381
  * - `tls.anchors` -- Explicit trust anchor(s): a DER/PEM Buffer, an array, or PEM string(s) (node `ca`).
@@ -393,11 +417,14 @@ function httpsTransport(defaults) {
393
417
  if (minVersion !== "TLSv1.2" && minVersion !== "TLSv1.3") throw E(C("bad-input"), "tls.minVersion must be 'TLSv1.2' or 'TLSv1.3' (never below the floor), got " + minVersion);
394
418
 
395
419
  var body = request.body;
396
- if (guard.bytes.isByteSource(body)) body = guard.bytes.source(body, E, C("bad-input"), "the request body");
420
+ var bodyIsFn = typeof body === "function";
421
+ if (!bodyIsFn && guard.bytes.isByteSource(body)) body = guard.bytes.source(body, E, C("bad-input"), "the request body");
397
422
 
398
423
  var reqHeaders = Object.assign({}, request.headers || {});
399
424
  Object.keys(reqHeaders).forEach(function (k) { var lk = k.toLowerCase(); if (lk === "proxy-authorization" || lk === "proxy-connection") delete reqHeaders[k]; });
400
- if (body != null && body !== "") {
425
+ if (bodyIsFn) {
426
+ Object.keys(reqHeaders).forEach(function (k) { var lk = k.toLowerCase(); if (lk === "content-length" || lk === "transfer-encoding" || lk === "expect") delete reqHeaders[k]; });
427
+ } else if (body != null && body !== "") {
401
428
  Object.keys(reqHeaders).forEach(function (k) { var lk = k.toLowerCase(); if (lk === "content-length" || lk === "transfer-encoding") delete reqHeaders[k]; });
402
429
  reqHeaders["Content-Length"] = Buffer.byteLength(body);
403
430
  }
@@ -484,9 +511,7 @@ function httpsTransport(defaults) {
484
511
  function issue(options) {
485
512
  try {
486
513
  req = nodeHttps.request(options, function (res) {
487
- var proto = res.socket && res.socket.getProtocol ? res.socket.getProtocol() : null;
488
- var cipher = res.socket && res.socket.getCipher ? res.socket.getCipher() : null;
489
- var peer = res.socket && res.socket.getPeerCertificate ? res.socket.getPeerCertificate() : null;
514
+ var tlsInfo = _tlsInfo(res.socket);
490
515
  var declared = parseInt((res.headers || {})["content-length"], 10);
491
516
  if (Number.isFinite(declared) && declared > prep.maxBytes) { fail(C("response-too-large"), "the declared content-length " + declared + " exceeds the " + prep.maxBytes + "-byte cap (RFC 7030 sec. 6)"); return; }
492
517
  var buf = Buffer.allocUnsafe(0);
@@ -514,14 +539,36 @@ function httpsTransport(defaults) {
514
539
  status: res.statusCode,
515
540
  headers: lower,
516
541
  body: Buffer.from(buf.subarray(0, len)),
517
- tls: { protocol: proto, cipher: cipher, peerCertificate: peer && peer.raw ? peer.raw : null },
542
+ tls: tlsInfo,
518
543
  });
519
544
  });
520
545
  res.on("error", function (e) { fail(C("transport-error"), "the response stream failed", e); });
521
546
  });
522
547
  req.on("error", function (e) { fail(_classifyError(e, C), "the request failed: " + ((e && e.message) || String(e)), e); });
523
- if (prep.body != null && prep.body !== "") req.write(prep.body);
524
- req.end();
548
+ if (typeof prep.body === "function") {
549
+ req.once("socket", function (socket) {
550
+ function _writeBoundBody() {
551
+ if (settled) return;
552
+ var info = _tlsInfo(socket);
553
+ Promise.resolve().then(function () { return prep.body(info); }).then(function (b) {
554
+ if (settled) return;
555
+ try {
556
+ if (guard.bytes.isByteSource(b)) b = guard.bytes.source(b, E, C("bad-input"), "the channel-binding body");
557
+ else if (typeof b !== "string") { fail(C("bad-input"), "the request body callback must return bytes or a string; a missing return, null, or any other value is refused"); return; }
558
+ } catch (ve) { _settleReject(ve); return; }
559
+ try {
560
+ if (b !== "") { req.setHeader("Content-Length", Buffer.byteLength(b)); req.write(b); }
561
+ req.end();
562
+ } catch (e2) { fail(C("transport-error"), "the request body could not be written: " + ((e2 && e2.message) || String(e2)), e2); }
563
+ }, function (e) { fail(C("transport-error"), "the channel-binding body callback failed", e); });
564
+ }
565
+ if (socket.getFinished && socket.getFinished()) { _writeBoundBody(); return; }
566
+ socket.once("secureConnect", _writeBoundBody);
567
+ });
568
+ } else {
569
+ if (prep.body != null && prep.body !== "") req.write(prep.body);
570
+ req.end();
571
+ }
525
572
  } catch (e) { fail(C("transport-error"), "the request could not be initiated: " + ((e && e.message) || String(e)), e); }
526
573
  }
527
574
 
package/lib/inspect.js CHANGED
@@ -795,7 +795,7 @@ var _INSPECT_BY_FORMAT = { x509: certificate, crl: crlReport, csr: csrReport, cm
795
795
  * @related pki.schema.detectFormat, pki.inspect.certificate
796
796
  *
797
797
  * Detect which PKI format `input` (a PEM string or DER Buffer) encodes and render
798
- * it with the matching report -- the inspect analogue of `pki.schema.parse`. Routes
798
+ * it with the matching report, the inspect analogue of `pki.schema.parse`. Routes
799
799
  * a certificate / CRL / CSR / CMS to `certificate` / `crl` / `csr` / `cms`; a
800
800
  * detected but out-of-scope format (OCSP, TSP, PKCS#8/#12, CRMF, CMP, ...) throws
801
801
  * `inspect/unsupported-format` naming it, and an unrecognized input
package/lib/jose.js CHANGED
@@ -294,7 +294,7 @@ function assertPublicJwk(jwk) {
294
294
  * or the message is refused with `jose/key-mismatch`. They are compared as RFC 7638
295
295
  * thumbprints, so member order and members outside the key itself cannot make equal
296
296
  * keys look different. Without `opts.key` the embedded `jwk` is used where the
297
- * profile permits one -- which verifies that the message is internally consistent,
297
+ * profile permits one, which verifies that the message is internally consistent,
298
298
  * not that any particular signer produced it. `keySource` reports which of the two
299
299
  * answered, so a signature checked against a caller-named key is distinguishable
300
300
  * from one checked against the key the message brought with it.
package/lib/key.js CHANGED
@@ -12,7 +12,7 @@
12
12
  * `publicFromPrivate` over every algorithm the WebCrypto engine drives: RSA, EC, Ed25519/Ed448,
13
13
  * X25519/X448, and the FIPS post-quantum ML-DSA / ML-KEM. Unencrypted export / import DELEGATES to the
14
14
  * WebCrypto `exportKey` / `importKey` PKCS#8 / SPKI encoders (which already emit each algorithm's
15
- * `AlgorithmIdentifier.parameters` correctly -- RSA NULL, EC namedCurve, Ed/X ABSENT), so the wrapper
15
+ * `AlgorithmIdentifier.parameters` correctly: RSA NULL, EC namedCurve, Ed/X ABSENT), so the wrapper
16
16
  * never re-encodes an AlgorithmIdentifier. PBES2 encrypt / decrypt composes the one shared `lib/pbes2.js`
17
17
  * home (the same PBKDF2 + AES-CBC primitives `pki.cms` uses). Parsing lives at `pki.schema.pkcs8.parse`.
18
18
  * @spec RFC 5958, RFC 8018, RFC 5280
@@ -73,8 +73,8 @@ async function _toPrivateKeyDer(input) {
73
73
  * (never encrypt opaque bytes), and the produced `EncryptedPrivateKeyInfo` is re-parsed before return.
74
74
  *
75
75
  * The PBKDF2 `prf` equal to the default (`hmacWithSHA1`) is omitted from the parameters (X.690 sec. 11.5),
76
- * `keyLength` is omitted (the AES cipher OID fixes the key size), and the salt / iteration count are bounded
77
- * -- so the output is byte-exact with OpenSSL's `pkcs8 -topk8 -v2`. A bad input throws a typed `KeyError`.
76
+ * `keyLength` is omitted (the AES cipher OID fixes the key size), and the salt / iteration count are bounded,
77
+ * so the output is byte-exact with OpenSSL's `pkcs8 -topk8 -v2`. A bad input throws a typed `KeyError`.
78
78
  *
79
79
  * @opts
80
80
  * - `cipher` (string) -- `aes-256-cbc` (default), `aes-192-cbc`, or `aes-128-cbc`.
@@ -187,13 +187,13 @@ function _decryptPbes2(encAlg, ciphertext, password, opts) {
187
187
  *
188
188
  * Export an extractable `CryptoKey` to DER (or PEM): a private key as PKCS#8 `OneAsymmetricKey`, a public
189
189
  * key as SubjectPublicKeyInfo. The encoding is delegated to the WebCrypto `exportKey` PKCS#8 / SPKI encoder,
190
- * so the algorithm-specific `AlgorithmIdentifier.parameters` are byte-correct -- RSA carries an explicit
190
+ * so the algorithm-specific `AlgorithmIdentifier.parameters` are byte-correct: RSA carries an explicit
191
191
  * NULL, EC a namedCurve OID, and Ed25519 / Ed448 / X25519 / X448 omit parameters (RFC 8410 sec. 3); the
192
192
  * wrapper never re-encodes the AlgorithmIdentifier.
193
193
  *
194
194
  * The key need not have been created by this toolkit's own WebCrypto: one from the platform's, or from a
195
- * separately-installed copy of this toolkit, is exported through whichever of them holds its material,
196
- * since neither can read the other's. A key created non-extractable is refused with that as the reason,
195
+ * separately-installed copy of this toolkit, is exported through whichever of them holds its material.
196
+ * A key created non-extractable is refused with that as the reason,
197
197
  * as is one whose implementation keeps its material out of this process's reach entirely.
198
198
  *
199
199
  * @opts
@@ -231,7 +231,7 @@ async function export_(key, opts) {
231
231
  * @related pki.key.export, pki.key.decrypt
232
232
  *
233
233
  * Import a DER / PEM PKCS#8 private key, SPKI public key, or (with `opts.password`) an `ENCRYPTED PRIVATE
234
- * KEY` -- auto-detecting the structure -- into a `CryptoKey`. The WebCrypto algorithm is inferred from the
234
+ * KEY`, auto-detecting the structure, into a `CryptoKey`. The WebCrypto algorithm is inferred from the
235
235
  * key's OID for the algorithms that name exactly one (Ed25519 / Ed448 / X25519 / X448 / ML-DSA / ML-KEM /
236
236
  * SLH-DSA); RSA and EC are ambiguous between signing and key agreement, so `opts.algorithm` must be supplied
237
237
  * for them (without it the import fails closed). Default key usages follow the algorithm and key type.
package/lib/lint.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * @nav Tooling
7
7
  * @title Lint
8
8
  * @fullname Certificate linting against CA/Browser Forum requirements
9
- * @intro The certificate LINTING engine -- the zlint / pkilint of JavaScript. It walks an
9
+ * @intro The certificate LINTING engine, the zlint / pkilint of JavaScript. It walks an
10
10
  * ALREADY-PARSED certificate (from `pki.schema.x509.parse`, whose extension values it
11
11
  * decodes with the shared RFC 5280 decoders) and emits graded, advisory FINDINGS: each
12
12
  * with a stable id, a severity (`fatal` > `error` > `warn` > `notice` > `pass`), a source,
package/lib/merkle.js CHANGED
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @intro
13
13
  * RFC 6962 (Certificate Transparency) / RFC 9162 (CT 2.0) Merkle-tree hash
14
- * and proof-verification core -- the load-bearing primitive a static-CT
14
+ * and proof-verification core: the load-bearing primitive a static-CT
15
15
  * client, a Merkle-Tree-Certificates relying party, and a sigstore / Rekor
16
16
  * inclusion check all compose. Every verb is strict verification over
17
17
  * SHA-256: zero new crypto.
@@ -234,11 +234,7 @@ function verifyInclusion(opts) {
234
234
  * `merkle/no-consistency-claim`. RFC 6962 sec. 2.1.2 defines the proof for
235
235
  * `0 < oldSize < newSize`: the empty tree is a prefix of every tree by
236
236
  * definition, so there is no proof to check and nothing at all binds `newRoot`.
237
- * Returning `true` there would say a step was proven append-only when nothing had
238
- * been proven, and a monitor written `if (!verifyConsistency(...)) alarm()` would
239
- * take that silence for evidence. A caller with no prior tree has an inclusion
240
- * question about the new one, or should start from a checkpoint it already
241
- * trusts. Two empty trees are still answered:
237
+ * Two empty trees are still answered:
242
238
  * that is the degenerate identity case, and both roots must be `emptyRootHash()`.
243
239
  *
244
240
  * A malformed input throws a typed `merkle/*` error: `oldSize > newSize`, a
package/lib/mime.js CHANGED
@@ -3,11 +3,11 @@
3
3
  "use strict";
4
4
  /**
5
5
  * @internal
6
- * lib/mime.js -- a minimal MIME entity framer + canonicalizer, the message-layer engine primitive
6
+ * lib/mime.js: a minimal MIME entity framer + canonicalizer, the message-layer engine primitive
7
7
  * under pki.smime (RFC 8551 S/MIME) and any future MIME-carrying feature. It parses an entity into
8
8
  * its headers + body, canonicalizes a text entity to the RFC 8551 sec. 3.1.1 form (CRLF line endings),
9
9
  * splits a multipart body on its boundary, and builds an entity/multipart back. There is NO crypto
10
- * here -- the CMS layer signs/verifies the canonical bytes this module produces.
10
+ * here. The CMS layer signs/verifies the canonical bytes this module produces.
11
11
  *
12
12
  * The load-bearing rule is canonicalization: the detached signature over a multipart/signed first part
13
13
  * is computed over that part's canonical MIME form, so the signer and verifier MUST share one
package/lib/ocsp.js CHANGED
@@ -352,14 +352,14 @@ function _certStatusNode(status, opts) {
352
352
 
353
353
  /**
354
354
  * @primitive pki.ocsp.buildErrorResponse
355
- * @signature pki.ocsp.buildErrorResponse(status) -> Buffer | string
355
+ * @signature pki.ocsp.buildErrorResponse(status) -> Buffer
356
356
  * @since 0.2.22
357
357
  * @status stable
358
358
  * @spec RFC 6960
359
359
  * @related pki.ocsp.sign
360
360
  *
361
- * Build an UNSIGNED error OCSPResponse -- `malformedRequest` / `internalError` / `tryLater` /
362
- * `sigRequired` / `unauthorized` -- carrying only the responseStatus and no responseBytes (RFC 6960
361
+ * Build an UNSIGNED error OCSPResponse, one of `malformedRequest` / `internalError` / `tryLater` /
362
+ * `sigRequired` / `unauthorized`, carrying only the responseStatus and no responseBytes (RFC 6960
363
363
  * sec. 2.3: an error message conveys no certificate status and is not signed).
364
364
  *
365
365
  * @example
@@ -374,7 +374,7 @@ function buildErrorResponse(status) {
374
374
 
375
375
  /**
376
376
  * @primitive pki.ocsp.verify
377
- * @signature pki.ocsp.verify(response, opts) -> Promise<{ status, responderAuthorized, signatureValid, thisUpdate, nextUpdate, revocationReason?, revocationTime?, nonceMatched?, reason }>
377
+ * @signature pki.ocsp.verify(response, opts) -> Promise<{ status, responderAuthorized, signatureValid, matched, thisUpdate, nextUpdate, revocationReason?, revocationTime?, nonceMatched?, reason }>
378
378
  * @since 0.2.22
379
379
  * @status stable
380
380
  * @spec RFC 6960, RFC 9654, RFC 5019
@@ -524,9 +524,9 @@ function _signerVerdict(parsed, found, failReason) {
524
524
  * request carried (or opts.certs supplied), including intermediates that do not sign and so are absent
525
525
  * from `signerCerts`: the responder passes it as the `opts.candidates` pool to `pki.path.build`, which
526
526
  * discovers and validates the ordered path from a `signerCerts` entry (leaf) up to a trust anchor.
527
- * The responder then confirms that certificate is authorized to sign the request -- its `keyUsage`,
527
+ * The responder then confirms that certificate is authorized to sign the request: its `keyUsage`,
528
528
  * where present, must assert `digitalSignature` (RFC 5280 sec. 4.2.1.3, since the certificate signed
529
- * the request) -- and compares its subject to the `requestorName` it expects. The decoded
529
+ * the request). It also compares the certificate's subject to the `requestorName` it expects. The decoded
530
530
  * `requestList`, `requestExtensions` and `version` are
531
531
  * returned so the CertIDs being asked about need no re-parse.
532
532
  *
package/lib/oid.js CHANGED
@@ -446,7 +446,7 @@ function register(dotted, n) {
446
446
  *
447
447
  * Register a whole OID family in one call. `base` is the shared arc prefix
448
448
  * (the starting variable a class of OIDs has in common) and `members` maps
449
- * each name to its trailing arc -- a number, or a short arc array for a
449
+ * each name to its trailing arc: a number, or a short arc array for a
450
450
  * multi-level leaf. Each full OID is derived as `base` followed by the leaf,
451
451
  * so a family is declared as its hierarchy and no full path is re-spelled.
452
452
  * This is the primitive the built-in seed set itself is built from.
@@ -10,9 +10,9 @@
10
10
  * @intro
11
11
  * RFC 5280 6 certification-path validation as a pure, re-entrant algorithm
12
12
  * over already-parsed certificates. `pki.path.validate(path, opts)` runs the
13
- * 6.1 state machine -- signature chaining, validity windows, name chaining,
13
+ * 6.1 state machine (signature chaining, validity windows, name chaining,
14
14
  * basic constraints and path length, key usage, name constraints, and the
15
- * certificate-policy tree -- and returns a structured verdict with a per-check
15
+ * certificate-policy tree) and returns a structured verdict with a per-check
16
16
  * reason code for every step. Validity-window enforcement is always on, with
17
17
  * the check date an explicit input; the trust anchor is an input, never one of
18
18
  * the validated certificates, and no input object is mutated.
@@ -20,12 +20,12 @@
20
20
  * Revocation is a pluggable hook: `pki.path.crlChecker(crls)` ships a CRL
21
21
  * consultation built on `pki.schema.crl.parse`; an OCSP checker satisfies the
22
22
  * same interface. Signature verification derives its algorithm from the
23
- * certificate and the issuer key -- never from a value the message controls --
23
+ * certificate and the issuer key, never from a value the message controls,
24
24
  * and fails closed on an unknown critical extension, an undetermined
25
25
  * revocation status, or any structural fault.
26
26
  *
27
27
  * @card
28
- * RFC 5280 6 certification-path validation -- run the 6.1 state machine over
28
+ * RFC 5280 6 certification-path validation: run the 6.1 state machine over
29
29
  * an ordered path and a trust anchor for a structured, fail-closed verdict
30
30
  * with per-check reason codes. Pure and re-entrant.
31
31
  */
@@ -836,7 +836,7 @@ function validateCriticalExtensionStructure(cert) {
836
836
  * inputs (`initialExplicitPolicy`,
837
837
  * `initialAnyPolicyInhibit`, `initialPolicyMappingInhibit`,
838
838
  * `userInitialPolicySet`, and `initialPermittedSubtrees` /
839
- * `initialExcludedSubtrees` -- arrays of `{ tag, base }` where `tag` is the
839
+ * `initialExcludedSubtrees`: arrays of `{ tag, base }` where `tag` is the
840
840
  * GeneralName tag number and `base` that form's constraint value), an
841
841
  * optional `requiredEku` (key purposes the target's extendedKeyUsage must
842
842
  * assert, given as registered OID names or dotted OID strings; an absent
@@ -846,9 +846,9 @@ function validateCriticalExtensionStructure(cert) {
846
846
  * are validated at the entry point. A mis-shaped value throws `path/bad-input`,
847
847
  * so it cannot silently go unapplied. Returns `{ valid, revocationChecked, anchorConstraints,
848
848
  * path, results, workingPublicKey, workingPublicKeyAlgorithm,
849
- * workingPublicKeyParameters, validPolicyTree }` where `results[i].checks`
849
+ * workingPublicKeyParameters, validPolicyTree, userConstrainedPolicySet }` where `results[i].checks`
850
850
  * carries a per-check reason code (`path/*`) for every step. Pure and
851
- * re-entrant -- no input object is mutated. An empty path or a missing anchor
851
+ * re-entrant: no input object is mutated. An empty path or a missing anchor
852
852
  * throws a typed `PathError`.
853
853
  *
854
854
  * `valid` alone cannot say whether revocation was ever established, so
@@ -1365,7 +1365,7 @@ function selectDelta(candidates) {
1365
1365
  * (`thisUpdate`/`nextUpdate`), and reports `{ status: "good"|"revoked"|
1366
1366
  * "unknown" }`. A partitioned/sharded CRL (a critical IDP naming a
1367
1367
  * distribution point) establishes "good" when it corresponds to one of the
1368
- * certificate's own cRLDistributionPoints -- at least one identically-encoded
1368
+ * certificate's own cRLDistributionPoints: at least one identically-encoded
1369
1369
  * name in common (RFC 5280 sec. 6.3.3). Reason-sharded CRLs ACCUMULATE: each
1370
1370
  * corresponding CRL contributes its interim reason mask (sec. 6.3.3(d)) and the
1371
1371
  * certificate is "good" once the shards together cover all eight revocation
@@ -1713,21 +1713,21 @@ function ocspChecker(responses) {
1713
1713
  * directly, or a CA-issued delegate bearing both id-kp-OCSPSigning and
1714
1714
  * id-pkix-ocsp-nocheck and passing the full out-of-path certificate gates),
1715
1715
  * verifies the response signature over `tbsResponseDataBytes`, and checks
1716
- * currency (`thisUpdate`/`nextUpdate`) -- there is no weaker second OCSP verify
1716
+ * currency (`thisUpdate`/`nextUpdate`). There is no weaker second OCSP verify
1717
1717
  * path. It is fail-closed and never throws on an unauthorized, stale, or
1718
1718
  * unverifiable response: those yield `{ status: "unknown" }` with the granular
1719
1719
  * `responderAuthorized`/`signatureValid`/`matched` flags and a `reason`; a
1720
1720
  * `revoked` status surfaces its `revocationReason`. Setting `opts.historicalMode`
1721
1721
  * treats a revocation whose `revocationTime` is strictly after `time` as not-yet-
1722
- * revoked (`good`) -- for validating a signature as of a past `time`, before the
1722
+ * revoked (`good`): for validating a signature as of a past `time`, before the
1723
1723
  * certificate was later revoked; the responder certificate is still validated at
1724
1724
  * `time` either way. `time` must be a valid `Date`. A malformed response's parse
1725
1725
  * fault surfaces as the parser's typed `ocsp/*` / `asn1/*` error.
1726
1726
  *
1727
1727
  * The response is its DER bytes, a PEM string, or an unmodified
1728
1728
  * `pki.schema.ocsp.parseResponse` result. A REBUILT parsed response is refused. A
1729
- * signature check has three parts -- the signature, the algorithm that verifies it,
1730
- * and the bytes it covers -- and on a parsed object all three are separate properties:
1729
+ * signature check has three parts (the signature, the algorithm that verifies it,
1730
+ * and the bytes it covers) and on a parsed object all three are separate properties:
1731
1731
  * a genuine CA signature over a certificate that CA issued, relabeled, verifies as a
1732
1732
  * ResponseData signature for a response that never existed. The parser marks what it
1733
1733
  * returns, so those three are known to have been derived together from one byte
@@ -2285,7 +2285,7 @@ async function _fetchAiaIssuers(current, aia) {
2285
2285
  * from a certificate's Authority Information Access `caIssuers` URL (RFC 5280 sec. 4.2.2.1) over
2286
2286
  * `pki.transport`: the fetch triggers only on a pool miss, every fetched certificate is UNTRUSTED pool material
2287
2287
  * that still flows through `validate` when validation is on (never a trust anchor), and the whole surface is
2288
- * SSRF/amplification bounded -- https-only, a total fetch budget (a SILENT cap, never a throw that denies a
2288
+ * SSRF/amplification bounded: https-only, a total fetch budget (a SILENT cap, never a throw that denies a
2289
2289
  * buildable path), a per-cert URL cap, a build-wide URL dedupe, a response size + certificate-count cap, and no
2290
2290
  * redirect following; every fetch fault is a silent skip. `aiaFetches` reports how many network GETs the build
2291
2291
  * performed (`0` when `fetchAia` is off). NOTE: with `opts.validate:false` (pure-builder mode) a fetched cert is
@@ -7,7 +7,7 @@
7
7
  * @title PKCS#12
8
8
  * @fullname PKCS#12 keystores (.p12 and .pfx): build and open
9
9
  * @intro The PKCS#12 (.p12 / .pfx) producing side (RFC 7292, RFC 9579). `pki.pkcs12.build` assembles a
10
- * password-integrity PFX -- key, certificate, CRL, and secret bags (shrouded keys and cert safes encrypted
10
+ * password-integrity PFX: key, certificate, CRL, and secret bags (shrouded keys and cert safes encrypted
11
11
  * under RFC 8018 PBES2) wrapped in an AuthenticatedSafe, protected by either a classic Appendix B HMAC or
12
12
  * an RFC 9579 PBMAC1 (PBKDF2 + HMAC) MAC, over AES-128/192/256-CBC and SHA-256/384/512. Every password is
13
13
  * encoded the PKCS#12 way (BMPString + NULL, Appendix B.1), so a file it emits opens in OpenSSL and NSS.
@@ -427,7 +427,7 @@ function _normalizeSpec(spec, opts, form) {
427
427
  *
428
428
  * @opts
429
429
  * - `password` -- the shared privacy + integrity password (string / Buffer / Uint8Array).
430
- * - `mac` -- `false` for a MAC-less store, or `{ algorithm: 'hmac'(default)|'pbmac1', hash: 'sha256'(default)|'sha1'|'sha384'|'sha512', salt?, iterations? }`. `keyLength` is a `pbmac1` field: the classic Appendix B derivation produces a key at the hash's own output length, and naming one under `hmac` is refused.
430
+ * - `mac` -- `false` for a MAC-less store, or `{ algorithm: 'hmac'(default)|'pbmac1', hash: 'sha256'(default)|'sha1'|'sha384'|'sha512', salt?, iterations?, password? }`. `password` overrides the shared integrity password for the MAC. `keyLength` is a `pbmac1` field: the classic Appendix B derivation produces a key at the hash's own output length, and naming one under `hmac` is refused.
431
431
  * - `integrity` -- `{ mode: 'public-key', signer: { cert, key, digestAlgorithm?, pss? } | signers: [ ... ], sid?, signingTime?, certificates? }` for public-key integrity (a CMS SignedData authSafe over any `pki.cms.sign` signer algorithm, no MacData). Combining it with a truthy `mac` is rejected.
432
432
  * - `recipientCerts` -- (public-key privacy convenience) `[certDer|PEM, ...]`; the convenience-form cert + key are placed in one recipient-enveloped safe (a plaintext keyBag). For the full form, set per-`safeContents` `recipients: [{ cert }, ...]` -- CERTIFICATE recipients only (RSA-OAEP / ECDH / X25519 / X448 / ML-KEM, dispatched off the cert key); a password or KEK recipient is not public-key privacy and is rejected -- with an optional `contentEncryptionAlgorithm` (`aes-128|192|256-cbc`, default 256; GCM/AEAD rejected). `encrypt` (password) and `recipients` (public-key) on the same safe is rejected; privacy is independent of integrity.
433
433
  * - `pem` (boolean) -- return a PEM `PKCS12` string instead of DER.
@@ -534,7 +534,7 @@ async function _build(spec, opts) {
534
534
  * a byte range the object carries, and the parser's mark is what says that range and the store it describes
535
535
  * came from one place. `Object.assign`, spread and a JSON round-trip drop the mark. The password is BMPString+NULL encoded (RFC 7292 App. B.1), the MAC is
536
536
  * recomputed over the store's exact AuthenticatedSafe byte range (`macedBytes`) using the store's own MAC
537
- * parameters -- the classic Appendix B (ID=3) HMAC or the RFC 9579 PBMAC1 -- and constant-time-compared to
537
+ * parameters, the classic Appendix B (ID=3) HMAC or the RFC 9579 PBMAC1, and constant-time-compared to
538
538
  * the stored MAC value. The verdict's `valid` is the password match, and `macAlgorithm` (`hmac` or `pbmac1`),
539
539
  * `macAlgorithmName` (the digest / scheme, e.g. `sha1`, `sha256`), and `iterationCount` name the integrity
540
540
  * algorithm the store used, so a caller can reject a legacy SHA-1 MAC by inspecting them rather than
@@ -617,7 +617,7 @@ function _capWork(iterations, salt, opts, keyLength, hardCap) {
617
617
  * SignedData signature, per RFC 7292 sec. 4 / 5.1, so no bag from a store whose integrity check fails is trusted),
618
618
  * then decrypt every PBES2 privacy safe and pkcs8ShroudedKeyBag with the password, and every id-envelopedData
619
619
  * (public-key privacy) safe with `opts.recipientKey` (RFC 7292 sec. 3.1, via `pki.cms.decrypt`), returning a
620
- * structured bundle `{ integrityMode, macVerified, signers, keys, certs, crls, secrets }` with each private key as PKCS#8
620
+ * structured bundle `{ valid, integrityMode, macVerified, signers, keys, certs, crls, secrets }` with each private key as PKCS#8
621
621
  * `PrivateKeyInfo` DER (re-validated), each certificate / CRL / secret as raw DER, all carrying their
622
622
  * `friendlyName` / `localKeyId` for pairing. `pfx` is the store's DER `Buffer`, a PEM string, or an
623
623
  * unmodified `pki.schema.pkcs12.parse` result; a rebuilt parsed store is refused, since the bytes whose
package/lib/rfc3339.js CHANGED
@@ -3,10 +3,10 @@
3
3
  "use strict";
4
4
  /**
5
5
  * @internal
6
- * lib/rfc3339.js -- RFC 3339 date-time parsing + validation, a fail-closed engine primitive shared by
6
+ * lib/rfc3339.js: RFC 3339 date-time parsing + validation, a fail-closed engine primitive shared by
7
7
  * pki.acme (a boolean field-validator over server-supplied JSON) and pki.ct (parse a CT log-list
8
8
  * timestamp / temporal-interval bound to a comparable Date). Beyond the grammar it enforces CALENDAR
9
- * validity -- a syntactically well-formed but impossible instant (month 13, February 30, hour 25, a
9
+ * validity: a syntactically well-formed but impossible instant (month 13, February 30, hour 25, a
10
10
  * :60 leap second, a +25:00 offset) is rejected, so a downstream expiry / window comparison never runs
11
11
  * on a value JS `Date` would silently roll over or `Date.parse` would NaN. Like the byte-reader / guard
12
12
  * family, `parse` takes the caller's `(code, message) -> error` factory so every consumer keeps its own
package/lib/scep.js CHANGED
@@ -14,7 +14,7 @@
14
14
  * issued certificate) in two nested CMS layers: an inner EnvelopedData
15
15
  * (`pkcsPKIEnvelope`) that encrypts the messageData to the recipient, and an
16
16
  * outer SignedData that signs it under a set of authenticated transaction
17
- * attributes -- messageType, transactionID, pkiStatus, failInfo, and the
17
+ * attributes: messageType, transactionID, pkiStatus, failInfo, and the
18
18
  * sender/recipient nonces (RFC 8894 sec. 3). `pki.scep.build` assembles a
19
19
  * request pkiMessage (PKCSReq, RenewalReq, CertPoll, GetCert, or GetCRL) or a
20
20
  * CA-side CertRep response; `pki.scep.parse` verifies the
@@ -520,7 +520,7 @@ async function parse(bytes, opts) {
520
520
  var messageType = MESSAGE_TYPE_BY_CODE[messageTypeCode];
521
521
  if (messageType == null) throw _err("scep/bad-message-type", "unknown messageType " + JSON.stringify(messageTypeCode) + " (RFC 8894 sec. 3.2.1.2)");
522
522
  if (_PARSE_SUPPORTED[messageType] !== 1) {
523
- throw _err("scep/unsupported-message-type", "pki.scep.parse reads PKCSReq, RenewalReq, and CertRep; " + messageType + " is not read in this release");
523
+ throw _err("scep/unsupported-message-type", "pki.scep.parse reads " + Object.keys(_PARSE_SUPPORTED).join(", ") + "; " + messageType + " is not read in this release");
524
524
  }
525
525
  var out = {
526
526
  signatureValid: true, signerAuthenticated: signerAuthenticated, signerCert: signer.cert,
package/lib/schema-all.js CHANGED
@@ -153,7 +153,7 @@ var FORMATS = [
153
153
  * The names of every registered format, in detection order.
154
154
  *
155
155
  * @example
156
- * pki.schema.all(); // -> ["cms", "tsp", "crmf", "cmp", "ocsp-request", "ocsp-response", "pkcs12", "pkcs8", "csr", "attrcert", "attrcert-v1", "crl", "x509"]
156
+ * pki.schema.all(); // -> ["cms", "tsp", "crmf", "cmp", "csrattrs", "ocsp-request", "ocsp-response", "pkcs12", "pkcs8", "csr", "attrcert", "attrcert-v1", "crl", "x509"]
157
157
  */
158
158
  function all() { return FORMATS.map(function (f) { return f.name; }); }
159
159
 
@@ -11,7 +11,7 @@
11
11
  * @intro
12
12
  * X.509 Attribute Certificate handling per RFC 5755. An attribute certificate
13
13
  * binds a holder to a set of privilege attributes (role, group, clearance)
14
- * without carrying a public key -- the authorization counterpart to an identity
14
+ * without carrying a public key, the authorization counterpart to an identity
15
15
  * certificate. `parse` decodes a v2 `AttributeCertificate` into its holder,
16
16
  * issuer, validity window (real `Date`s), attributes, and extensions, reusing
17
17
  * the shared signed-envelope so the raw `tbsBytes` (the exact signed region) and