All examples below use this function. Define it once in your shell profile or deployment scripts.
stamp() {
openssl ts -query -sha256 -data "$1" -no_nonce \
| curl -s -H "Content-Type: application/timestamp-query" \
--data-binary @- https://free.tsa.cnx.net.kh/ > "$1.tsr"
}
This hashes the file locally, sends only the hash to CNX, and writes the timestamp token alongside the original file. The original is never modified.
Backup software records when a backup was made in its own catalog — a timestamp written by the same system that holds the backup. A privileged administrator, or an attacker who has compromised backup infrastructure, can modify both the backup and its catalog entry. No major backup tool provides external timestamp attestation; this gap is unaddressed by the backup software industry.
A CNX timestamp token created immediately after a backup completes is a witness that no backup administrator can retroactively forge. Call it from your post-job hook or cron:
stamp /backups/daily-$(date +%Y%m%d).tar.gz
The .tsr file sits alongside the backup. In a dispute or audit, the token proves the backup existed in exactly this state at this time — independently, externally, to a party outside your infrastructure.
Veeam post-job script: add the stamp function and the call above to a post-job script in the Veeam job advanced settings → Scripts tab. Veeam passes the backup file path in $VEEAM_BACKUP_FILE if configured.
Stamp the log file at regular intervals. Each token proves the log was in exactly this state at this time — insertions or deletions after the stamp are detectable on the next verification.
# Run hourly via cron: 0 * * * * stamp /var/log/audit/app.log mv /var/log/audit/app.log.tsr /var/log/audit/stamps/$(date -u +%Y%m%dT%H%M).tsr
The .tsr files in the stamps directory form a chain. To verify any interval: retrieve the .tsr from that hour and the log snapshot that existed at that time.
In regulated industries, the meaningful timestamp is not on the source commit — it is on the release artifact. The commit timestamp can be questioned; the artifact is what was actually deployed. A CNX timestamp on the release tarball or container image digest proves the artifact existed before deployment, before an audit, and before any dispute.
Stamp a release tarball at build time:
stamp release-v1.0.0.tar.gz
Stamp a Docker image: use the image's content digest, not its local ID — the digest is the same value anywhere the image is pulled, so it's what you'd actually want to prove later.
# Push (or pull) the image, then get its content digest
docker push myapp:v1.0.0
docker inspect --format='{{index .RepoDigests 0}}' myapp:v1.0.0 > /tmp/image-digest
cat /tmp/image-digest
# myapp@sha256:9b2f3c1a8e4d0c7f6a5b3d2e1f0a9c8b7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a
# Timestamp the digest and save the token next to your release assets
stamp /tmp/image-digest
mv /tmp/image-digest.tsr myapp-v1.0.0-digest.tsr
Store the .tsr in your release assets alongside the artifact. For CI/CD pipelines, add the stamp call as a post-build step right after the push, before publishing the release. The token proves the exact digest existed at that time — anyone who later pulls myapp@sha256:9b2f3c1a... is pulling the same bytes this token attests to.
SignTool has native RFC 3161 support via /tr. Add the CNX TSA URL to any existing signing command:
signtool sign /tr https://free.tsa.cnx.net.kh/ /td sha256 /fd sha256 /f cert.pfx script.ps1
The timestamp is embedded in the signature. The signed file remains verifiable after the signing certificate expires.
jarsigner has native RFC 3161 support via -tsa:
jarsigner -tsa https://free.tsa.cnx.net.kh/ -keystore keystore.jks -storepass pass app.jar alias
The timestamp is embedded in the JAR signature block. No sidecar file.
Adobe Acrobat Pro, iText 7, and PyHanko all support embedding CNX timestamps directly inside PDF signatures — no separate file needed.