Timestamping (RFC 3161)

An RFC 3161 Time-Stamp Protocol client — the requester / verifier side, not a TSA. A timestamp authority binds a hash of your data to a trusted time, producing a timestamp token that proves the data existed at that instant: timestamp a release artifact, an audit-log checkpoint, a b.scitt signed statement, a contract.

b.tsa.buildRequest(data, opts) produces the DER TimeStampReq (a message imprint = the hash of your data, plus an optional nonce and a request for the TSA's certificate); b.tsa.parseResponse(der) reads the TimeStampResp, surfacing the PKIStatus (and any failure-info bits) and the token; b.tsa.verifyToken(token, opts) verifies the token against your data and returns the asserted time. The transport (an HTTP POST of application/timestamp-query to the TSA's URL) is the operator's to make — the framework builds the request and verifies the response.

Verification (RFC 3161 §2.4.2 / §2.3) is the security-bearing part and is done in full: the token is a CMS SignedData (b.cms) whose eContentType must be id-ct-TSTInfo; the message imprint inside the TSTInfo must equal the hash of your data (constant-time compare); a sent nonce must round-trip; the signer's certificate must carry the id-kp-timeStamping extended key usage, marked critical and as the only EKU; and the CMS signature over the signed attributes must verify (the messageDigest attribute is checked against the recomputed eContent digest first). An optional trust-anchor set verifies the certificate chain and validity at the asserted time.

Algorithms. Timestamp tokens are third-party artifacts: public TSAs sign with classical RSA (PKCS#1 v1.5 or PSS) or ECDSA over SHA-2, so verification accepts those — the same consume-what-exists stance as b.cose verification. This is not a signing default (the framework is not the TSA); it is verification of externally-produced tokens. The message-imprint hash you request defaults to SHA-512 and may be any of SHA-256 / 384 / 512 or SHA3-256 / 512 the TSA supports.

b.tsa.buildRequest(data, opts?) #

experimental0.12.38soc2
{
  {
    hashAlg:    string,   // "SHA-512" (default) | "SHA-256" | "SHA-384" | "SHA3-256" | "SHA3-512"
    hashed:     boolean,  // true means `data` is already the digest (must match hashAlg length)
    reqPolicy:  string,   // request a specific TSA policy OID (dotted)
    nonce:      Buffer,   // explicit nonce bytes, or false to omit (default: random 8 bytes)
    certReq:    boolean,  // ask the TSA to include its cert (default true)
  }
}

Build a DER-encoded RFC 3161 TimeStampReq for data. POST the returned bytes to the TSA as application/timestamp-query; keep the returned nonce to pass to verifyToken. By default a random 64-bit nonce is included and the TSA is asked to return its certificate.

var req = b.tsa.buildRequest(releaseTarball, { hashAlg: "SHA-512" });
// POST req.der to the TSA; keep req.nonce for verifyToken
// → { der, nonce, hashAlg, messageImprint }

b.tsa.parseResponse(der) #

experimental0.12.38soc2

Parse a DER RFC 3161 TimeStampResp. Returns the PKIStatus and, when the request was granted, the timestamp token (the DER ContentInfo to pass to verifyToken). A non-granted status surfaces the status integer, any free-text, and the decoded failure-info flags rather than throwing — the caller decides how to react.

var resp = b.tsa.parseResponse(httpBodyBytes);
if (resp.granted) { var out = b.tsa.verifyToken(resp.token, { data: tarball, nonce: req.nonce }); }
// → { granted: true, status: 0, token, statusString: null, failInfo: [] }

b.tsa.verifyToken(token, opts) #

experimental0.12.38soc2
{
  {
    data:            Buffer,    // the timestamped data (hashed with hashAlg)
    hash:            Buffer,    // OR a pre-computed digest (with hashAlg)
    hashAlg:         string,    // default "SHA-512" — must match the imprint
    nonce:           Buffer,    // require the token nonce to match (from buildRequest)
    trustAnchorsPem: string|string[], // PEM trust root(s) to authenticate the TSA — REQUIRED unless allowUntrustedIssuer
    allowUntrustedIssuer: boolean,     // accept a token with no trust anchor (result carries issuerTrusted:false)
    at:              Date,      // validity instant for chain check (default: genTime); must be a valid Date
  }
}

Verify an RFC 3161 timestamp token against your data and return the asserted time. Performs the full §2.4.2 / §2.3 check: eContentType is id-ct-TSTInfo, the message imprint equals the hash of opts.data (or opts.hash), a sent nonce round-trips, the signer cert's extendedKeyUsage is a critical, sole id-kp-timeStamping, and the CMS signature verifies. The signer certificate is embedded in the token (and therefore attacker-controlled), so opts.trustAnchorsPem is required by default — without it a self-signed token would pass on its self-contained signature alone. To accept an unauthenticated timestamp, set opts.allowUntrustedIssuer:true; the result then carries issuerTrusted:false.

var out = b.tsa.verifyToken(resp.token, { data: tarball, hashAlg: "SHA-512", nonce: req.nonce, trustAnchorsPem: caPem });
// → { genTime, policy, serialHex, accuracy, hashAlg, signerCertPem, issuerTrusted: true }

Last updated 2026-08-08T16:39:49.652Z by seeder.