SecureBlackbox 16: Implementing CAdES Data Signing Using SecureBlackbox

Note: This article applies only to SecureBlackbox Legacy. For future development please consider using the latest version.

There are several ways to create a CAdES signature with SecureBlackbox. One of the simplest of them is to use the TElCAdESSignatureProcessor class. Whilst creating an advanced signature is generally a nontrivial and fairly sophisticated task, TElCAdESSignatureProcessor aims to do most of the job internally and transparently to the user. TElCAdESSignatureProcessor is capable of creating CAdES signatures of all the subtypes defined in the standard (CAdES-BES, -EPES, -T, -C, -X, -XL, and -A). It can also upgrade CAdES signatures of a 'lower' subtype (e.g., CAdES-T) to an 'upper' one (e.g., CAdES-XL or CAdES-A).

Below you will find a collection of code snippets that illustrate the use of the TElCAdESSignatureProcessor class.


Content


Creating a CAdES-BES Signature

CAdES-BES ([CADES, p. 4.3.1]) is the simplest subtype of CAdES signatures, which only contain the digital signature itself and a collection of mandatory signed attributes (the message digest, content type, and signing certificate). A CAdES-BES signature can be created with the following code:

[Delphi]

// Creating an instance of the signature processor.
CAdESProcessor := TElCAdESSignatureProcessor.Create();
try
  // Creating an instance of the signed message class.
  CMS := TElSignedCMSMessage.Create(nil);
  try
    // Creating a NEW signed message.
    CMS.CreateNew(SourceStream, 0, SourceStream.Size);

    // Adding a signature.
    Sig := CMS.Signatures[CMS.AddSignature()];

    // Binding the signature to the CAdES processor.
    CAdESProcessor.Signature := Sig;

    // Creating the signature.
    CAdESProcessor.CreateBES(Cert);

    // Saving the CMS.
    CMSStream := TFileStream.Create('signature-BES.bin', fmCreate);
    try
      CMS.Save(CMSStream);
    finally
      FreeAndNil(CMSStream);
    end;
  finally
    FreeAndNil(CMS);
  end;
finally
  FreeAndNil(CAdESProcessor);
end;

[C#]

// Creating an instance of the signature processor.
TElCAdESSignatureProcessor processor = new TElCAdESSignatureProcessor();
try
{
  // Creating an instance of the signed message class.
  TElSignedCMSMessage cms = new TElSignedCMSMessage();
  try
  {
    // Creating a NEW signed message.
    cms.CreateNew(sourceStream, 0, sourceStream.Length);

    // Adding a signature.
    TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());

    // Binding the signature to the CAdES processor.
    processor.Signature = sig;

    // Creating the signature.
    processor.CreateBES(cert);

    // Saving the CMS.
    FileStream cmsStream = new FileStream(“signature-BES.bin”, FileMode.Create);
    try
    {
      cms.Save(cmsStream);
    }
    finally
    {
      cmsStream.Close();
    }
  }
  finally
  {
    cms.Dispose();
  }
}
finally
{
  processor.Dispose();
}

In the above code the SourceStream object should contain the data to be signed and should be positioned to its beginning, and the Cert object should reference a valid signing certificate with the associated private key. These requirements apply to all sample code snippets below.


Creating a CAdES-EPES Signature

CAdES-EPES ([CADES, p. 4.3.2]) is the second possible subtype of the CAdES signature, which references a signature policy in accordance with which the signature should be created and verified. The relevant code follows:

[Delphi]

// Creating an instance of the signature processor.
CAdESProcessor := TElCAdESSignatureProcessor.Create();
try
  // Creating an instance of the signed message class.
  CMS := TElSignedCMSMessage.Create(nil);
  try
    // Creating a NEW signed message.
    CMS.CreateNew(SourceStream, 0, SourceStream.Size);

    // Adding a signature.
    Sig := CMS.Signatures[CMS.AddSignature()];

    // Binding the signature to the CAdES processor.
    CAdESProcessor.Signature := Sig;

    // Creating the signature.
    CAdESProcessor.CreateEPES(Cert,
      StrToOID('1.3.6.1.4.1.34850.20001.32.1.23'),
      SB_ALGORITHM_DGST_SHA1,
      PolicyHash
    );

    // Saving the CMS.
    CMSStream := TFileStream.Create('signature-EPES.bin', fmCreate);
    try
      CMS.Save(CMSStream);
    finally
      FreeAndNil(CMSStream);
    end;
  finally
    FreeAndNil(CMS);
  end;
