TSA

TSA is a self-hosted RFC 3161 Timestamp Authority for NethServer 8, based on the sigstore timestamp-server. It issues and verifies trusted timestamp tokens for documents and digital signatures.

The TSA app announcement

TSA is a community application from the tebbiworld repository. Documentation and source can be found on Github

A Timestamp Authority (TSA) confirms that a piece of data existed at a given point in time. The client sends only a hash of the document to the TSA; the TSA returns a signed token (RFC 3161) that binds this hash to the current time. The document itself is never transmitted.

Typical use cases:

  • Signed PDFs (LibreSign, JSignPdf, other PAdES tools): without a TSA, the signature contains only the local clock of the signing server (signing_time). Adobe Acrobat and other validators treat this as untrusted. With an embedded RFC 3161 token, the signing time is confirmed by an independent signer.
  • Evidence that a file existed at a specific time (lab records, source code, exports, log archives) using openssl ts.
  • Many files at once: create a list of hashes (e.g. sha256sum) and timestamp that list. One token then covers all listed files.

Public services such as freeTSA.org offer free RFC 3161 timestamps. This module is an alternative for cases where you want to run the service yourself.

Aspect Public TSA (e.g. freeTSA.org) This module (self-hosted)
Operator Third party You, on your own NS8 node
What leaves your network Document hash only Nothing (unless clients are external)
Availability Depends on the public service Depends on your node
Signing certificate Operated by the provider Your own chain, or an uploaded commercial timestamping certificate
Trust by third parties Depends on the provider Clients must import your Root CA
Suitable for Occasional use, no own infrastructure Automated signing workflows on your own cluster (e.g. LibreSign on Nextcloud)

Evidentiary value: a self-operated TSA is suitable for internal and technical use. Against third parties, its tokens carry limited legal weight compared to an accredited, audited provider. If qualified (e.g. eIDAS) timestamps are required, obtain a commercial timestamping certificate and install it via Upload certificate (see below).

  • A single distroless, rootless container (sigstore timestamp-server, UID 65532).
  • The container listens on 127.0.0.1 only and is published through the Traefik instance of the node on which the module runs.
  • HTTPS, Let's Encrypt and HTTP→HTTPS redirect are handled by Traefik, exactly like in other NS8 web applications.

This is the most important concept of the module. The two certificates have different purposes and cannot replace each other.

HTTPS transport certificate RFC 3161 signing certificate
Purpose Encrypts the connection between client and server Signs every timestamp token
Issued by Let's Encrypt (via Traefik), optional Module itself (self-signed chain) or manual upload
Renewal Automatic by Traefik Explicit action in the module UI (Rotate)
Lifetime Short (Let's Encrypt default) Root CA approx. 30 years, leaf approx. 25 years
Algorithm Traefik default EC P-384, leaf key stored as AES-256 encrypted PKCS#8

Why Let's Encrypt cannot sign timestamps: RFC 3161 requires the extension extendedKeyUsage = timeStamping marked as critical in the signing certificate. Public TLS certificates, including Let's Encrypt, do not contain this extension. The signing certificate is therefore always either the self-generated chain or an externally obtained timestamping certificate.

The signing chain is generated on the first save of the configuration. Existing certificates are never overwritten when the configuration is saved again.

On a NethServer 8 node:

add-module ghcr.io/tebbiworld/tsa:latest 1

Then open the module UI and configure:

  • Host name (FQDN), e.g. tsa.example.org
  • Let's Encrypt (optional): requires that ports 80/443 of this FQDN reach the node on which the module runs (HTTP-01 challenge).
  • HTTP→HTTPS redirect (optional)

On the first save, the module generates the signing chain and starts the server.

Method Path Purpose
POST /api/v1/timestamp Submit a timestamp query (Content-Type application/timestamp-query)
GET /api/v1/timestamp/certchain Download the signing certificate chain
GET /ping Health check

Timestamp URL for clients: https:<fqdn>/api/v1/timestamp =====Certificate page===== The Certificate page of the module UI provides: * Current signer: subject, valid-until date, SHA-256 fingerprint * Download chain * Self test: issues a real token and verifies it against the chain * Rotate: archives the current chain and generates a new one * Upload certificate: installs an externally obtained timestamping certificate. The certificate is checked for the timeStamping EKU before anything is replaced. Note on rotation: tokens issued before a rotation can only be verified against the old chain. Keep the archived chain as long as old tokens need to be verifiable. =====Usage===== ====Command line (openssl)==== Replace tsa.example.org with your FQDN. 1. Create a timestamp query for a file: <code bash> openssl ts -query -data file.pdf -sha256 -cert -out file.tsq </code> 2. Send the query to the TSA: <code bash> curl -H “Content-Type: application/timestamp-query” –data-binary @file.tsq https://tsa.example.org/api/v1/timestamp -o file.tsr </code> 3. Download the chain (once): <code bash> curl -o tsa-chain.pem https://tsa.example.org/api/v1/timestamp/certchain </code> 4. Show and verify the token: <code bash> openssl ts -reply -in file.tsr -text openssl ts -verify -in file.tsr -queryfile file.tsq -CAfile tsa-chain.pem </code> Expected result: Verification: OK For strict verification, use only the Root CA certificate as -CAfile (the trust anchor), not the complete chain. ====Timestamping many files==== <code bash> find /path/to/files -type f -exec sha256sum {} + > hashes.txt openssl ts -query -data hashes.txt -sha256 -cert -out hashes.tsq </code> Continue with step 2. Keep hashes.txt, the files and the token together: verification requires all of them. ====LibreSign / JSignPdf==== Set the TSA URL to https:<fqdn>/api/v1/timestamp.

LibreSign note: in the tested setup (LibreSign 13.2.6), the PhpNative signing engine did not embed the TSA token although a TSA URL was configured. With the JSignPdf engine, the token was embedded.

Validators must trust the Root CA of your TSA. Download the chain from /api/v1/timestamp/certchain and import the Root CA certificate as a trusted certificate in the validating application (in Acrobat: Trusted Certificates). Without this step, the timestamp is displayed as not verifiable, even though the token is technically valid.

  • Back up the Root CA private key offline. It is the trust anchor of the whole TSA. Whoever holds it can issue tokens that your clients accept.
  • Keep archived chains after each rotation (see above).
  • The accuracy of the timestamps depends on the system clock of the node. Make sure time synchronisation (NTP/chrony) works on the node.
curl -i https://tsa.example.org/ping

For a full functional test, use the Self test on the Certificate page, or the openssl sequence under Usage.

Private hobby project, shared as-is. No warranty, no guaranteed support, use at your own risk. Unofficial community package, not affiliated with or endorsed by the sigstore project. The module pulls the upstream sigstore timestamp-server image; the module's own code is licensed GPL-3.0-or-later. Bug reports via GitHub issues.