Pular para o conteúdo principal

CAdES signatures

The CAdES standard lets you sign any binary file. The @Lacuna.Pki.Cades.CadesSigner class creates, customizes and assembles the CMS signature package.

Basic signature example​

The code below shows a basic CAdES signature, to introduce and exercise the concepts and properties of this signer.

// Instantiate the signer object, which creates the signature
var signer = new CadesSigner();

signer.SetSigningCertificate(signingCert); // the signer's certificate, with its private key
signer.SetDataToSign(toSign); // bytes or stream of the document to sign
signer.SetPolicy(CadesPolicySpec.GetCadesBes()); // CAdES-BES signature policy, with the Windows roots as TrustArbitrator
signer.ComputeSignature(); // creates the attributes and gets the signer's signature

var cadesSig = signer.GetSignature(); // assembles the signature package and returns its BER-encoded bytes

Advanced signature example​

Below is a CAdES signature with the ICP-Brasil AD-RT signature policy (with a timestamp), followed by a description of each Set method used on the signer.

PKCertificateWithKey signingCert = ...
byte[] toSign = ...

// ICP-Brasil AD-RT signature policy
var policy = BrazilCadesPolicySpec.GetAdrTempoV21();

// Timestamp requester for the timestamp authority at tsUri
var tsRequester = new TimestampRequester(tsUri);

// Instantiate the signer object, which creates the signature
var signer = new CadesSigner();

signer.SetSigningCertificate(signingCert); // the signer's certificate, with its private key
signer.SetDataToSign(toSign); // bytes or stream of the data to sign
signer.SetPolicy(policy); // signature policy
signer.SetTimestampRequester(tsRequester); // timestamp requester
signer.ComputeSignature(); // creates the attributes and gets the signer's signature

var cadesSig = signer.GetSignature(); // assembles the signature package and returns its BER-encoded bytes
  • @Lacuna.Pki.Cades.CadesSigner.SetSigningCertificate(Lacuna.Pki.PKCertificateWithKey) - Sets the signer's certificate. The example uses a certificate with its private key. For how to load a certificate with its private key, see Certificates with private key.

  • @Lacuna.Pki.Cades.CadesSigner.SetDataToSign(System.Byte[]) - Sets the data to sign. The CAdES standard lets you sign any kind of binary file or data.

  • @Lacuna.Pki.Cades.CadesSigner.SetPolicy(Lacuna.Pki.Cades.CadesPolicySpec) - Sets the signature policy. The SDK has policies already configured for the standards of some PKIs, such as ICP-Brasil, and also lets you create or customize your own policy. The example passes a policy already configured for the ICP-Brasil AD-RT standard. For more information on signature policies, see Signature policies.

  • @Lacuna.Pki.Cades.CadesSigner.SetTimestampRequester(Lacuna.Pki.ITimestampRequester) - Sets a requester that gets timestamps from a timestamp authority. The signature policy in the example (ICP-Brasil AD-RT) requires a timestamp, so the signer needs a timestamp requester.

Remote signature​

The @Lacuna.Pki.Cades.CadesSigner signer can also create a CAdES signature whose signing happens remotely, for instance in the user's browser. In that case, the signer is set with a certificate without a private key: @Lacuna.Pki.Cades.CadesSigner.SetSigningCertificate(Lacuna.Pki.PKCertificate). You also use the method that generates the data the client signs (Lacuna.Pki.Cades.CadesSigner.GenerateToSignBytes(Lacuna.Pki.SignatureAlgorithm@)) and the method that puts the signed data into the CAdES signature (Lacuna.Pki.Cades.CadesSigner.SetPrecomputedSignature(System.Byte[])).

For more information on remote signatures, see Signing with a remote key (signature in the browser).

Signature validation​

With PKI SDK you can validate the whole signature package against a single policy:

CadesSignature signature = ...

Dictionary<CadesSignerInfo,ValidationResults> validationResults = signature.ValidateAllSignatures(CadesPoliciesForValidation.GetCadesBasic());

foreach (var item in validationResults) {
Console.WriteLine("Passed checks:");
item.Value.PassedChecks.ForEach(vi => Console.WriteLine(vi.Detail)); // prints every check that passed

if (item.Value.HasErrors) { // if there are errors
Console.WriteLine("Errors:");
item.Value.Errors.ForEach(e => Console.WriteLine(e.Message)); // prints why the checks failed
}
}

Or validate each signature against the policy you want:


var cadesSig = ...
var myIssuer = ...

CadesSignature signature = CadesSignature.Open(cadesSig);
foreach (var signerInfo in signature.Signers) {

var policyMapper = signerInfo.SigningCertificate.Issuer.Equals(myIssuer) // if the certificate was issued by my company's issuer, outside the Windows roots
? CadesPoliciesForValidation.GetCadesBasic(new CustomArbitrator()) // use a custom trust arbitrator that trusts my issuer
: CadesPoliciesForValidation.GetCadesBasic(); // otherwise use the Windows roots as trusted roots

ValidationResults result = signature.ValidateSignature(signerInfo, policyMapper); // validates the signature against the given policy

Console.WriteLine("Passed checks:");
result.PassedChecks.ForEach(vi => Console.WriteLine(vi.Detail)); // prints every check that passed
if (result.HasErrors) {
Console.WriteLine("Errors:");
result.Errors.ForEach(e => Console.WriteLine($"{e.Message} - {e.Detail}")); // prints why the checks failed
}
}

See also​

View as Markdown