finally
  FreeAndNil(CAdESProcessor);
end;

[C#]

// Creating an instance of the signature processor.
TElCAdESSignatureProcessor processor = new TElCAdESSignatureProcessor();
try
{
  // Creating an instance of the signed message class.
  TElSignedCMSMessage cms = new TElSignedCMSMessage();
  try
  {
    // Creating a NEW signed message.
    cms.CreateNew(sourceStream, 0, sourceStream.Length);

    // Adding a signature.
    TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());

    // Binding the signature to the CAdES processor.
    processor.Signature = sig;

    // Creating the signature.
    processor.CreateEPES(cert,
      SBStrUtils.Unit.StrToOID(“1.3.6.1.4.1.34850.20001.32.1.23”),
      SBConstants.Unit.SB_ALGORITHM_DGST_SHA1,
      policyHash
    );

    // Saving the CMS.
    FileStream cmsStream = new FileStream(“signature-EPES.bin”, FileMode.Create);
    try
    {
      cms.Save(cmsStream);
    }
    finally
    {
      cmsStream.Close();
    }
  }
  finally
  {
    cms.Dispose();
  }
}
finally
{
  processor.Dispose();
}

Additional parameters of the CreateEPES() method are expected to contain the following values:

  • PolicyID: the object identifier of the applicable signature policy.
  • PolicyHashAlg: the hash algorithm used to calculate the policy hash.
  • PolicyHash: the result of the hash function applied to the DER encoded policy file.

Creating a CAdES-T Signature

CAdES-T ([CADES, p. 4.4.1]) extends CAdES-BES and CAdES-EPES with an external timestamp that certifies the time of signing. To be able to create CAdES-T signatures you must have access to an online TSA service that is capable of producing RFC3161-compliant timestamps.

[Delphi]

// Creating an instance of the signature processor.
CAdESProcessor := TElCAdESSignatureProcessor.Create();
try
  // Creating an instance of the signed message class.
  CMS := TElSignedCMSMessage.Create(nil);
  try
    // Creating a NEW signed message.
    CMS.CreateNew(SourceStream, 0, SourceStream.Size);

    // Adding a signature.
    Sig := CMS.Signatures[CMS.AddSignature()];

    // Binding the signature to the CAdES processor.
    CAdESProcessor.Signature := Sig;

    // Creating timestamping components.
    HttpClient := TElHTTPSClient.Create(nil);
    try
      // (!) Remember to handle the HttpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      TspClient := TElHTTPTSPClient.Create(nil);
      try
        TspClient.HTTPClient := HttpClient;
        TspClient.URL := “http://tsa.myserver.com”;
        HttpClient.SocketTimeout := 20000; // 20 seconds

        // Creating the signature.
        CAdESProcessor.CreateT(Cert, TspClient);

        // Saving the CMS.
        CMSStream := TFileStream.Create('signature-T.bin', fmCreate);
        try
          CMS.Save(CMSStream);
        finally
          FreeAndNil(CMSStream);
        end;
      finally
        FreeAndNil(TspClient);
      end;
    finally
      FreeAndNil(HttpClient);
    end;
  finally
    FreeAndNil(CMS);
  end;
finally
  FreeAndNil(CAdESProcessor);
end;

