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#
- Create a
CadesSignatureobject and setDigitalSignatureCertificate. - Set
SignatureStandard = CadesSignatureStandard.CadesLTA. - Set a time-stamping server in
TimeStamping.ServerUrl: it is required, for the signature time-stamp and for the archive time-stamp. - Sign with
ApplyDigitalSignature. The validation data is collected from the CRL and OCSP addresses written in the certificates. SetIsDetachedSignature = truefor 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)
| Value | Level | What the signature contains |
|---|---|---|
Cms | CMS / PKCS#7 | A basic signature, recognized by the older software |
CadesBes | CAdES-BES (default) | The signing certificate referenced by a signed attribute |
CadesLT | CAdES-BASELINE-LT | A signature time-stamp and the certificates and revocation data, in the SignedData |
CadesLTA | CAdES-BASELINE-LTA | CAdES-LT plus an archive time-stamp v3: long-term archival |
CadesC, CadesXL, CadesA | CAdES-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.