@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.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/lib/acme.js +8 -7
- package/lib/asn1-der.js +9 -7
- package/lib/attrcert-sign.js +8 -8
- package/lib/byte-reader.js +1 -1
- package/lib/byte-writer.js +1 -1
- package/lib/cmc-verify.js +4 -4
- package/lib/cmp-build.js +3 -3
- package/lib/cmp-session.js +3 -3
- package/lib/cmp-verify.js +2 -1
- package/lib/cms-verify.js +22 -17
- package/lib/composite-kem.js +2 -2
- package/lib/crl-sign.js +5 -5
- package/lib/crmf-sign.js +3 -3
- package/lib/csr-sign.js +2 -2
- package/lib/ct.js +3 -3
- package/lib/est.js +40 -8
- package/lib/framework-error.js +2 -2
- package/lib/hpke.js +2 -2
- package/lib/http-transport.js +61 -14
- package/lib/inspect.js +1 -1
- package/lib/jose.js +1 -1
- package/lib/key.js +7 -7
- package/lib/lint.js +1 -1
- package/lib/merkle.js +2 -6
- package/lib/mime.js +2 -2
- package/lib/ocsp.js +6 -6
- package/lib/oid.js +1 -1
- package/lib/path-validate.js +13 -13
- package/lib/pkcs12-build.js +4 -4
- package/lib/rfc3339.js +2 -2
- package/lib/scep.js +2 -2
- package/lib/schema-all.js +1 -1
- package/lib/schema-attrcert.js +1 -1
- package/lib/schema-cmc.js +2 -2
- package/lib/schema-cmp.js +8 -9
- package/lib/schema-cms.js +3 -3
- package/lib/schema-crmf.js +3 -3
- package/lib/schema-csr.js +1 -1
- package/lib/schema-csrattrs.js +1 -1
- package/lib/schema-engine.js +4 -4
- package/lib/schema-ocsp.js +1 -1
- package/lib/schema-pkcs12.js +2 -2
- package/lib/schema-pkcs8.js +2 -2
- package/lib/schema-smime.js +1 -1
- package/lib/schema-tsp.js +6 -6
- package/lib/schema-x509.js +2 -2
- package/lib/shbs.js +3 -4
- package/lib/sign-scheme.js +1 -1
- package/lib/sigstore.js +2 -2
- package/lib/smime.js +16 -16
- package/lib/tls-cert-compress.js +7 -7
- package/lib/trust.js +5 -5
- package/lib/tsp-sign.js +8 -6
- package/lib/webauthn.js +23 -19
- package/lib/webcrypto.js +3 -3
- package/lib/x509-sign.js +5 -5
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/schema-cmc.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* RFC 5272 CMC message-layer decoding, as updated by RFC 6402. A Full PKI
|
|
13
13
|
* Request (`PKIData`) and a Full PKI Response (`PKIResponse`) both ride inside
|
|
14
14
|
* a CMS SignedData (or AuthenticatedData) as the encapsulated content, named by
|
|
15
|
-
* the eContentType `id-cct-PKIData` / `id-cct-PKIResponse
|
|
15
|
+
* the eContentType `id-cct-PKIData` / `id-cct-PKIResponse`, so `parse` peels
|
|
16
16
|
* the CMS layer, dispatches on that content type, and decodes the message.
|
|
17
17
|
*
|
|
18
18
|
* Every body part carries a `BodyPartID`, and the identifier MUST be unique
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* unrecognized control is data, not a fault, because the rule that a server
|
|
23
23
|
* fails an unrecognized control binds the server, not the client reading a
|
|
24
24
|
* response. The status controls (`CMCStatusInfo` v1 and `CMCStatusInfoV2`) are
|
|
25
|
-
* collected in wire order
|
|
25
|
+
* collected in wire order. A response may carry several verdicts, and the
|
|
26
26
|
* ABSENCE of one means success.
|
|
27
27
|
*
|
|
28
28
|
* The `reqSequence` byte range is surfaced exactly as it appeared on the wire,
|
package/lib/schema-cmp.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* CRMF parser; response, revocation, confirmation, error, general-message,
|
|
23
23
|
* and polling arms decode structurally (an encrypted certificate's
|
|
24
24
|
* EnvelopedData decodes via the CMS parser); every other defined arm is
|
|
25
|
-
* recognized and surfaced raw
|
|
25
|
+
* recognized and surfaced raw; `nested` messages are never auto-recursed.
|
|
26
26
|
* Protection is surfaced, not verified: the exact `headerBytes` and
|
|
27
27
|
* `bodyBytes` wire slices are exposed so an external verifier reconstructs
|
|
28
28
|
* the virtual ProtectedPart `SEQUENCE { header, body }` and checks the MAC
|
|
@@ -725,7 +725,7 @@ var readName = _valueParser("Name", pkix.name(NS));
|
|
|
725
725
|
* Parse a DER `Buffer` or a PEM string into a structured PKIMessage:
|
|
726
726
|
* `{ header, headerBytes, body, bodyBytes, protection, extraCerts }`.
|
|
727
727
|
* `header` carries `pvno` (1..3), `sender` / `recipient` (validated
|
|
728
|
-
* GeneralNames
|
|
728
|
+
* GeneralNames, the anonymous NULL-DN form included), and the optional
|
|
729
729
|
* `messageTime`, `protectionAlg`, `senderKID` / `recipKID`,
|
|
730
730
|
* `transactionID`, `senderNonce` / `recipNonce`, `freeText`, and
|
|
731
731
|
* `generalInfo` (recognized id-it types value-checked: implicitConfirm is
|
|
@@ -734,14 +734,14 @@ var readName = _valueParser("Name", pkix.name(NS));
|
|
|
734
734
|
* (`ir` / `cr` / `kur` / `krr` / `ccr`) decode via the CRMF parser;
|
|
735
735
|
* `ip` / `cp` / `kup` / `ccp` decode to `{ caPubs, response }` (an encrypted
|
|
736
736
|
* certificate's EnvelopedData decodes via the CMS parser; the deprecated
|
|
737
|
-
* EncryptedValue arm and `caPubs` surface raw
|
|
737
|
+
* EncryptedValue arm and `caPubs` surface raw; the parser confers no
|
|
738
738
|
* trust); `krp` decodes to `{ status, newSigCert, caCerts, keyPairHist }`;
|
|
739
739
|
* `rr` / `rp`, `genm` / `genp`, `error`, `certConf` (an empty
|
|
740
740
|
* confirmation is the legal reject-all), and `pollReq` / `pollRep` decode
|
|
741
|
-
* structurally; `pkiconf` decodes to `null`; every other defined arm
|
|
742
|
-
* `p10cr` (feed `body.bytes` to
|
|
743
|
-
* challenge-response and announcement arms,
|
|
744
|
-
* auto-recursed)
|
|
741
|
+
* structurally; `pkiconf` decodes to `null`; every other defined arm
|
|
742
|
+
* surfaces raw with `decoded` absent: `p10cr` (feed `body.bytes` to
|
|
743
|
+
* `pki.schema.csr.parse`), the challenge-response and announcement arms,
|
|
744
|
+
* and `nested` (never auto-recursed). `certReqId` values
|
|
745
745
|
* are BigInt and accept the protocol's -1 sentinel.
|
|
746
746
|
*
|
|
747
747
|
* Protection is surfaced, not verified: `protection` carries the raw,
|
|
@@ -785,8 +785,7 @@ var parse = pkix.makeParser({
|
|
|
785
785
|
* @related pki.schema.cmp.parse
|
|
786
786
|
*
|
|
787
787
|
* Extract the DER bytes from a PEM block (default label `CMP`). CMP is
|
|
788
|
-
* wire-DER over HTTP (RFC 9811)
|
|
789
|
-
* messages that transit text channels.
|
|
788
|
+
* wire-DER over HTTP (RFC 9811).
|
|
790
789
|
*
|
|
791
790
|
* @example
|
|
792
791
|
* var pair = await pki.key.generate("Ed25519");
|
package/lib/schema-cms.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @intro
|
|
12
12
|
* CMS handling per RFC 5652 (sec. 3 ContentInfo envelope). `parse` turns a DER or PEM
|
|
13
|
-
* (`CMS`) message into a structured object and is an OID-dispatch envelope
|
|
13
|
+
* (`CMS`) message into a structured object and is an OID-dispatch envelope:
|
|
14
14
|
* ContentInfo reads its `contentType` and structurally decodes SignedData (sec. 5),
|
|
15
15
|
* EnvelopedData (sec. 6, with all five RecipientInfo kinds: key-transport,
|
|
16
16
|
* key-agreement per RFC 5753, KEK, password, and other, including the RFC 9629
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
* parse but an out-of-set element does. DER-only, fail-closed.
|
|
39
39
|
*
|
|
40
40
|
* @card
|
|
41
|
-
* Parse DER / PEM CMS (RFC 5652 / 5083 / 9629) into structured, validated fields
|
|
42
|
-
*
|
|
41
|
+
* Parse DER / PEM CMS (RFC 5652 / 5083 / 9629) into structured, validated fields:
|
|
42
|
+
* signed, enveloped, encrypted, authenticated, and auth-enveloped content;
|
|
43
43
|
* raw attribute bytes for external verification; certificates/CRLs kept raw,
|
|
44
44
|
* fail-closed.
|
|
45
45
|
*/
|
package/lib/schema-crmf.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @intro
|
|
12
12
|
* Certificate Request Message Format handling per RFC 4211. `parse` decodes a
|
|
13
|
-
* `CertReqMessages
|
|
13
|
+
* `CertReqMessages`, the request body CMP and EST enrollment carry, into an
|
|
14
14
|
* array of messages, each with its `CertRequest` (certReqId, a `CertTemplate`
|
|
15
15
|
* of the requested certificate fields, and any registration controls), an
|
|
16
16
|
* optional proof-of-possession, and optional registration info.
|
|
@@ -327,7 +327,7 @@ var CERT_REQ_MESSAGES = schema.seqOf(CERT_REQ_MSG, {
|
|
|
327
327
|
* surfaced. `popo` is
|
|
328
328
|
* `null`, `{ type: "raVerified" }`, `{ type: "signature", poposkInput,
|
|
329
329
|
* algorithmIdentifier, signature }`, or `{ type: "keyEncipherment" |
|
|
330
|
-
* "keyAgreement", method, bytes }` (where `method` is the POPOPrivKey alternative
|
|
330
|
+
* "keyAgreement", method, bytes }` (where `method` is the POPOPrivKey alternative:
|
|
331
331
|
* `thisMessage` / `subsequentMessage` / `dhMAC` / `agreeMAC` / `encryptedKey`, each
|
|
332
332
|
* structurally validated, the `encryptedKey` EnvelopedData included). When present, `poposkInput` is
|
|
333
333
|
* `{ bytes, signedBytes, publicKey }`, where `bytes` is the raw wire `[0]` TLV,
|
|
@@ -385,7 +385,7 @@ function pemDecode(text, label) { return pkix.pemDecode(text, label || null, Pem
|
|
|
385
385
|
* @related pki.schema.crmf.pemDecode
|
|
386
386
|
*
|
|
387
387
|
* Wrap DER bytes in a PEM envelope. RFC 4211 registers no RFC 7468 label, so
|
|
388
|
-
* `label` is REQUIRED
|
|
388
|
+
* `label` is REQUIRED: the operator names the envelope explicitly (mirroring
|
|
389
389
|
* `pemDecode`, which accepts any label). Omitting it throws `pem/bad-label`.
|
|
390
390
|
*
|
|
391
391
|
* @example
|
package/lib/schema-csr.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* A CSR is self-signed only in the sense that the requester proves possession of
|
|
22
22
|
* the private key; unlike a certificate or CRL there is no inner signature
|
|
23
23
|
* algorithm to agree with, the subject MAY be empty, and the attribute set has
|
|
24
|
-
* no uniqueness constraint
|
|
24
|
+
* no uniqueness constraint: the parser deliberately omits those three
|
|
25
25
|
* certificate/CRL guards.
|
|
26
26
|
*
|
|
27
27
|
* @card
|
package/lib/schema-csrattrs.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* and `id-aa-certificationRequestInfoTemplate` -> a fully-decoded `template`.
|
|
25
25
|
*
|
|
26
26
|
* Structure is strict-DER throughout, but UNKNOWN OIDs and attribute types
|
|
27
|
-
* are TOLERATED
|
|
27
|
+
* are TOLERATED: surfaced raw, never a parse fault ("the client MUST ignore
|
|
28
28
|
* any OID or attribute it does not recognize", RFC 8951 sec. 4.5.2). The
|
|
29
29
|
* RFC 9908 semantic MUSTs that ARE enforced fail closed with a typed
|
|
30
30
|
* `csrattrs/*` code: at most one `id-ExtensionReq` attribute, its values a SET
|
package/lib/schema-engine.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @order 60
|
|
10
10
|
*
|
|
11
11
|
* @intro
|
|
12
|
-
* L2 of the ASN.1 stack
|
|
12
|
+
* L2 of the ASN.1 stack: a declarative structure-schema engine. A schema is
|
|
13
13
|
* plain data (`{kind, ...}` descriptors built by the combinators here) and
|
|
14
14
|
* `walk(schema, node, ctx)` interprets it against a decoded DER node. The
|
|
15
15
|
* engine is where every cross-cutting structural rule lives ONCE: the shape
|
|
@@ -179,7 +179,7 @@ function implicitSeqOf(tag, item, opts) {
|
|
|
179
179
|
* Interpret a declarative schema against a decoded DER node, enforcing the
|
|
180
180
|
* schema's structural rules (shape assertion, arity, optional / context-tagged
|
|
181
181
|
* fields in increasing tag order, SET-OF uniqueness) and returning the built
|
|
182
|
-
* value
|
|
182
|
+
* value, or the match tree (`{ node, fields | items }`, with the build output
|
|
183
183
|
* on `.result`) for a structure with no build fn. `ctx = { E, prefix, oid }`
|
|
184
184
|
* supplies the typed-error constructor, the error-code family prefix, and the
|
|
185
185
|
* OID registry a build fn resolves names through.
|
|
@@ -464,8 +464,8 @@ function _encodeChoice(schema, value, ctx) {
|
|
|
464
464
|
* @related pki.schema.engine.walk, pki.asn1.decode
|
|
465
465
|
*
|
|
466
466
|
* Decode a fresh DER (or, with `ber: true`, BER) blob carried inside an
|
|
467
|
-
* already-decoded value
|
|
468
|
-
* structure
|
|
467
|
+
* already-decoded value (an OCTET STRING whose content is itself an encoded
|
|
468
|
+
* structure) and walk it against a schema. A codec failure is wrapped in the
|
|
469
469
|
* caller's typed `code`; a schema rejection keeps its own code. This is the
|
|
470
470
|
* one named form of the re-decode idiom, so the caps that a fresh
|
|
471
471
|
* `pki.asn1.decode` would restart from zero can be carried across re-decode
|
package/lib/schema-ocsp.js
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*
|
|
30
30
|
* @card
|
|
31
31
|
* Parse DER / PEM OCSP requests and responses (RFC 6960) into structured,
|
|
32
|
-
* validated fields
|
|
32
|
+
* validated fields: per-certificate status, responder identity, raw tbs bytes for
|
|
33
33
|
* external verification, certificates kept raw, fail-closed.
|
|
34
34
|
*/
|
|
35
35
|
|
package/lib/schema-pkcs12.js
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* MAC-less store surfaces `integrityMode: "none"` for the caller's policy
|
|
28
28
|
* to judge. RFC 7292
|
|
29
29
|
* sec. 4.1 encodes content in BER, so parsing this one format accepts exactly
|
|
30
|
-
* two BER shapes
|
|
30
|
+
* two BER shapes (indefinite lengths and constructed OCTET STRINGs)
|
|
31
31
|
* anywhere in the store; every other strictness verdict, and every other
|
|
32
32
|
* format, stays strict DER, fail-closed.
|
|
33
33
|
*
|
|
@@ -406,7 +406,7 @@ function _buildBag(rec, state, ctx) {
|
|
|
406
406
|
* Parse a DER / BER `Buffer` or a PEM string into a structured PFX:
|
|
407
407
|
* `{ version, integrityMode, mac, macedBytes, authSafeSigned, safeBags,
|
|
408
408
|
* encryptedSafes }`. `integrityMode` is `"password"` (id-data authSafe with
|
|
409
|
-
* MacData
|
|
409
|
+
* MacData: `mac` carries `{ kind, hashOid, hashName, hashParameters,
|
|
410
410
|
* pbmac1, macValue, macSalt, iterations }`, where `kind` distinguishes the
|
|
411
411
|
* RFC 9579 PBMAC1 arm; for PBMAC1 the required parameters are validated and
|
|
412
412
|
* decoded onto `pbmac1` (`{ kdf: { salt, iterationCount, keyLength, prfOid,
|
package/lib/schema-pkcs8.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* A PKCS#8 key is a container, not a signed structure: it has no signature, no
|
|
21
21
|
* distinguished name, and no to-be-signed region. The private-key OCTET STRING
|
|
22
|
-
* content is kept raw
|
|
22
|
+
* content is kept raw: the algorithm-specific inner key (an RSAPrivateKey, an
|
|
23
23
|
* ECPrivateKey, a CurvePrivateKey) is decoded by the caller using the surfaced
|
|
24
24
|
* algorithm OID, so an unknown or future key type never fails the parse. An
|
|
25
25
|
* `ENCRYPTED PRIVATE KEY` (EncryptedPrivateKeyInfo, RFC 5958 sec. 3) is recognized
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
*
|
|
29
29
|
* @card
|
|
30
30
|
* Parse DER / PEM PKCS#8 private keys (RFC 5208 / 5958) into structured,
|
|
31
|
-
* validated fields
|
|
31
|
+
* validated fields: algorithm, raw key bytes, attributes, optional public key,
|
|
32
32
|
* fail-closed. Encrypted keys are recognized, not decrypted.
|
|
33
33
|
*/
|
|
34
34
|
|
package/lib/schema-smime.js
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
*
|
|
38
38
|
* @card
|
|
39
39
|
* Decode RFC 5035 ESS SigningCertificate / SigningCertificateV2 and RFC 8551
|
|
40
|
-
* SMIMECapabilities signed-attribute values
|
|
40
|
+
* SMIMECapabilities signed-attribute values: cert-hash binding, validated
|
|
41
41
|
* issuer GeneralNames, ordered capability list, OID-dispatched, fail-closed.
|
|
42
42
|
*/
|
|
43
43
|
|
package/lib/schema-tsp.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @intro
|
|
13
13
|
* RFC 3161 Time-Stamp Protocol handling. A `TimeStampResp` is what a client
|
|
14
|
-
* receives from a TSA
|
|
14
|
+
* receives from a TSA: a `PKIStatusInfo` plus, on success, a `TimeStampToken`;
|
|
15
15
|
* `parse` decodes it and enforces the status-to-token coupling (a granted
|
|
16
16
|
* response carries a token, a rejection does not). A `TimeStampToken` is itself a
|
|
17
17
|
* CMS SignedData whose encapsulated content is a `TSTInfo`, so `parseToken`
|
|
@@ -279,8 +279,8 @@ var parseRequest = pkix.makeParser({ pemLabel: null, PemError: PemError, ErrorCl
|
|
|
279
279
|
* @spec RFC 3161
|
|
280
280
|
* @related pki.schema.tsp.parseToken, pki.schema.tsp.parse
|
|
281
281
|
*
|
|
282
|
-
* Parse a bare `TSTInfo` payload (a DER `Buffer
|
|
283
|
-
* encapsulates
|
|
282
|
+
* Parse a bare `TSTInfo` payload (a DER `Buffer`, the structure a timestamp token
|
|
283
|
+
* encapsulates) into `{ version, policy, messageImprint, serialNumber, genTime,
|
|
284
284
|
* accuracy, ordering, nonce, tsa, extensions }`. `messageImprint.hashedMessage` is
|
|
285
285
|
* the raw digest; `serialNumber` / `nonce` are lossless (BigInt + hex); `genTime` is
|
|
286
286
|
* a `Date` with sub-second precision. A malformed structure throws a typed
|
|
@@ -312,7 +312,7 @@ var parseTstInfo = pkix.makeParser({ pemLabel: null, PemError: PemError, ErrorCl
|
|
|
312
312
|
*
|
|
313
313
|
* Parse a DER `Buffer` or a PEM string into a `TimeStampResp`: `{ status,
|
|
314
314
|
* statusString, failInfo, timeStampToken }`. The status-to-token coupling is
|
|
315
|
-
* enforced
|
|
315
|
+
* enforced: a granted response (status 0/1) carries `timeStampToken` (surfaced raw
|
|
316
316
|
* for `parseToken`), any other status does not. `failInfo` decodes the
|
|
317
317
|
* `PKIFailureInfo` named bits. A malformed structure throws a typed `TspError`.
|
|
318
318
|
*
|
|
@@ -340,7 +340,7 @@ var parse = pkix.makeParser({ pemLabel: null, PemError: PemError, ErrorClass: Ts
|
|
|
340
340
|
* @spec RFC 3161, RFC 5652
|
|
341
341
|
* @related pki.schema.tsp.parse, pki.schema.cms.parse
|
|
342
342
|
*
|
|
343
|
-
* Parse a `TimeStampToken` (a DER `Buffer` or PEM)
|
|
343
|
+
* Parse a `TimeStampToken` (a DER `Buffer` or PEM): a CMS SignedData whose
|
|
344
344
|
* encapsulated content is a `TSTInfo`. Composes `pki.schema.cms.parse`, asserts the
|
|
345
345
|
* `id-ct-TSTInfo` content type (`tsp/wrong-econtent-type`), that the content is
|
|
346
346
|
* attached (`tsp/detached-token`), the single-signer rule (`tsp/multi-signer`,
|
|
@@ -434,7 +434,7 @@ function pemDecode(text, label) { return pkix.pemDecode(text, label || null, Pem
|
|
|
434
434
|
* @related pki.schema.tsp.pemDecode
|
|
435
435
|
*
|
|
436
436
|
* Wrap DER bytes in a PEM envelope. RFC 3161 defines no standard PEM label, so
|
|
437
|
-
* `label` is REQUIRED
|
|
437
|
+
* `label` is REQUIRED: the operator names the envelope explicitly (mirroring
|
|
438
438
|
* `pemDecode`, which accepts any label). Omitting it throws `pem/bad-label`.
|
|
439
439
|
*
|
|
440
440
|
* @example
|
package/lib/schema-x509.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @intro
|
|
14
14
|
* X.509 certificate handling per RFC 5280. The seed surface is
|
|
15
|
-
* `parse
|
|
15
|
+
* `parse`, which turns a DER or PEM certificate into a structured,
|
|
16
16
|
* fully-decoded object: version, serial, signature algorithm, issuer
|
|
17
17
|
* and subject distinguished names, validity window (as real `Date`s),
|
|
18
18
|
* subject public-key info, and the extension list. The parser composes
|
|
@@ -49,7 +49,7 @@ var PemError = frameworkError.PemError;
|
|
|
49
49
|
* @related pki.schema.x509.pemEncode
|
|
50
50
|
*
|
|
51
51
|
* Extract the DER bytes from a PEM block (default label `CERTIFICATE`, the
|
|
52
|
-
* RFC 7468 sec. 5 armor
|
|
52
|
+
* RFC 7468 sec. 5 armor, the canonical-label default every sibling format
|
|
53
53
|
* applies). Pass a `label` to enforce a different block type, or an explicit
|
|
54
54
|
* `null` to take the first block of any type. Throws `PemError` on a
|
|
55
55
|
* missing / mismatched envelope or a non-base64 body.
|
package/lib/shbs.js
CHANGED
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
* @nav Signatures
|
|
7
7
|
* @title Stateful hash-based
|
|
8
8
|
* @fullname Stateful hash-based signatures: LMS and XMSS
|
|
9
|
-
* @intro Stateful hash-based signature VERIFICATION
|
|
9
|
+
* @intro Stateful hash-based signature VERIFICATION: HSS/LMS (RFC 8554),
|
|
10
10
|
* carried in X.509 by RFC 9802 and in CMS by RFC 9708, profiled by NIST
|
|
11
|
-
* SP 800-208. Verify only
|
|
12
|
-
* is catastrophic to get wrong. Each one-time key must be used exactly once,
|
|
11
|
+
* SP 800-208. Verify only. Each one-time key must be used exactly once,
|
|
13
12
|
* so the private key embeds a monotonic index whose state must advance and
|
|
14
13
|
* persist atomically across every signature and every process restart. A single
|
|
15
14
|
* index reuse (a restored VM snapshot, a crashed writer, a concurrent signer)
|
|
@@ -222,7 +221,7 @@ function _asBytes(x, label) { return guard.bytes.source(x, ShbsError, "shbs/bad-
|
|
|
222
221
|
* @related pki.shbs.verifyLms
|
|
223
222
|
*
|
|
224
223
|
* Verify an HSS (Hierarchical Signature System) signature over `message` under
|
|
225
|
-
* `publicKey
|
|
224
|
+
* `publicKey`, the wire form RFC 9802 (X.509) and RFC 9708 (CMS) carry for
|
|
226
225
|
* `id-alg-hss-lms-hashsig`. The public key and signature are the raw HSS octet
|
|
227
226
|
* blobs the certificate / CMS parsers already surface (no ASN.1 wrapping). Every
|
|
228
227
|
* level of the hierarchy must verify: a single failing level yields false.
|
package/lib/sign-scheme.js
CHANGED
|
@@ -46,7 +46,7 @@ var MLDSA_SUITABLE_DIGEST = {
|
|
|
46
46
|
"ML-DSA-65": { sha384: 1, sha512: 1, shake256: 1 },
|
|
47
47
|
"ML-DSA-87": { sha512: 1, shake256: 1 },
|
|
48
48
|
};
|
|
49
|
-
// @enforced-by behavioral -- an own-property table read has no rename-proof shape distinct from a
|
|
49
|
+
// @enforced-by behavioral -- an own-property table read has no rename-proof shape distinct from a legitimate lookup, so a RED conformance vector is the guard
|
|
50
50
|
function mldsaDigestSuitable(mlName, md) {
|
|
51
51
|
if (!intrinsic.hasOwn(MLDSA_SUITABLE_DIGEST, mlName)) return false;
|
|
52
52
|
var row = MLDSA_SUITABLE_DIGEST[mlName];
|
package/lib/sigstore.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* ephemeral, ~10 minutes); the Rekor inclusion proof folded to a Rekor-signed
|
|
18
18
|
* tree root; the log entry binding to this exact signature; and the in-toto
|
|
19
19
|
* subject digest the caller confirms against the published artifact. Verify-only
|
|
20
|
-
* and offline
|
|
20
|
+
* and offline: every input is in the bundle or a caller argument. Reuses the
|
|
21
21
|
* shipped X.509 parser, RFC 5280 path validator, RFC 9162 Merkle verifier, and
|
|
22
22
|
* native crypto engine; the net-new codecs are the DSSE PAE byte-builder and a
|
|
23
23
|
* fail-closed JSON bundle reader.
|
|
@@ -102,7 +102,7 @@ function _jsonParse(input, code, label) {
|
|
|
102
102
|
* LEN(body) SP body`, where `LEN` is the ASCII-decimal byte length (no leading
|
|
103
103
|
* zeros) and `type` is the UTF-8 `payloadType`. This is the exact preimage a DSSE
|
|
104
104
|
* signature covers; `LEN` is over the decoded body byte length, never the base64
|
|
105
|
-
* length
|
|
105
|
+
* length. Any deviation is a signature-verify bypass.
|
|
106
106
|
*
|
|
107
107
|
* @example
|
|
108
108
|
* var b = pki.sigstore.pae("application/vnd.in-toto+json", Buffer.from("{}"));
|
package/lib/smime.js
CHANGED
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
* @intro
|
|
13
13
|
* RFC 8551 S/MIME assembly + verification + encryption over the shipped CMS
|
|
14
14
|
* layer. `sign` wraps a MIME entity as a signed S/MIME message and `verify`
|
|
15
|
-
* unwraps and verifies one, in both forms: `multipart/signed` (clear-signed
|
|
15
|
+
* unwraps and verifies one, in both forms: `multipart/signed` (clear-signed:
|
|
16
16
|
* the content stays readable, a detached CMS signature rides alongside) and
|
|
17
17
|
* `application/pkcs7-mime` (opaque, where the whole entity is a base64 CMS
|
|
18
18
|
* SignedData). `encrypt` envelopes a MIME entity as an opaque
|
|
19
|
-
* `application/pkcs7-mime` message and `decrypt` opens one
|
|
19
|
+
* `application/pkcs7-mime` message and `decrypt` opens one: `authEnveloped-data`
|
|
20
20
|
* (AES-GCM, confidentiality AND integrity, the default) or `enveloped-data`
|
|
21
21
|
* (AES-CBC, confidentiality only, so `decrypt` surfaces `authenticated:false`,
|
|
22
22
|
* the EFAIL / RFC 8551 sec. 3.3 no-integrity caveat). The crypto is entirely
|
|
@@ -469,7 +469,7 @@ function _base64Body(der) {
|
|
|
469
469
|
* Assemble a signed S/MIME message (RFC 8551). `content` is the payload: a raw body wrapped as a
|
|
470
470
|
* `text/plain` entity by default, or the caller's own complete MIME entity when `opts.entity` is set;
|
|
471
471
|
* `signers` is the `pki.cms.sign` signer array (any RSA / RSASSA-PSS / ECDSA / EdDSA / ML-DSA / SLH-DSA
|
|
472
|
-
* signer
|
|
472
|
+
* signer: the S/MIME layer is algorithm-agnostic). Two forms via `opts.form`:
|
|
473
473
|
* - `"multipart"` (default, clear-signed): a `multipart/signed` message carrying the canonical entity
|
|
474
474
|
* verbatim in the first part and a DETACHED CMS SignedData (`application/pkcs7-signature`) over its
|
|
475
475
|
* canonical form in the second, with `protocol="application/pkcs7-signature"` + a matching `micalg`.
|
|
@@ -490,7 +490,7 @@ function _base64Body(der) {
|
|
|
490
490
|
* @opts hcp the Header Confidentiality Policy applied to the OUTER display copies: `"hcp_baseline"` (default) or `"hcp_no_confidentiality"`. A signed message's payload is not encrypted, so this governs presentation, not secrecy; used with `protectHeaders`.
|
|
491
491
|
* @opts sid forwarded to cms.sign: the SignerIdentifier form, `"issuerAndSerial"` (default) or `"subjectKeyIdentifier"`.
|
|
492
492
|
* @opts signedAttributes forwarded: `false` omits the signed-attributes set entirely (a bare-signature SignedData).
|
|
493
|
-
* @opts additionalSignedAttributes forwarded: extra signed attributes to carry, as `[{
|
|
493
|
+
* @opts additionalSignedAttributes forwarded: extra signed attributes to carry, as `[{ type, values }]`.
|
|
494
494
|
* @example
|
|
495
495
|
* var pair = await pki.key.generate("Ed25519");
|
|
496
496
|
* var signerKeyPkcs8 = await pki.key.export(pair.privateKey);
|
|
@@ -547,7 +547,7 @@ function _capped(msg) {
|
|
|
547
547
|
*
|
|
548
548
|
* `valid` and `trusted` are separate claims, exactly as in `cms.verify`: a SignedData carries its own
|
|
549
549
|
* certificates, so `valid` says the signature is sound under one of them and nothing about who signed.
|
|
550
|
-
* Name the roots you accept in `opts.trustAnchors` and `trusted` says every signer chained to one
|
|
550
|
+
* Name the roots you accept in `opts.trustAnchors` and `trusted` says every signer chained to one,
|
|
551
551
|
* validated for EMAIL, at both ends of the chain. The signer certificate must carry the
|
|
552
552
|
* `emailProtection` key purpose (RFC 8551 sec. 4.4.4), because a certificate restricted to `serverAuth`
|
|
553
553
|
* chains to its root perfectly well and is still the wrong key to have signed a message; and the anchor's
|
|
@@ -557,8 +557,8 @@ function _capped(msg) {
|
|
|
557
557
|
* A `micalg`
|
|
558
558
|
* that disagrees with the actual digest is advisory unless `opts.strictMicalg` (then `smime/micalg-mismatch`).
|
|
559
559
|
* If the message is header-protected (RFC 9788), `protectedHeaders` is the AUTHENTICATED inner header set (a
|
|
560
|
-
* tampered outer header cannot alter it) and `headerProtection` is `{ present, mode, fromMismatch, confidential, legacy }
|
|
561
|
-
*
|
|
560
|
+
* tampered outer header cannot alter it) and `headerProtection` is `{ present, mode, fromMismatch, confidential, legacy }`.
|
|
561
|
+
* `present` is `true` only for cryptographically-DECLARED (`hp=`) protection you may trust; `fromMismatch` is
|
|
562
562
|
* `true` when the outer From differs from the protected one, `false` when they agree, and `null` when there was
|
|
563
563
|
* no protected From to compare against, which is every message without header protection. Test it against
|
|
564
564
|
* `false` rather than for falsiness: `!fromMismatch` treats the unanswered case as a passed check, and that is
|
|
@@ -569,7 +569,7 @@ function _capped(msg) {
|
|
|
569
569
|
* whose declared `hp` is malformed, invalid, or contradicts the envelope fails closed (`smime/bad-header-protection`),
|
|
570
570
|
* never a silent downgrade. `legacy` is `null` unless `opts.legacyHeaderProtection` detected a legacy RFC 8551
|
|
571
571
|
* `message/rfc822` wrap (see that option), in which case it is its own `{ headers, mode, fromMismatch, confidential }`
|
|
572
|
-
* object (`headers` an ordered `[{ name, value }]` array that retains legally-repeated fields like `Received`)
|
|
572
|
+
* object (`headers` an ordered `[{ name, value }]` array that retains legally-repeated fields like `Received`). A
|
|
573
573
|
* legacy inference is never placed in `protectedHeaders` and never sets `present: true`, because it is
|
|
574
574
|
* indistinguishable from an ordinary forwarded `message/rfc822`, so a caller keying trust off `present` /
|
|
575
575
|
* `protectedHeaders` cannot mistake the opt-in heuristic for authenticated headers.
|
|
@@ -582,12 +582,12 @@ function _capped(msg) {
|
|
|
582
582
|
* extension carries none, from the subject DN's PKCS #9 `emailAddress` attribute, which RFC 8550 sec. 3
|
|
583
583
|
* requires a receiving agent to recognize. Where both are present the extension wins. Only a signer
|
|
584
584
|
* whose signature verified contributes an identity, so a tampered message cannot report a binding. `match` is THREE-valued and a caller enforcing sender binding tests
|
|
585
|
-
* `match === true
|
|
585
|
+
* `match === true`; `false` means every identity was comparable and none matched, and `null` means the
|
|
586
586
|
* question was not answered (no `expectedSender` and no single outer `From`, a signer certificate
|
|
587
587
|
* asserting no readable email identity, or an internationalized address needing an IDNA transform this
|
|
588
588
|
* toolkit does not perform). `null` is not a pass. `sender.identities` lists what the certificate
|
|
589
589
|
* actually asserts, `sender.checked` whether a comparison ran, and `sender.source` which input it ran
|
|
590
|
-
* against
|
|
590
|
+
* against. `"from"` is ADVISORY, because on a message without header protection the outer From is
|
|
591
591
|
* attacker-controlled.
|
|
592
592
|
*
|
|
593
593
|
* @opts certs extra signer certificates (DER `Buffer`s) to match, forwarded to `cms.verify`.
|
|
@@ -687,7 +687,7 @@ function _cmsEncryptOpts(opts) {
|
|
|
687
687
|
* @related pki.smime.decrypt, pki.cms.encrypt
|
|
688
688
|
*
|
|
689
689
|
* Envelope a MIME entity as an encrypted S/MIME message (RFC 8551 sec. 3.3 / sec. 3.4). `content` is the
|
|
690
|
-
* payload
|
|
690
|
+
* payload: a raw body wrapped as a `text/plain` entity by default, or the caller's own complete MIME
|
|
691
691
|
* entity when `opts.entity` is set; `recipients` is the `pki.cms.encrypt` recipient array (any RSA-OAEP
|
|
692
692
|
* ktri / EC or X25519/X448 kari / ML-KEM ori-KEM / password pwri / kek kekri: the S/MIME layer is
|
|
693
693
|
* recipient-agnostic; a single descriptor is accepted and normalized to a one-element array). Enveloping
|
|
@@ -697,7 +697,7 @@ function _cmsEncryptOpts(opts) {
|
|
|
697
697
|
* with `smime-type=enveloped-data` (confidentiality only, no integrity, RFC 8551 sec. 3.3). With
|
|
698
698
|
* `opts.protectHeaders`, the message is header-protected (RFC 9788): the real `opts.headers` are inlined
|
|
699
699
|
* inside the ciphertext (the payload Content-Type gains `hp="cipher"`), and only the Header-Confidentiality-
|
|
700
|
-
* Policy-processed display copies appear outside
|
|
700
|
+
* Policy-processed display copies appear outside. The default `hcp_baseline` obscures Subject to `[...]`
|
|
701
701
|
* and removes Comments / Keywords, so those values live only in the ciphertext; `decrypt` recovers the real
|
|
702
702
|
* inner set. Returns the assembled message bytes. Fail-closed with `SmimeError`.
|
|
703
703
|
*
|
|
@@ -740,7 +740,7 @@ async function encrypt(content, recipients, opts) {
|
|
|
740
740
|
* @spec RFC 8551, RFC 5652, RFC 5083, RFC 9788
|
|
741
741
|
* @related pki.smime.encrypt, pki.cms.decrypt, pki.smime.verify
|
|
742
742
|
*
|
|
743
|
-
* Open an encrypted S/MIME message (RFC 8551 sec. 3.3 / sec. 3.4)
|
|
743
|
+
* Open an encrypted S/MIME message (RFC 8551 sec. 3.3 / sec. 3.4), an `application/pkcs7-mime` entity
|
|
744
744
|
* whose base64 body is a CMS EnvelopedData or AuthEnvelopedData. `keyMaterial` is the `pki.cms.decrypt`
|
|
745
745
|
* key material (`{ key, cert }`, `{ password }`, or `{ kek, kekId? }`). Returns the recovered inner MIME
|
|
746
746
|
* entity as `content`, the `smimeType`, `authenticated` (true only for AuthEnvelopedData; a CBC
|
|
@@ -753,7 +753,7 @@ async function encrypt(content, recipients, opts) {
|
|
|
753
753
|
* (RFC 9788, `hp="cipher"`), `protectedHeaders` is the recovered real inner header set (the values the outer
|
|
754
754
|
* Header Confidentiality Policy hid) and `headerProtection` is `{ present, mode, fromMismatch, confidential, legacy }`,
|
|
755
755
|
* where `present` is `true` only for a declared `hp=` payload, and `confidential` names the fields the composer
|
|
756
|
-
* kept end-to-end confidential (via the authenticated HP-Outer records, RFC 9788 sec. 4.3)
|
|
756
|
+
* kept end-to-end confidential (via the authenticated HP-Outer records, RFC 9788 sec. 4.3), so a caller can
|
|
757
757
|
* reply/forward without leaking them (sec. 6.1); a payload whose `hp` is malformed or contradicts the envelope
|
|
758
758
|
* fails closed (`smime/bad-header-protection`). `legacy` is `null` unless `opts.legacyHeaderProtection` detected a
|
|
759
759
|
* legacy RFC 8551 `message/rfc822` wrap (its own `{ headers, mode, fromMismatch, confidential }` object, where `headers`
|
|
@@ -806,7 +806,7 @@ async function decrypt(message, keyMaterial, opts) {
|
|
|
806
806
|
* @related pki.smime.decompress, pki.cms.compress
|
|
807
807
|
*
|
|
808
808
|
* Compress a MIME entity as an opaque compressed S/MIME message (RFC 8551 sec. 3.6). `content` is the
|
|
809
|
-
* payload
|
|
809
|
+
* payload: a raw body wrapped as a `text/plain` entity by default, or the caller's own complete MIME
|
|
810
810
|
* entity when `opts.entity` is set. The entity is canonicalized (RFC 8551 sec. 3.1) and ZLIB-compressed
|
|
811
811
|
* into a CMS `CompressedData` (`pki.cms.compress`), carried opaque in one `application/pkcs7-mime;
|
|
812
812
|
* smime-type=compressed-data; name=smime.p7z` entity (base64). Compression is a size transform with NO
|
|
@@ -838,7 +838,7 @@ async function compress(content, opts) {
|
|
|
838
838
|
* @spec RFC 8551, RFC 3274
|
|
839
839
|
* @related pki.smime.compress, pki.cms.decompress, pki.smime.verify, pki.smime.decrypt
|
|
840
840
|
*
|
|
841
|
-
* Decompress a compressed S/MIME message (RFC 8551 sec. 3.6)
|
|
841
|
+
* Decompress a compressed S/MIME message (RFC 8551 sec. 3.6), an `application/pkcs7-mime` entity whose
|
|
842
842
|
* base64 body is a CMS `CompressedData`. Returns the recovered inner MIME entity as `content` plus the
|
|
843
843
|
* inner `contentType` / `contentTypeName` and the `compressionAlgorithm`. The inflate is BOUNDED (a
|
|
844
844
|
* decompression-bomb defense, `cms/decompress-too-large`; `opts.maxOutputBytes` tightens it downward).
|
package/lib/tls-cert-compress.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @intro
|
|
13
13
|
* TLS handshake structures that carry certificates. `decompressCertificate`
|
|
14
|
-
* and `compressCertificate` are the RFC 8879 `CompressedCertificate` codec
|
|
14
|
+
* and `compressCertificate` are the RFC 8879 `CompressedCertificate` codec:
|
|
15
15
|
* the compressed form of a TLS 1.3 `Certificate` message, which shrinks the
|
|
16
16
|
* largest thing a handshake sends and matters most for post-quantum chains,
|
|
17
17
|
* where certificates grow by kilobytes. `parseCertificateMessage` decodes the
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
* allocated), and the output must then equal that length exactly (which catches
|
|
31
31
|
* the under-length direction a cap cannot see). The caller's policy cap applies
|
|
32
32
|
* independently, so a peer declaring 16 MiB does not get 16 MiB. This module
|
|
33
|
-
* decodes structure only
|
|
33
|
+
* decodes structure only. It never verifies a certificate, builds a path, or
|
|
34
34
|
* speaks the handshake.
|
|
35
35
|
*
|
|
36
|
-
* All three registered algorithms
|
|
36
|
+
* All three registered algorithms (zlib, brotli and zstd) are implemented,
|
|
37
37
|
* and each is offered only where the running Node can decompress it safely. A
|
|
38
38
|
* decompressor must fault on a frame it could not finish; where one instead
|
|
39
39
|
* returns a short result and reports the whole input consumed, a peer could cut
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
*
|
|
45
45
|
* @card
|
|
46
46
|
* Encode and decode RFC 8879 TLS compressed certificate messages and the
|
|
47
|
-
* RFC 8446 Certificate message inside them
|
|
47
|
+
* RFC 8446 Certificate message inside them: a two-sided decompression
|
|
48
48
|
* bound, exact-length enforcement, per-entry certificate DER surfaced raw,
|
|
49
49
|
* fail-closed. All three registered algorithms are implemented; each is
|
|
50
50
|
* offered only where the running Node decompresses it safely.
|
|
@@ -138,7 +138,7 @@ function _resolveAllowed(opts) {
|
|
|
138
138
|
* body is a framing violation (`opaque<1..2^24-1>`), not an empty certificate list.
|
|
139
139
|
*
|
|
140
140
|
* Throws `TlsError` with a stable `tls/*` code on any malformed input, never a raw
|
|
141
|
-
* `TypeError`. Structure only
|
|
141
|
+
* `TypeError`. Structure only: no certificate here is verified or path-built.
|
|
142
142
|
*
|
|
143
143
|
* @opts
|
|
144
144
|
* maxOutputBytes - tighten the decompression cap DOWNWARD from the RFC 8446 sec. 4
|
|
@@ -221,8 +221,8 @@ function decompressCertificate(bytes, opts) {
|
|
|
221
221
|
*
|
|
222
222
|
* Decode an RFC 8446 sec. 4.4.2 `Certificate` message into its
|
|
223
223
|
* `certificateRequestContext` (raw, empty in a server's handshake certificate) and its
|
|
224
|
-
* `entries`. Each entry surfaces `certData`
|
|
225
|
-
* on the wire, ready for `pki.schema.x509.parse` and never re-serialized, plus the raw
|
|
224
|
+
* `entries`. Each entry surfaces `certData` (the certificate DER exactly as it appeared
|
|
225
|
+
* on the wire, ready for `pki.schema.x509.parse` and never re-serialized), plus the raw
|
|
226
226
|
* `extensions` bytes that follow it and `extensionList`, those bytes decoded to their
|
|
227
227
|
* RFC 8446 sec. 4.2 records (`type` and raw `data` per extension). The vector's framing is
|
|
228
228
|
* validated and not accepted opaquely, so a vector that cannot be a whole number of
|
package/lib/trust.js
CHANGED
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
* Everything is fail-closed and offline: the caller supplies the text (no
|
|
25
25
|
* network fetch); every malformed or oversized input throws a typed
|
|
26
26
|
* `trust/*` error before the offending allocation; a certificate object and
|
|
27
|
-
* its trust object are paired by byte-exact (CKA_ISSUER, CKA_SERIAL_NUMBER)
|
|
28
|
-
*
|
|
27
|
+
* its trust object are paired by byte-exact (CKA_ISSUER, CKA_SERIAL_NUMBER),
|
|
28
|
+
* never by adjacency, and cross-checked against the parsed DER, so
|
|
29
29
|
* trust metadata can never attach to the wrong root; only
|
|
30
30
|
* `CKT_NSS_TRUSTED_DELEGATOR` grants a purpose (everything else, including
|
|
31
31
|
* an absent bit, is untrusted).
|
|
@@ -441,9 +441,9 @@ function _dedupAnchors(anchors) {
|
|
|
441
441
|
* Parse the Mozilla/NSS `certdata.txt` root-store object stream into
|
|
442
442
|
* constraint-carrying trust anchors. Each CKO_CERTIFICATE object's
|
|
443
443
|
* MULTILINE_OCTAL `CKA_VALUE` is decoded and parsed as a DER certificate; the
|
|
444
|
-
* paired CKO_NSS_TRUST object
|
|
444
|
+
* paired CKO_NSS_TRUST object (joined by byte-exact CKA_ISSUER +
|
|
445
445
|
* CKA_SERIAL_NUMBER, never adjacency, and cross-checked against the parsed
|
|
446
|
-
* DER
|
|
446
|
+
* DER) contributes the purpose trust bits (only CKT_NSS_TRUSTED_DELEGATOR
|
|
447
447
|
* grants a purpose); the per-purpose distrust-after dates ride in the
|
|
448
448
|
* certificate object as bare ASCII times routed through the strict DER time
|
|
449
449
|
* reader. Every anchor carries the exact `{ name, publicKey, algorithm,
|
|
@@ -641,7 +641,7 @@ function _pemCell(cell) {
|
|
|
641
641
|
* (`Common Name or Certificate Name`, `Trust Bits`, `Distrust for TLS After
|
|
642
642
|
* Date`, `Distrust for S/MIME After Date`, `PEM Info`) fails closed with
|
|
643
643
|
* `trust/bad-csv`. Fields follow RFC 4180 quoting (embedded commas, newlines,
|
|
644
|
-
* doubled-quote escapes
|
|
644
|
+
* doubled-quote escapes; the PEM Info column depends on it). `Trust Bits`
|
|
645
645
|
* is set-valued (Websites -> serverAuth, Email -> emailProtection, Code ->
|
|
646
646
|
* codeSigning; absent -> untrusted). A DATE-only distrust cell expands to the
|
|
647
647
|
* end-of-day `...T23:59:59Z` instant, matching the NSS `...235959Z`
|
package/lib/tsp-sign.js
CHANGED
|
@@ -96,8 +96,8 @@ function _signingCertV2(certDer, hashName) {
|
|
|
96
96
|
* @spec RFC 3161
|
|
97
97
|
* @related pki.schema.tsp.parseToken, pki.cms.sign
|
|
98
98
|
*
|
|
99
|
-
* Create an RFC 3161 TimeStampToken over `messageImprint` (`{ hashAlgorithm, hashedMessage }
|
|
100
|
-
*
|
|
99
|
+
* Create an RFC 3161 TimeStampToken over `messageImprint` (`{ hashAlgorithm, hashedMessage }`:
|
|
100
|
+
* the hash of the data being timestamped, computed by the requester). `tsa` is the
|
|
101
101
|
* timestamp authority's `{ cert, key }` (as `pki.cms.sign` takes them). The token is a CMS
|
|
102
102
|
* SignedData whose content is a `TSTInfo` carrying the imprint, the TSA policy, a serial
|
|
103
103
|
* number, and `genTime`; the RFC 3161 sec. 2.4.2 signing-certificate attribute binding the
|
|
@@ -110,6 +110,8 @@ function _signingCertV2(certDer, hashName) {
|
|
|
110
110
|
* @opts accuracy The genTime +/- accuracy, as `{ seconds?, millis?, micros? }`.
|
|
111
111
|
* @opts ordering Whether tokens from this TSA are strictly ordered in time (boolean).
|
|
112
112
|
* @opts certHashAlgorithm The ESSCertIDv2 hash algorithm name. Default `sha256`.
|
|
113
|
+
* @opts digestAlgorithm / pss Passed through to `pki.cms.sign` (the signer digest algorithm, RSA-PSS padding).
|
|
114
|
+
* @opts additionalSignedAttributes Extra signed attributes to carry on the token, as `[{ type, values }]` (forwarded to `pki.cms.sign`).
|
|
113
115
|
* @opts sid / pem Passed through to `pki.cms.sign` (signer identifier, PEM output).
|
|
114
116
|
* @example
|
|
115
117
|
* var pair = await pki.key.generate("Ed25519");
|
|
@@ -303,7 +305,7 @@ function request(messageImprint, opts) {
|
|
|
303
305
|
* @spec RFC 3161
|
|
304
306
|
* @related pki.tsp.request, pki.schema.tsp.parseRequest
|
|
305
307
|
*
|
|
306
|
-
* Parse a `TimeStampReq` (DER `Buffer` or PEM)
|
|
308
|
+
* Parse a `TimeStampReq` (DER `Buffer` or PEM), the `pki.schema.tsp.parseRequest` decoder on the
|
|
307
309
|
* `pki.tsp` namespace. Returns `{ version, messageImprint, reqPolicy, reqPolicyName, nonce,
|
|
308
310
|
* nonceHex, certReq, extensions }`; a malformed structure throws a typed `TspError`.
|
|
309
311
|
*
|
|
@@ -382,7 +384,7 @@ function response(token, opts) {
|
|
|
382
384
|
* @spec RFC 3161
|
|
383
385
|
* @related pki.tsp.response, pki.schema.tsp.parse
|
|
384
386
|
*
|
|
385
|
-
* Parse a `TimeStampResp` (DER `Buffer` or PEM)
|
|
387
|
+
* Parse a `TimeStampResp` (DER `Buffer` or PEM), the shipped `pki.schema.tsp.parse` decoder on
|
|
386
388
|
* the `pki.tsp` namespace. Returns `{ status, statusString, failInfo, timeStampToken }` with the
|
|
387
389
|
* status-to-token coupling enforced; a granted response's token is decoded via `parseToken`.
|
|
388
390
|
*
|
|
@@ -535,7 +537,7 @@ function _buildTsaChains(leaf, pool) {
|
|
|
535
537
|
* original bytes (hashed under the token's messageImprint algorithm) or a precomputed
|
|
536
538
|
* `{ hashAlgorithm, hashedMessage }`. Returns `{ valid, trusted, revocationChecked,
|
|
537
539
|
* anchorConstraints, genTime, accuracy, serialNumber,
|
|
538
|
-
* serialNumberHex, policy, nonce, tsa, tstInfo, signer, code?, reason? }`. `valid` is true only
|
|
540
|
+
* serialNumberHex, policy, policyName, nonce, tsa, tstInfo, signer, code?, reason? }`. `valid` is true only
|
|
539
541
|
* when the CMS signature, the imprint match, the eContentType, the ESSCertID(V2) binding, the
|
|
540
542
|
* RFC 3161 sec. 2.3 critical single-`timeStamping` extendedKeyUsage rule, the requested nonce (when
|
|
541
543
|
* supplied), and, when `trustAnchors` is supplied, the full out-of-path TSA-cert path
|
|
@@ -603,7 +605,7 @@ async function verify(token, data, opts) {
|
|
|
603
605
|
var revocationChecked = false;
|
|
604
606
|
var anchorConstraints = null;
|
|
605
607
|
function fail(code, reason) {
|
|
606
|
-
return { valid: false, trusted: false, revocationChecked: revocationChecked, anchorConstraints: anchorConstraints, code: code, reason: reason || null, genTime: tst.genTime, accuracy: tst.accuracy, serialNumber: tst.serialNumber, serialNumberHex: tst.serialNumberHex, policy: tst.policy, nonce: tst.nonce, tsa: tst.tsa, tstInfo: tst, signer: null };
|
|
608
|
+
return { valid: false, trusted: false, revocationChecked: revocationChecked, anchorConstraints: anchorConstraints, code: code, reason: reason || null, genTime: tst.genTime, accuracy: tst.accuracy, serialNumber: tst.serialNumber, serialNumberHex: tst.serialNumberHex, policy: tst.policy, policyName: tst.policyName, nonce: tst.nonce, tsa: tst.tsa, tstInfo: tst, signer: null };
|
|
607
609
|
}
|
|
608
610
|
var cmsRes = await cmsVerify.verify(tokenDer, { certs: opts.certs });
|
|
609
611
|
var signer = cmsRes.signers[0];
|