[C#]

// Creating an instance of the signature processor.
TElCAdESSignatureProcessor processor = new TElCAdESSignatureProcessor();
try
{
  // Creating an instance of the signed message class.
  TElSignedCMSMessage cms = new TElSignedCMSMessage();
  try
  {
    // Creating a NEW signed message.
    cms.CreateNew(sourceStream, 0, sourceStream.Length);

    // Adding a signature.
    TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());

    // Binding the signature to the CAdES processor.
    processor.Signature = sig;

    // Creating timestamping components.
    httpClient = new TElHTTPSClient();
    try
    {
      // (!) Remember to handle the httpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      tspClient = new TElHTTPTSPClient();
      try
      {
        tspClient.HTTPClient = httpClient;
        tspClient.URL = “http://tsa.myserver.com”;
        httpClient.SocketTimeout = 20000; // 20 seconds

        // Creating the signature.
        processor.CreateT(cert, tspClient);

        // Saving the CMS.
        FileStream cmsStream = new FileStream(“signature-T.bin”, FileMode.Create);
        try
        {
          cms.Save(cmsStream);
        }
        finally
        {
          cmsStream.Close();
        }
      }
      finally
      {
        tspClient.Dispose();
      }
    }
    finally
    {
      httpClient.Dispose();
    }
  }
  finally
  {
    cms.Dispose();
  }
}
finally
{
  processor.Dispose();
}

The CreateT() method creates a CAdES-BES message and applies a timestamp to it.


Creating a CAdES-C Signature

CAdES-C ([CADES, p. 4.4.2]) extends a signature of the CAdES-T type with complete certificate and revocation element references to allow the verifier to reconstruct the PKI environment in its revision at the moment of signing. Only including the references and not the whole elements themselves helps reduce the signature size for the cases where verifiers are known to have access to all past revisions of the validation elements.

[Delphi]

// Creating an instance of signature processor.
CAdESProcessor := TElCAdESSignatureProcessor.Create();
try
  // Creating an instance of the signed message class.
  CMS := TElSignedCMSMessage.Create(nil);
  try
    // Creating NEW signed message.
    CMS.CreateNew(SourceStream, 0, SourceStream.Size);

    // Adding a signature.
    Sig := CMS.Signatures[CMS.AddSignature()];

    // Binding the signature to the CAdES processor.
    CAdESProcessor.Signature := Sig;

    // Creating timestamping components.
    HttpClient := TElHTTPSClient.Create(nil);
    try
      // (!) Remember to handle the HttpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      TspClient := TElHTTPTSPClient.Create(nil);
      try
        TspClient.HTTPClient := HttpClient;
        TspClient.URL := “http://tsa.myserver.com”;
        HttpClient.SocketTimeout := 20000; // 20 seconds

        // Creating the signature.
        CAdESProcessor.CreateC(Cert, TspClient);

        // Saving the CMS.
        CMSStream := TFileStream.Create('signature-C.bin', fmCreate);
        try
          CMS.Save(CMSStream);
        finally
          FreeAndNil(CMSStream);
        end;
      finally
        FreeAndNil(TspClient);
      end;
    finally
      FreeAndNil(HttpClient);
    end;
  finally
    FreeAndNil(CMS);
  end;
finally
  FreeAndNil(CAdESProcessor);
end;

[C#]

// Creating an instance of signature processor.
TElCAdESSignatureProcessor processor = new TElCAdESSignatureProcessor();
try
{
  // Creating an instance of the signed message class.
  TElSignedCMSMessage cms = new TElSignedCMSMessage();
  try
  {
    // Creating NEW signed message.
    cms.CreateNew(sourceStream, 0, sourceStream.Length);

    // Adding a signature.
    TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());

    // Binding the signature to the CAdES processor.
    processor.Signature = sig;

    // Creating timestamping components.
    httpClient = new TElHTTPSClient();
    try
    {
      // (!) Remember to handle the httpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      tspClient = new TElHTTPTSPClient();
      try
      {
        tspClient.HTTPClient = httpClient;
        tspClient.URL = “http://tsa.myserver.com”;
        httpClient.SocketTimeout = 20000; // 20 seconds

        // Creating the signature.
        processor.CreateC(cert, tspClient);

        // Saving the CMS.
        FileStream cmsStream = new FileStream(“signature-C.bin”, FileMode.Create);
        try
        {
          cms.Save(cmsStream);
        }
        finally
        {
          cmsStream.Close();
        }
      }
      finally
      {
        tspClient.Dispose();
      }
    }
    finally
    {
      httpClient.Dispose();
    }
  }
  finally
  {
    cms.Dispose();
  }
}
finally
{
  processor.Dispose();
}

