TX Text Control .NET for WPF

Timestamp Configuration

Topic

Without a timestamp server, the time of a signature is whatever the clock of the signing computer said, and nothing proves it. A trusted timestamp from an RFC 3161 time server makes the signing time verifiable, which matters most years later, after the signer's certificate has expired. In TX Text Control .NET for WPF, the configuration is one constructor argument, the URL of the time server; the timestamp is requested while the signed PDF is saved.

A first timestamp is added in Add a Trusted Timestamp in Getting Started. What an application needs beyond that, fallback servers, an answer for an offline computer and timestamps for signature fields, is covered here.

Why a Signature Needs a Trusted Time

Take a contract signed in February 2026 with a certificate that expires in January 2027. When somebody checks the contract in 2032, the certificate has long expired, and without a trusted time the validator can't tell whether it was valid in February 2026. Adobe Acrobat and other validators then often warn or report that the long-term validity of the signature can't be verified, although nobody changed the document.

A trusted timestamp gives the validator what it needs: the signature matches the document, the timestamp is trusted, the certificate was valid at the time of the timestamp and the document is unchanged since:

A timeline with a certificate issued in January 2026, expiring in January 2027 and a document opened in 2032, next to the checks a validator passes thanks to the timestamp.

What Happens During the Save

A time server, or Time-Stamping Authority (TSA), doesn't sign the document. It certifies the time of a signature that TX Text Control has already created:

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

The time server never sees the content of the document. The computer that signs, however, needs network access to the time server at the moment of saving, which a WPF application can't take for granted on a laptop or behind a company firewall.

Specify the Time Server

The second parameter of both DigitalSignature constructors, timeServerURL, decides where the signing time comes from:

Value of timeServerURLSigning time
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

Certificate authorities offer time servers, and many organizations run their own for internal documents. Choose one that the readers of your documents trust: validators check the timestamp too.

There are no other time server settings: DigitalSignature takes no credentials, proxy or timeout. The server is contacted when WPF.TextControl.Save writes the PDF, not when the DigitalSignature object is created.

Handle an Unavailable Time Server

A time server that doesn't exist or returns invalid data makes Save throw a FilterException with the Reason InvalidTimeServer. The following handler tries the servers of a list one after the other. If none answers, it asks the user in a WPF MessageBox whether to sign with the computer's date and time. MainWindow.xaml.cs needs using System.IO;, using System.Security.Cryptography.X509Certificates;, using System.Windows; and using TXTextControl;.

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

private void signWithTimestampButton_Click(object sender, RoutedEventArgs e)
{
    X509Certificate2 certificate = X509CertificateLoader.LoadPkcs12FromFile(
        "certificate.pfx", "123", X509KeyStorageFlags.Exportable);

    byte[] signedPdf = null;

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

        try
        {
            textControl1.Save(out byte[] pdf, BinaryStreamType.AdobePDF, saveSettings);
            signedPdf = pdf;
            break;
        }
        catch (FilterException exception) when (exception.Reason == FilterException.FilterError.InvalidTimeServer)
        {
            // Try the next time server
        }
    }

    if (signedPdf == null)
    {
        MessageBoxResult answer = MessageBox.Show(this,
            "No time server returned a timestamp. Sign with the date and time of this computer instead?",
            "Timestamp", MessageBoxButton.YesNo, MessageBoxImage.Warning);

        if (answer != MessageBoxResult.Yes)
        {
            return;
        }

        SaveSettings saveSettings = new SaveSettings()
        {
            DigitalSignature = new DigitalSignature(certificate, "")
        };

        textControl1.Save(out signedPdf, BinaryStreamType.AdobePDF, saveSettings);
    }

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

The code works as follows:

  • Every attempt uses a new SaveSettings object with a DigitalSignature for the next server.
  • The PDF is saved into a byte array first, so no file is written until a signature exists.
  • When no server answers, the user decides. If your documents must stay verifiable for years, don't offer the choice: refuse to sign rather than silently drop the timestamp.

Add Timestamps to Signature Fields

Signed signature fields get one DigitalSignature each in SaveSettings.SignatureFields, and each has its own time server URL: pass the URL instead of the empty string in the loop of Sign the Fields of the Document, and every field gets its own timestamp. The fields of one document can use different time servers or none; Multiple Signatures mixes both.

How Readers Show the Signing Time

The Signatures panel of Adobe Acrobat Reader shows where the time of a signature comes from. Without a timestamp, it states that the signing time is from the clock on the signer's computer:

Adobe Acrobat with the Signatures panel open, stating among the details of a valid signature that the signing time is from the clock on the signer's computer.

With a timestamp, the time is cryptographic evidence inside the signature and keeps the signature verifiable after the certificate expires. The blog article Building Long-Term Trust with Digital Signatures and Timestamps in C# .NET walks through the validation.

Timestamps and PAdES

Requirements for archives, contracts and electronic signatures often name a PAdES profile, one of the PDF Advanced Electronic Signature profiles. PAdES-B and PAdES-T differ only in the timestamp:

PAdES-BPAdES-T
ContainsThe digital signature, the signer's certificate and its certificate chainAll of PAdES-B plus a trusted RFC 3161 timestamp
After the certificate expires or is revokedA validator may be unable to determine whether the certificate was valid when the document was signedThe timestamp proves that the signature existed while the certificate was valid

Text Control states that TX Text Control creates PAdES-T signatures when you pass both a certificate and the URL of a time server. That URL is the only choice: DigitalSignature has no members besides its constructors, so a profile, a hash algorithm or revocation data can't be set. If a recipient or a regulation requires a particular level, sign sample documents and check them with the recipient's validator first. Verify the Signatures in Code describes what the TXTextControl.PDF.Validation package checks.

Next Steps