Skip to content

Time-stamps (RFC 3161)

POSThttps://api.kennmarq.com/v1/tsa/{key}

Our own RFC 3161 time-stamp server, for local mode: when your machine signs a C2PA manifest, it asks this URL to time-stamp the signature. The key sits in the URL because the C2PA library can't add headers.

A tsa-only key

Create a key whose only scope is tsa and put it in the URL. Any key with more scopes is refused here with 403 key_not_allowed_in_url: URLs end up in logs, and a powerful key must never be one of them. If that happens, rotate the key you sent.

Time-stamp URL
https://api.kennmarq.com/v1/tsa/sk_live_…

Request

  • Content-Type: application/timestamp-query
  • The body: a DER-encoded TimeStampReq, at most 4 KB.
  • Message imprints in SHA-256, SHA-384 or SHA-512. A SHA-1 imprint gets a rejection status inside the reply.
  • certReq is honoured (our TSA chain goes into the token) and your nonce is echoed.

Response

200 with Content-Type: application/timestamp-reply exactly, and the DER TimeStampResp as the body, byte for byte as our server produced it. Each token states an accuracy of 1 second, carries a random 128-bit serial and our own policy OID, and is signed with ECDSA P-256 / SHA-256 includingsigningCertificateV2 (RFC 5816).

Every token goes into our public transparency log before it's returned; the X-Log-Index header says where, and GET /v1/log/proof/{index} proves it. A rejection carries no token and no index.

Example with OpenSSL

Shell
# A query for a file's SHA-256, asking for our certificate in the reply
openssl ts -query -data artwork.png -sha256 -cert -out request.tsq

curl https://api.kennmarq.com/v1/tsa/$TSA_KEY \
  -H "Content-Type: application/timestamp-query" \
  --data-binary @request.tsq \
  -o response.tsr

openssl ts -reply -in response.tsr -text

To verify a token, fetch our TSA chain from GET /v1/certificate?chain=tsa.

Counting

Each time-stamp counts once in the month's time-stamp allowance, which is the same size as your plan's marks (and your test marks for test keys), kept apart for live and test keys. A request that fails on our side isn't counted. The plan's calls a minute apply to the organisation, all its keys together; the key's IP allowlist applies to the key.

C2PA validators report our time-stamps as timeStamp.untrusted until our publicly trusted certificate is in place, as they did DigiCert's free stamps. The file still validates.

Errors

Errors of POST /v1/tsa
StatusCodeWhen
400invalid_requestAn empty body, or a query our server couldn't parse.
401missing_api_key, invalid_api_key, api_key_revokedNo key, an unknown key, or a revoked one.
402quota_exceededThe month's time-stamps are used up.
403key_not_allowed_in_urlThe key has scopes beyond tsa.
403ip_not_allowedThe address isn't on the key's IP allowlist.
413payload_too_largeThe query is over 4 KB.
415unsupported_media_typeThe Content-Type isn't application/timestamp-query.
429rate_limitedToo many calls this minute.
503tsa_unavailableThe time-stamp server is down for a moment. Nothing is charged; retry.