CAdES-C is the first signature subtype so far to involve deep certificate validation during the signing process. The procedure of deep validation consists of the construction of the complete certificate chain and validation of each certificate using offline and/or online revocation information provisioning services (CRL and OCSP responders). Please remember to register relevant component factories before signing (see below) if you plan to use online PKI services in your project.


Creating a CAdES-X Signature

CAdES-X (types 1 and 2) ([CADES, pp. 4.4.3.2 and 4.4.3.3]) extends a CAdES-C signature with a validation timestamp over the entire CAdES-C structure (type 1) or the certificate and revocation references only (type 2). The validation timestamp provides an external trusted third party certification of the validation elements, thus allowing verifiers to establish the integrity of those elements at the moment of signing.

[Delphi]

// Creating an instance of signature processor.
CAdESProcessor := TElCAdESSignatureProcessor.Create();
try
  // Creating an instance of the signed message class.
  CMS := TElSignedCMSMessage.Create(nil);
  try
    // Creating NEW signed message.
    CMS.CreateNew(SourceStream, 0, SourceStream.Size);

    // Adding a signature.
    Sig := CMS.Signatures[CMS.AddSignature()];

    // Binding the signature to the CAdES processor.
    CAdESProcessor.Signature := Sig;

    // Creating timestamping components.
    HttpClient := TElHTTPSClient.Create(nil);
    try
      // (!) Remember to handle the HttpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      TspClient := TElHTTPTSPClient.Create(nil);
      try
        TspClient.HTTPClient := HttpClient;
        TspClient.URL := “http://tsa.myserver.com”;
        HttpClient.SocketTimeout := 20000; // 20 seconds

        // Creating the signature.
        CAdESProcessor.CreateX1(Cert, TspClient, TspClient);

        // Saving the CMS.
        CMSStream := TFileStream.Create('signature-X1.bin', fmCreate);
        try
          CMS.Save(CMSStream);
        finally
          FreeAndNil(CMSStream);
        end;
      finally
        FreeAndNil(TspClient);
      end;
    finally
      FreeAndNil(HttpClient);
    end;
  finally
    FreeAndNil(CMS);
  end;
finally
  FreeAndNil(CAdESProcessor);
end;

[C#]

// Creating an instance of signature processor.
TElCAdESSignatureProcessor processor = new TElCAdESSignatureProcessor();
try
{
  // Creating an instance of the signed message class.
  TElSignedCMSMessage cms = new TElSignedCMSMessage();
  try
  {
    // Creating NEW signed message.
    cms.CreateNew(sourceStream, 0, sourceStream.Length);

    // Adding a signature.
    TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());

    // Binding the signature to the CAdES processor.
    processor.Signature = sig;

    // Creating timestamping components.
    httpClient = new TElHTTPSClient();
    try
    {
      // (!) Remember to handle the httpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      tspClient = new TElHTTPTSPClient();
      try
      {
        tspClient.HTTPClient = httpClient;
        tspClient.URL = “http://tsa.myserver.com”;
        httpClient.SocketTimeout = 20000; // 20 seconds

        // Creating the signature.
        processor.CreateX1(cert, tspClient, tspClient);

        // Saving the CMS.
        FileStream cmsStream = new FileStream(“signature-X1.bin”, FileMode.Create);
        try
        {
          cms.Save(cmsStream);
        }
        finally
        {
          cmsStream.Close();
        }
      }
      finally
      {
        tspClient.Dispose();
      }
    }
    finally
    {
      httpClient.Dispose();
    }
  }
  finally
  {
    cms.Dispose();
  }
}
finally
{
  processor.Dispose();
}

Note that the CreateX1() and CreateX2() methods accept two TSP client objects. The first object is used to request a signature timestamp (used to produce a CAdES-T signature), and the second one to request a validation timestamp over the CAdES-C blob or the validation references.

Just as in the CAdES-C case, the creation of CAdES-X signatures involves deep certificate validation.


Creating a CAdES-XL Signature

