---
title: "Asynchronous signature finishing"
description: "Asynchronous finishing of CAdES signatures in PKI SDK: a more reliable and faster process that withstands CRL, OCSP and timestamp failures."
canonical: "https://docs.lacunasoftware.com/en-us/articles/pki-sdk/signatures/cades/finisher"
locale: "en"
product: "PKI SDK"
last_updated: "2026-10-12"
---

# Asynchronous signature finishing

Asynchronous signature finishing is an approach PKI SDK offers for a more reliable and efficient signature process. It has
the following advantages:

* It withstands failures in the distribution of CRLs/OCSPs and of timestamps.
* The synchronous part of the process is faster, because it no longer waits for the responses of CRL, OCSP or timestamp
  requests.
* It allows signature policies with a grace period.

The client's signature is requested only once and saved, which ends the process for the user. Later, in a
*background worker* for instance, the online or cached requests and checks are performed and the signature is finished. If
this second step has problems, there is no need to ask the client to sign again.

## Signature finisher

The @Lacuna.Pki.Cades.CadesSignatureFinisher class handles signature finishing. Below is an example of the finisher,
followed by a description of the methods it uses.

First, we create an unfinished signature:

```cs
// Basic CAdES signature
var signer = new CadesSigner();
signer.SetSigningCertificate(signingCert);
signer.SetDataToSign(toSign);
signer.SetPolicy(policy);

// Before calling ComputeSignature(),
// set the signature not to be finished
signer.SetFinishSignature(false);

signer.ComputeSignature();
var cadesSig = signer.GetSignature();       // returns the unfinished signature package

// Save the unfinished signature and end the process
```

Later, in a *background worker* (a Windows service or a scheduled task), we finish the signature:

```cs
// Loading the unfinished signature
byte[] cadesSig = ...

// Instantiating the finisher with the unfinished signature
var finisher = new CadesSignatureFinisher(CadesSignature.Open(cadesSig));
finisher.SetPolicy(policy);
finisher.SetTimestampRequester(tsRequester);          // timestamp requester (if the policy requires a timestamp)
finisher.UseOnlyCrlsIssuedAfterGracePeriod = true;    // use only revocation values issued after the grace period ends

finisher.PerformStep();
if (finisher.IsSignatureFinished) {
    // Signature finished
    // Returns the BER-encoded bytes of the finished signature
    var finishedCadesSig = finisher.GetSignatureEncoded();
} else {
    // Returns the suggested delay before calling the finishing service again with PerformStep()
    var delay = finisher.NextStepDelay.Value;

    // or

    // Returns the suggested time for the next call to the finishing service with PerformStep()
    var time = finisher.NextStepTime.Value;
}
```

* @Lacuna.Pki.Cades.CadesSignatureFinisher.SetPolicy(Lacuna.Pki.Cades.CadesPolicySpec) /
  @Lacuna.Pki.Cades.CadesSignatureFinisher.SetPolicyMapper(Lacuna.Pki.Cades.ICadesPolicyMapper) /
  @Lacuna.Pki.Cades.CadesSignatureFinisher.SetPolicyMapper(Lacuna.Pki.Cades.ICadesPolicyMapperBySignerInfo) -
  Set the signature policy for finishing. Ideally it is the same policy used on the signer, but at this second stage only
  its timestamp, revocation value and reference, and certificate properties are used.

* @Lacuna.Pki.Cades.CadesSignatureFinisher.SetTimestampRequester(Lacuna.Pki.ITimestampRequester) -
  Used if the signature policy requires a timestamp.

* @Lacuna.Pki.Cades.CadesSignatureFinisher.UseOnlyCrlsIssuedAfterGracePeriod -
  Requires the revocation values checked to have been issued after the grace period. For more information on grace periods,
  see [Policies with a grace period](https://docs.lacunasoftware.com/en-us/articles/pki-sdk/signatures/policies/grace-period).

* @Lacuna.Pki.Cades.CadesSignatureFinisher.PerformStep -
  The engine of the signature finisher: it fetches what is needed to finish the signature and, if the policy has a grace
  period that has not ended yet, tells when to run it again.

## See also

* @Lacuna.Pki.Cades.CadesSignatureFinisher
