Home / Alt manpages / openssl-ts(1ssl)

  • openssl-ts(1ssl)
  • OpenSSL command
  • linux

Create and Verify RFC 3161 Timestamps with openssl ts

Proving a file existed at a given moment, without trusting your own system clock, is exactly what openssl ts is for. It creates an RFC 3161 timestamp request for a file, and verifies a response once a TSA (timestamping authority) sends one back. OpenSSL 3.0.13's ts does not contact a TSA itself: creating requests, creating replies for a TSA operator, and verifying replies are all it does, and moving a request to a service is a separate step you handle yourself.

Allow about 10 minutes for the local request and inspection; verification takes a little longer if you need to obtain the TSA certificate chain. You need the openssl package, a file worth timestamping, and a TSA that accepts RFC 3161 requests. No elevated privileges are needed. Work in a directory where you can keep the original file, request and response together.

1. Check the installed command

Start by checking the binary and the exact options available on this machine. This guide was checked with Ubuntu's openssl package version 3.0.13-0ubuntu3.15, whose manpage is dated 18 August 2026 and identifies the command as OpenSSL 3.0.13:

openssl version -a
openssl ts -help

The three useful modes are -query, -reply and -verify. A query contains a digest of your data, not the data itself. The TSA signs a timestamp token containing that digest and a time, so anyone verifying the response must still hold the original data, or the original request plus a trusted certificate source.

2. Create a timestamp request

Keep the input file unchanged from this point on. The digest in the request represents its exact bytes, so editing it, normalising line endings, or swapping it out later will make data-based verification fail:

mkdir -p "$HOME/ts-work"
cd "$HOME/ts-work"
printf '%s\n' 'release candidate 2026-09-25' > release.txt
openssl ts -query \
  -data release.txt \
  -sha256 \
  -cert \
  -out release.tsq

-data makes OpenSSL hash the named file. The local manpage says SHA-256 is the default, but naming -sha256 keeps the choice visible in scripts and review. -cert asks the TSA to include its signing certificate in the response; it does not put a certificate in the request itself. A nonce is included by default, and it is worth keeping unless the TSA specifically requires -no_nonce, since the nonce helps guard against replay.

The command writes DER, a binary format, to release.tsq, so a successful run prints nothing about the request because the output is redirected:

test -s release.tsq && echo "request written"
openssl ts -query -in release.tsq -text

Look for Hash Algorithm: sha256, a 32-byte message imprint, a nonce, and Certificate required: yes. Omit -out and the default is standard output, useful for a pipeline but an easy way to mix binary DER with terminal output, so use a file while you are still learning the command.

3. Send the request without changing it

Transfer release.tsq to the TSA using the method agreed with its operator, such as an approved upload or email workflow. ts has no built-in HTTP or TCP transport of its own. Do not send release.txt merely because it is convenient: the whole point of the request is that it discloses the digest rather than the source data.

Ask for a DER timestamp response, normally saved as release.tsr. A response status that is not granted is not a valid timestamp for this workflow. Keep the returned file unchanged, and record which trust anchor you intend to verify it against.

4. Verify the response against the original file

Verification checks both the message imprint and the TSA signature chain. At least one trust source is mandatory, so replace the example path with a CA bundle your organisation actually trusts; the bundle is an input here, not a reason to disable certificate checks:

openssl ts -verify \
  -data release.txt \
  -in release.tsr \
  -CAfile /path/to/tsa-trust-chain.pem

Success is reported as:

Verification: OK

The command exits non-zero for a mismatched file, an invalid response, an untrusted signer, or certificate verification errors, so check the exit status in automation:

if openssl ts -verify -data release.txt -in release.tsr \
    -CAfile /path/to/tsa-trust-chain.pem >verify.log 2>&1; then
    echo "timestamp verified"
else
    status=$?
    sed -n '1,120p' verify.log
    echo "timestamp verification failed (exit $status)" >&2
    exit "$status"
fi

Use exactly one of -data, -digest and -queryfile. For a file-based check, use -data as above. If the original file is gone but the original request survives, verify that request instead:

openssl ts -verify \
  -queryfile release.tsq \
  -in release.tsr \
  -CAfile /path/to/tsa-trust-chain.pem

That proves the response matches the request. The request's digest can only be tied back to the original file if you have independently preserved or recomputed that file.

5. Understand the TSA operator boundary

-reply is for the operator of a TSA, not a shortcut to a public timestamp. It needs a configuration file, a timestamping certificate and its private key, and the signing certificate must carry exactly one critical timeStamping extended key usage. The configuration names a serial file, signer certificate, private key, signing digest and default policy. The serial file is created if absent and incremented for each response, so protect it from concurrent writers and back it up according to the TSA's operating procedure.

For a reply, -queryfile reads the DER request and -out writes a DER response. -text is for human-readable inspection, not for a response another tool should verify. If the request asks for the signer certificate, -chain supplies additional PEM certificates; -reply does not build that chain automatically. Treat the private key and serial file as security-sensitive state, and never run an untested reply configuration against production keys.

Common traps

  • Digest mismatch: the input changed, the wrong file was supplied, or the response belongs to another request. Recreate the request from the intended file and obtain a new response.
  • Unable to build certificate chain: check -CAfile, -CApath or -CAstore, then supply missing intermediates with -untrusted. Do not use -no_check_time as a general fix: it changes certificate-time checking.
  • Response format errors: check whether the file is a timestamp response or a bare timestamp token. Add -token_in only when the input really is a DER ContentInfo token.
  • Unexpected policy or algorithm: inspect the request and response with -text. A policy requested with -tspolicy must be accepted by the TSA; it is not a local override.

Recovery

There is no useful undo for a timestamp already issued. Recovery means preserving the original file and request, rejecting failed verification, and obtaining a fresh response. You can remove disposable working copies once retention requirements are satisfied.

Done means

  • Request created. release.tsq is a non-empty DER request, inspected with -text.
  • Original preserved. release.txt is unchanged from the moment the request was made.
  • Response stored separately. The TSA response is saved as release.tsr.
  • Verification passed. openssl ts -verify returns zero and prints Verification: OK against an explicitly trusted CA source.