CAdES-XL ([CADES, p. 4.4.3.4]) is obtained from CAdES-X by inserting the values of the referenced validation elements (certificates, CRLs, and OCSP responses) to the signature blob. The CAdES-XL signature is thus a self-contained signature that does not require any external certificate or revocation provisioning services to be successfully validated.

[Delphi]

// Creating an instance of signature processor.
CAdESProcessor := TElCAdESSignatureProcessor.Create();
try
  // Creating an instance of the signed message class.
  CMS := TElSignedCMSMessage.Create(nil);
  try
    // Creating NEW signed message.
    CMS.CreateNew(SourceStream, 0, SourceStream.Size);

    // Adding a signature.
    Sig := CMS.Signatures[CMS.AddSignature()];

    // Binding the signature to the CAdES processor.
    CAdESProcessor.Signature := Sig;

    // Creating timestamping components.
    HttpClient := TElHTTPSClient.Create(nil);
    try
      // (!) Remember to handle the HttpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      TspClient := TElHTTPTSPClient.Create(nil);
      try
        TspClient.HTTPClient := HttpClient;
        TspClient.URL := “http://tsa.myserver.com”;
        HttpClient.SocketTimeout := 20000; // 20 seconds

        // Creating the signature.
        CAdESProcessor.CreateXL1(Cert, TspClient, TspClient);

        // Saving the CMS.
        CMSStream := TFileStream.Create('signature-XL1.bin', fmCreate);
        try
          CMS.Save(CMSStream);
        finally
          FreeAndNil(CMSStream);
        end;
      finally
        FreeAndNil(TspClient);
      end;
    finally
      FreeAndNil(HttpClient);
    end;
  finally
    FreeAndNil(CMS);
  end;
finally
  FreeAndNil(CAdESProcessor);
end;

[C#]

// Creating an instance of signature processor.
TElCAdESSignatureProcessor processor = new TElCAdESSignatureProcessor();
try
{
  // Creating an instance of the signed message class.
  TElSignedCMSMessage cms = new TElSignedCMSMessage();
  try
  {
    // Creating NEW signed message.
    cms.CreateNew(sourceStream, 0, sourceStream.Length);

    // Adding a signature.
    TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());

    // Binding the signature to the CAdES processor.
    processor.Signature = sig;

    // Creating timestamping components.
    httpClient = new TElHTTPSClient();
    try
    {
      // (!) Remember to handle the httpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      tspClient = new TElHTTPTSPClient();
      try
      {
        tspClient.HTTPClient = httpClient;
        tspClient.URL = “http://tsa.myserver.com”;
        httpClient.SocketTimeout = 20000; // 20 seconds

        // Creating the signature.
        processor.CreateXL1(cert, tspClient, tspClient);

        // Saving the CMS.
        FileStream cmsStream = new FileStream(“signature-XL1.bin”, FileMode.Create);
        try
        {
          cms.Save(cmsStream);
        }
        finally
        {
          cmsStream.Close();
        }
      }
      finally
      {
        tspClient.Dispose();
      }
    }
    finally
    {
      httpClient.Dispose();
    }
  }
  finally
  {
    cms.Dispose();
  }
}
finally
{
  processor.Dispose();
}

Note that the CreateXL1() and CreateXL2() methods accept two TSP client objects. The first object is used to request a signature timestamp (used to produce a CAdES-T signature), and the second one to request a validation timestamp over the CAdES-C blob or the validation references.

Just as in the CAdES-C and CAdES-X cases, the creation of CAdES-X signatures involves deep certificate validation.


Creating a CAdES-A (Archival) Signature

The CAdES-A subtype ([CADES, p. 4.4.4]) builds on a CAdES-C or CAdES-XL signature by adding one or more archival timestamps. CAdES-A is used for long-term archival of electronic signatures. Successive timestamps protect the whole signature material against vulnerable hashing algorithms and the expiration/termination of the PKI services used at the time when the signature and/or previous archival timestamps were created.

[Delphi]

