A CAdES-BASELINE-LTA signature (long-term archival, ETSI EN 319 122-1) keeps a P7M or P7S signature verifiable for many years. It contains a time-stamp of the signature, the certificates and the revocation data (CRL and OCSP responses) of the signing certificate and of the time-stamp, and an archive time-stamp (v3) that protects the signature and all its validation data. The validators, such as the DSS validation tool of the European Commission, report it as CAdES-BASELINE-LTA.

How to create a CAdES-LTA signature in C#

  1. Create a CadesSignature object and set DigitalSignatureCertificate.
  2. Set SignatureStandard = CadesSignatureStandard.CadesLTA.
  3. Set a time-stamping server in TimeStamping.ServerUrl: it is required, for the signature time-stamp and for the archive time-stamp.
  4. Sign with ApplyDigitalSignature. The validation data is collected from the CRL and OCSP addresses written in the certificates. Set IsDetachedSignature = true for a detached .p7s signature.

C# code: CAdES-BASELINE-LTA signature

/// <summary>
/// Signs a file with a CAdES-BASELINE-LTA signature: signature time-stamp, validation data and archive time-stamp.
/// </summary>
static void SignWithCadesLta(string unsignedFile, string p7mFile)
{
    CadesSignature cadesSignature = new CadesSignature(LibrarySerialNumber);

    cadesSignature.DigitalSignatureCertificate = LoadSigningCertificate();

    // CAdES-BASELINE-LTA (ETSI EN 319 122-1): a signature time-stamp, the certificates and the revocation data (CRL, OCSP)
    // of the signing certificate and of the time-stamp, and an archive time-stamp of the signature and of its validation data.
    cadesSignature.SignatureStandard = CadesSignatureStandard.CadesLTA;
    cadesSignature.HashAlgorithm = SignLib.HashAlgorithm.SHA256;

    // The time-stamping server is required: it creates the signature time-stamp and the archive time-stamp.
    cadesSignature.TimeStamping.ServerUrl = new Uri("https://ca.signfiles.com/TSAServer.aspx");

    // The signed file is included in the signature (.p7m). For a detached signature (.p7s) set IsDetachedSignature = true.
    File.WriteAllBytes(p7mFile, cadesSignature.ApplyDigitalSignature(unsignedFile));
}

CAdES levels (CadesSignature.SignatureStandard)

ValueLevelWhat the signature contains
CmsCMS / PKCS#7A basic signature, recognized by the older software
CadesBesCAdES-BES (default)The signing certificate referenced by a signed attribute
CadesLTCAdES-BASELINE-LTA signature time-stamp and the certificates and revocation data, in the SignedData
CadesLTACAdES-BASELINE-LTACAdES-LT plus an archive time-stamp v3: long-term archival
CadesC, CadesXL, CadesACAdES-C, X Long, A (ETSI TS 101 733)The older long-term formats, with the validation data in unsigned attributes; validators report CAdES-A, not CAdES-BASELINE-LTA

For new long-term signatures use the baseline levels CadesLT and CadesLTA. A time-stamp of the signature (CAdES-T) can be added at any level by setting TimeStamping.ServerUrl.

C# code: verify and detect the level

CadesVerify.SignatureStandard reports the level detected from the file, including CadesLTA.

/// <summary>
/// Verifies a .p7m file and displays its signatures.
/// </summary>
static void PrintCadesSignatures(string p7mFile)
{
    // The signature is verified when the CadesVerify object is created.
    CadesVerify cadesVerify = new CadesVerify(p7mFile, LibrarySerialNumber);

    // The standard is detected from the attributes of the signers.
    Console.WriteLine(Path.GetFileName(p7mFile) + ": " + cadesVerify.SignatureStandard + ", " + cadesVerify.Signatures.Count + " signature(s), signed file: " + cadesVerify.DocumentName);

    foreach (CadesSignatureInfo signatureInfo in cadesVerify.Signatures)
    {
        // SignatureIsValid verifies only the integrity of the signature: not the certificate chain or the revocation status.
        Console.WriteLine("  Signer: " + (signatureInfo.SignatureCertificate != null ? signatureInfo.SignatureCertificate.GetNameInfo(X509NameType.SimpleName, false) : "(certificate not included)")
            + ", valid: " + signatureInfo.SignatureIsValid + ", " + signatureInfo.HashAlgorithm.FriendlyName
            + (signatureInfo.SignatureIsTimestamped ? ", time-stamped " + signatureInfo.TimestampInfo.SignatureTime.ToLocalTime() : string.Empty));
    }

    Console.WriteLine();
}

For the basic P7M and P7S signatures see CAdES digital signature; the same long-term archival exists for PAdES-LTA, XAdES-LTA and ASiC-E. For legal effect in the European Union, use a qualified time-stamping service, such as the eIDAS qualified timestamps of qtsa.eu.

Run the full sample. The complete Visual Studio project P7M P7S CAdES Long-Term and Co-Signature is included in the library download, in the folder NET Sample Projects (.NET 8, .NET 9 and .NET 10) and in NET Framework Sample Projects (.NET Framework 4.6.2), with the test files and a test certificate. Without a serial number the library runs in demo mode. Download the library and the samples · User manual

Frequently asked questions

What is the difference between CAdES-A and CAdES-LTA?

Both contain the validation data and an archive time-stamp. CAdES-A is the older format of ETSI TS 101 733, with the validation data in unsigned attributes. CAdES-BASELINE-LTA (ETSI EN 319 122-1) writes the certificates and the revocation data in the SignedData and is the profile expected by the eIDAS validators.

Why is there no revocation data in my signature?

The revocation data is taken from the CRL and OCSP addresses of the certificates. A self-signed test certificate has none, so only the certificates are added.