TX Text Control .NET Server

RFC 3161 Timestamps

Topic

A signature shows who signed a document and that it hasn't changed since, but not when it was signed. That gap matters years later, when the signer's certificate has expired or been revoked. A trusted timestamp from an RFC 3161 time server closes it: it certifies that the signature existed at a particular moment, while the certificate was still valid. TX Text Control requests the timestamp while it saves the signed PDF, so you only pass the address of a time server.

Getting Started adds a timestamp to a whole-document signature in Add a Trusted Timestamp. What a timestamp means for the profile of a signature is described in PAdES.

Why a Signature Needs a Trusted Time

Suppose a contract is signed in February 2026 with a certificate that expires in January 2027, and somebody checks the contract in 2032. At that point, a validator only knows that the certificate has expired, not whether it was valid in February 2026. Without a trusted time, validators such as Adobe Acrobat often show warnings or state that the long-term validity of the signature can't be verified, although the document is unchanged.

With a timestamp, the validator can answer all its questions: the signature matches the document, the timestamp is trusted, the certificate was valid at the time of the timestamp and the document hasn't changed since signing.

A timeline with a certificate valid from January 2026 to January 2027 and a document opened in 2032, whose validation still succeeds because of the timestamp

How a Timestamp Is Created

A time server, also called a Time-Stamping Authority (TSA), doesn't sign your document. When TX Text Control saves a signed PDF with a time server URL, these steps happen:

  1. TX Text Control creates the signature of the document.
  2. It sends a cryptographic hash of the signature to the time server. The PDF itself never leaves your system.
  3. The time server combines the hash with the current, trusted UTC time and signs the result with its own certificate.
  4. TX Text Control embeds the returned timestamp token in the PDF as part of the signature.

Because only a hash is sent, the time server has no access to the document or its content. Requesting a timestamp typically adds a fraction of a second to the signing process.

Specify the Time Server

Both constructors of DigitalSignature take the URL of the time server as their second parameter, timeServerURL:

Value of timeServerURLSigning time
null or an empty stringThe current date and time of the computer
The URL of an RFC 3161 time server, such as http://timestamp.digicert.comA trusted timestamp from the time server

Timestamps are offered by certificate authorities such as DigiCert, GlobalSign, Entrust and SSL.com, and many organizations operate their own time servers for internal signing workflows. Use a trusted server, because validators check the timestamp as well.

DigitalSignature has no further settings for the time server, such as credentials, a proxy or a timeout. The server is contacted when Save creates the PDF, not when the DigitalSignature object is created.

Handle an Unavailable Time Server

When the time server doesn't exist or returns invalid data, Save throws a FilterException whose Reason is InvalidTimeServer. The following program tries the time servers of a list in order and stops without a signed document if none of them returns a timestamp:

using System.Security.Cryptography.X509Certificates;
using TXTextControl;

string[] timeServers =
{
    "http://timestamp.digicert.com",
    // Add the URL of a second RFC 3161 time server, for example your organization's own
};

X509Certificate2 certificate = X509CertificateLoader.LoadPkcs12FromFile(
    "certificate.pfx", "123", X509KeyStorageFlags.Exportable);

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Text = "This document is signed with a trusted timestamp.";

    byte[]? signedPdf = null;

    foreach (string timeServer in timeServers)
    {
        SaveSettings saveSettings = new SaveSettings()
        {
            DigitalSignature = new DigitalSignature(certificate, timeServer)
        };

        try
        {
            tx.Save(out byte[] pdf, BinaryStreamType.AdobePDF, saveSettings);
            signedPdf = pdf;
            break;
        }
        catch (FilterException exception) when (exception.Reason == FilterException.FilterError.InvalidTimeServer)
        {
            Console.WriteLine($"{timeServer} didn't return a valid timestamp.");
        }
    }

    if (signedPdf == null)
    {
        throw new InvalidOperationException("No time server returned a valid timestamp.");
    }

    File.WriteAllBytes("signed.pdf", signedPdf);
}

The code works as follows:

  • Each attempt creates a new SaveSettings object with a DigitalSignature for the next time server.
  • The document is saved into a byte array, and the file is written only after a signature with a timestamp was created.
  • If no time server answers, the program throws an exception instead of signing without a timestamp. A document that must be verifiable in the long term shouldn't silently lose its timestamp.

Add Timestamps to Signature Fields

When a document is signed in its signature fields, each field gets its own DigitalSignature in SaveSettings.SignatureFields, and each of them has its own time server URL. Pass the URL as the second constructor parameter in the loop of Sign the Fields of a Document, for example new DigitalSignature(certificate, "http://timestamp.digicert.com", field.Name). Sign Several Fields in One Save signs one field with a timestamp and the others without.

How Readers Show the Timestamp

In the Signatures panel of Adobe Acrobat Reader, a signature without a trusted timestamp is reported, once its certificate has expired, as a signature whose long-term validity can't be verified. For a signature with a timestamp, Acrobat Reader states that it includes an embedded timestamp:

The Signatures panel of Adobe Acrobat Reader for a valid signature that includes an embedded timestamp

The TXTextControl.PDF.Validation package reports the signing time that a signature contains, as Signature Validation describes.

Next Steps