// Creating an instance of signature processor.
CAdESProcessor := TElCAdESSignatureProcessor.Create();
try
  // Creating an instance of the signed message class.
  CMS := TElSignedCMSMessage.Create(nil);
  try
    // Opening existing signed message.
    CMS.Open(SigStream, nil);

    // Obtaining the signature object.
    Sig := CMS.Signatures[0];

    // Binding the signature to the CAdES processor.
    CAdESProcessor.Signature := Sig;

    // Creating timestamping components.
    HttpClient := TElHTTPSClient.Create(nil);
    try
      // (!) Remember to handle the HttpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      TspClient := TElHTTPTSPClient.Create(nil);
      try
        TspClient.HTTPClient := HttpClient;
        TspClient.URL := “http://tsa.myserver.com”;
        HttpClient.SocketTimeout := 20000; // 20 seconds

        // Creating the signature.
        if FCAdESProcessor.IsT() then
          // A signature timestamp is already included.
          CAdESProcessor.UpgradeToA(TspClient)
        else
          // No signature timestamp yet, passing two TSP client objects.
          CAdESProcessor.UpgradeToA(TspClient, TspClient);

        // Saving the CMS.
        CMSStream := TFileStream.Create('signature-A.bin', fmCreate);
        try
          CMS.Save(CMSStream);
        finally
          FreeAndNil(CMSStream);
        end;
      finally
        FreeAndNil(TspClient);
      end;
    finally
      FreeAndNil(HttpClient);
    end;
  finally
    FreeAndNil(CMS);
  end;
finally
  FreeAndNil(CAdESProcessor);
end;

[C#]

// Creating an instance of signature processor.
TElCAdESSignatureProcessor processor = new TElCAdESSignatureProcessor();
try
{
  // Creating an instance of the signed message class.
  TElSignedCMSMessage cms = new TElSignedCMSMessage();
  try
  {
    // Creating NEW signed message.
    cms.Open(sigStream, null, 0, 0);

    // Adding a signature.
    TElCMSSignature sig = cms.get_Signatures(0);

    // Binding the signature to the CAdES processor.
    processor.Signature = sig;

    // Creating timestamping components.
    httpClient = new TElHTTPSClient();
    try
    {
      // (!) Remember to handle the httpClient's OnCertificateValidate
      // event if the TSA server is accessible via HTTPS protocol.

      tspClient = new TElHTTPTSPClient();
      try
      {
        tspClient.HTTPClient = httpClient;
        tspClient.URL = “http://tsa.myserver.com”;
        httpClient.SocketTimeout = 20000; // 20 seconds

        // Creating the signature.
        if (processor.IsT())
        {
          // A signature timestamp is already included.
          processor.UpgradeToA(tspClient)
        }
        else
        {
          // No signature timestamp yet, passing two TSP client objects.
          processor.UpgradeToA(tspClient, tspClient);
        }

        // Saving the CMS.
        FileStream cmsStream = new FileStream(“signature-A.bin”, FileMode.Create);
        try
        {
          cms.Save(cmsStream);
        }
        finally
        {
          cmsStream.Close();
        }
      }
      finally
      {
        tspClient.Dispose();
      }
    }
    finally
    {
      httpClient.Dispose();
    }
  }
  finally
  {
    cms.Dispose();
  }
}
finally
{
  processor.Dispose();
}

Note that unlike previous subtypes, you can't create a CAdES-A signature from scratch. Instead, you should create a signature of a lower subtype (e.g., CAdES-XL) and then upgrade it to CAdES-A.


Preparing and Tuning the TElCAdESSignatureProcessor Object

Each PKI environment is different, so you will probably need to tune up the TElCAdESSignatureProcessor object to match your particular one. Not only are there are plenty of configuration aspects that might affect the deep validation process (such as the locations of revocation status provisioning sources and connectivity options), but also the CAdES standard as well had undertaken a number of reviews, improvements, and breaking changes since it appeared in 2001.

ForceSigningCertificateV2 Specifies whether the signing certificate reference should be included in form of the ESS-signing-certificate-v2 (default) or ESS-signing-certificate attribute.
ValidationMoment Use this property to set the moment of time at which the signature should be validated. Leave intact to use the current time from the local computer.
ForceCompleteChainValidation Controls whether the component should validate the whole certificate chain up to the trusted certificate. This can be switched off for debugging or testing purposes to suppress validation exceptions.
IgnoreChainValidationErrors Set this property to true to suppress validation exceptions if the component fails to validate the chain for some reason (e.g., a missing CRL or CA certificate). This option may be useful when creating signatures using nonvalidated certificate chains, but may pose a security flaw if used when validating signatures.
PerformRevocationCheck Specifies whether the component should perform revocation checks against CRL and OCSP servers or local revocation information. If the property is switched off, no revocation checking will be performed.
OfflineMode Tells the component that no internet connections should be attempted when validating the chain. Ensure that the appropriate certificates and revocation elements are available to the component (either in the body of the signature or locally) when switching this property on; otherwise, you might come across chain validation issues.
DeepTimestampValidation Specifies if deep validation should be performed for timestamp elements.
DeepCountersignatureValidation Specifies if deep validation should be performed for countersignature elements.
TrustedCertificates Allows you to provide a separate list of trusted certificates for use during the validation process.
AllowPartialValidationInfo Lets the component finalize and complete the signature even if it was unable to collect the complete validation information.
SkipValidationTimestampedSignatures Tells the component to skip the renewal of revocation information for signatures that contain validation timestamps (that is, CAdES-X, CAdES-XL, and CAdES-A), as those timestamps 'lock' them. If this property is set to false and an upgrade is attempted for a signature with a validation timestamp inside, an exception will be thrown.
GracePeriod A period of 'idle time' (in milliseconds) between the moments of creation of a CAdES-T signature and collection of validation information for upgrading to a higher signature subtype, to allow the revocation status update to propagate through the PKI environment up to the revocation status responders.
ReportInvalidTimestamps Specifies if the component should throw exceptions if an invalid timestamp is encountered in the signature during the validation. Switching this property off may present a security flaw.
AddReferenceToSigningCert Tells the component to add a reference to the signing certificate to the certificate-references and certificate-values attributes. While doing this is against the requirements of the CAdES standard, some verifying tools erroneously require the signing certificate to be referenced in those attributes.
AddReferencesToIrrevocableCerts Tells the component to include certificates that do not have associated revocation information providers to the certificate-references and certificate-values attributes (compliance: same as above).
AddReferencesToAllUsedCertsAndRevInfo Tells the component to include all certificates used during the deep validation process (even those belonging to third parties, such as OCSP responders) to the certificate-references and certificate-values attributes (compliance: same as above).

Sometimes there is a need to get a detailed trace of the chain validation process (to find a reason for a reported validation issue, for example). TElCAdESSignatureProcessor performs the validation internally with the use of the TElX509CertificateValidator component. To get access to this component and a collection of its tracing events, handle the OnCertValidatorPrepared event.

You can also use the event to perform a finer tuning of the TElX509CertificateValidator component.


Registering Revocation Retriever Factories

The TElCAdESSignatureProcessor and TElX509CertificateValidator classes use revocation information retrievers to obtain various pieces of validation information during the deep validation process. The retrievers are created by four object factories, responsible for different kinds of online services. In most public PKI environments, it is enough to register the HTTP OCSP and HTTP CRL factories, while private and corporate environments might require LDAP connectivity as well. In projects built against the .NET, Java, and C++ product editions the factories should be populated manually with the following code:


// Registering HTTP OCSP client
SBHTTPOCSPClient.Unit.RegisterHTTPOCSPClientFactory();

// Registering HTTP CRL retriever
SBHTTPCRL.Unit.RegisterHTTPCRLRetrieverFactory();

// Registering LDAP CRL retriever
SBLDAPCRL.Unit.RegisterLDAPCRLRetrieverFactory();

// Registering LDAP certificate retriever
SBLDAPCertRetriever.Unit.RegisterLDAPCertificateRetrieverFactory();

In Delphi environments the retrievers are registered automatically, provided that you've referenced the corresponding units in your project's or form's uses clause:

uses
  SBHTTPOCSPClient, SBHTTPCRL, SBLDAPCRL, SBLDAPCertRetriever;

References

[CADES]: Electronic Signatures and Infrastructures (ESI); CMS Advanced Electronic Signatures (CAdES), ETSI TS 101 733 V2.1.1.

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.