Implementing CAdES signing of data using SecureBlackbox

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 non-trivial 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 TElCAdESSignatureProcessor class.


Content


Creating a CAdES-BES signature

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

[Delphi]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. CAdESProcessor := TElCAdESSignatureProcessor.Create();
  3. <span class="keyword">try</span>
  4. <span class="comment">// Creating an instance of the signed message class.</span>
  5. CMS := TElSignedCMSMessage.Create(<span class="keyword">nil</span>);
  6. <span class="keyword">try</span>
  7. <span class="comment">// Creating NEW signed message.</span>
  8. CMS.CreateNew(SourceStream, <span class="number">0</span>, SourceStream.Size);
  9. &nbsp;
  10. <span class="comment">// Adding a signature.</span>
  11. Sig := CMS.Signatures[CMS.AddSignature()];
  12. &nbsp;
  13. <span class="comment">// Binding the signature to the CAdES processor.</span>
  14. CAdESProcessor.Signature := Sig;
  15. &nbsp;
  16. <span class="comment">// Creating the signature.</span>
  17. CAdESProcessor.CreateBES(Cert);
  18. <span class="comment">// Saving the CMS.</span>
  19. CMSStream := TFileStream.Create(‘signature-BES.bin’, fmCreate);
  20. <span class="keyword">try</span>
  21. CMS.Save(CMSStream);
  22. <span class="keyword">finally</span>
  23. FreeAndNil(CMSStream);
  24. <span class="keyword">end</span>;
  25. <span class="keyword">finally</span>
  26. FreeAndNil(CMS);
  27. <span class="keyword">end</span>;
  28. <span class="keyword">finally</span>
  29. FreeAndNil(CAdESProcessor);
  30. <span class="keyword">end</span>;

[C#]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. TElCAdESSignatureProcessor processor = <span class="keyword">new</span> TElCAdESSignatureProcessor();
  3. <span class="keyword">try</span>
  4. {
  5. <span class="comment">// Creating an instance of the signed message class.</span>
  6. TElSignedCMSMessage cms = <span class="keyword">new</span> TElSignedCMSMessage();
  7. <span class="keyword">try</span>
  8. {
  9. <span class="comment">// Creating NEW signed message.</span>
  10. cms.CreateNew(sourceStream, <span class="number">0</span>, sourceStream.Length);
  11. &nbsp;
  12. <span class="comment">// Adding a signature.</span>
  13. TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());
  14. &nbsp;
  15. <span class="comment">// Binding the signature to the CAdES processor.</span>
  16. processor.Signature = sig;
  17. &nbsp;
  18. <span class="comment">// Creating the signature.</span>
  19. processor.CreateBES(cert);
  20. <span class="comment">// Saving the CMS.</span>
  21. FileStream cmsStream = <span class="keyword">new</span> FileStream(“signature-BES.bin”, FileMode.Create);
  22. <span class="keyword">try</span>
  23. {
  24. cms.Save(cmsStream);
  25. }
  26. <span class="keyword">finally</span>
  27. {
  28. cmsStream.Close();
  29. }
  30. }
  31. <span class="keyword">finally</span>
  32. {
  33. cms.Dispose();
  34. }
  35. }
  36. <span class="keyword">finally</span>
  37. {
  38. processor.Dispose();
  39. }

In the above code the SourceStream object should contain the data to be signed and 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 a second possible subtype of CAdES signature which references a signature policy in accordance with which the signature should be created and verified. The relevant code follows:

[Delphi]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. CAdESProcessor := TElCAdESSignatureProcessor.Create();
  3. <span class="keyword">try</span>
  4. <span class="comment">// Creating an instance of the signed message class.</span>
  5. CMS := TElSignedCMSMessage.Create(<span class="keyword">nil</span>);
  6. <span class="keyword">try</span>
  7. <span class="comment">// Creating NEW signed message.</span>
  8. CMS.CreateNew(SourceStream, <span class="number">0</span>, SourceStream.Size);
  9. &nbsp;
  10. <span class="comment">// Adding a signature.</span>
  11. Sig := CMS.Signatures[CMS.AddSignature()];
  12. &nbsp;
  13. <span class="comment">// Binding the signature to the CAdES processor.</span>
  14. CAdESProcessor.Signature := Sig;
  15. &nbsp;
  16. <span class="comment">// Creating the signature.</span>
  17. CAdESProcessor.CreateEPES(Cert,
  18. StrToOID(‘<span class="number">1.3</span>.<span class="number">6.1</span>.<span class="number">4.1</span>.<span class="number">34850.20001</span>.<span class="number">32.1</span>.<span class="number">23</span>’),
  19. SB_ALGORITHM_DGST_SHA1,
  20. PolicyHash
  21. );
  22. <span class="comment">// Saving the CMS.</span>
  23. CMSStream := TFileStream.Create(‘signature-EPES.bin’, fmCreate);
  24. <span class="keyword">try</span>
  25. CMS.Save(CMSStream);
  26. <span class="keyword">finally</span>
  27. FreeAndNil(CMSStream);
  28. <span class="keyword">end</span>;
  29. <span class="keyword">finally</span>
  30. FreeAndNil(CMS);
  31. <span class="keyword">end</span>;
  32. <span class="keyword">finally</span>
  33. FreeAndNil(CAdESProcessor);
  34. <span class="keyword">end</span>;

[C#]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. TElCAdESSignatureProcessor processor = <span class="keyword">new</span> TElCAdESSignatureProcessor();
  3. <span class="keyword">try</span>
  4. {
  5. <span class="comment">// Creating an instance of the signed message class.</span>
  6. TElSignedCMSMessage cms = <span class="keyword">new</span> TElSignedCMSMessage();
  7. <span class="keyword">try</span>
  8. {
  9. <span class="comment">// Creating NEW signed message.</span>
  10. cms.CreateNew(sourceStream, <span class="number">0</span>, sourceStream.Length);
  11. &nbsp;
  12. <span class="comment">// Adding a signature.</span>
  13. TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());
  14. &nbsp;
  15. <span class="comment">// Binding the signature to the CAdES processor.</span>
  16. processor.Signature = sig;
  17. &nbsp;
  18. <span class="comment">// Creating the signature.</span>
  19. processor.CreateEPES(cert,
  20. SBStrUtils.Unit.StrToOID(“<span class="number">1.3</span>.<span class="number">6.1</span>.<span class="number">4.1</span>.<span class="number">34850.20001</span>.<span class="number">32.1</span>.<span class="number">23</span>”),
  21. SBConstants.Unit.SB_ALGORITHM_DGST_SHA1,
  22. policyHash
  23. );
  24. <span class="comment">// Saving the CMS.</span>
  25. FileStream cmsStream = <span class="keyword">new</span> FileStream(“signature-EPES.bin”, FileMode.Create);
  26. <span class="keyword">try</span>
  27. {
  28. cms.Save(cmsStream);
  29. }
  30. <span class="keyword">finally</span>
  31. {
  32. cmsStream.Close();
  33. }
  34. }
  35. <span class="keyword">finally</span>
  36. {
  37. cms.Dispose();
  38. }
  39. }
  40. <span class="keyword">finally</span>
  41. {
  42. processor.Dispose();
  43. }

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 signature ([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]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. CAdESProcessor := TElCAdESSignatureProcessor.Create();
  3. <span class="keyword">try</span>
  4. <span class="comment">// Creating an instance of the signed message class.</span>
  5. CMS := TElSignedCMSMessage.Create(<span class="keyword">nil</span>);
  6. <span class="keyword">try</span>
  7. <span class="comment">// Creating NEW signed message.</span>
  8. CMS.CreateNew(SourceStream, <span class="number">0</span>, SourceStream.Size);
  9. &nbsp;
  10. <span class="comment">// Adding a signature.</span>
  11. Sig := CMS.Signatures[CMS.AddSignature()];
  12. &nbsp;
  13. <span class="comment">// Binding the signature to the CAdES processor.</span>
  14. CAdESProcessor.Signature := Sig;
  15. &nbsp;
  16. <span class="comment">// Creating timestamping components.</span>
  17. HttpClient := TElHTTPSClient.Create(<span class="keyword">nil</span>);
  18. <span class="keyword">try</span>
  19. <span class="comment">// (!) Remember to handle the HttpClient’s OnCertificateValidate</span>
  20. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  21. &nbsp;
  22. TspClient := TElHTTPTSPClient.Create(<span class="keyword">nil</span>);
  23. <span class="keyword">try</span>
  24. TspClient.HTTPClient := HttpClient;
  25. TspClient.URL := “http:<span class="comment">//tsa.myserver.com”;</span>
  26. HttpClient.SocketTimeout := <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  27. &nbsp;
  28. <span class="comment">// Creating the signature.</span>
  29. CAdESProcessor.CreateT(Cert, TspClient);
  30. <span class="comment">// Saving the CMS.</span>
  31. CMSStream := TFileStream.Create(‘signature-T.bin’, fmCreate);
  32. <span class="keyword">try</span>
  33. CMS.Save(CMSStream);
  34. <span class="keyword">finally</span>
  35. FreeAndNil(CMSStream);
  36. <span class="keyword">end</span>;
  37. <span class="keyword">finally</span>
  38. FreeAndNil(TspClient);
  39. <span class="keyword">end</span>;
  40. <span class="keyword">finally</span>
  41. FreeAndNil(HttpClient);
  42. <span class="keyword">end</span>;
  43. <span class="keyword">finally</span>
  44. FreeAndNil(CMS);
  45. <span class="keyword">end</span>;
  46. <span class="keyword">finally</span>
  47. FreeAndNil(CAdESProcessor);
  48. <span class="keyword">end</span>;

[C#]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. TElCAdESSignatureProcessor processor = <span class="keyword">new</span> TElCAdESSignatureProcessor();
  3. <span class="keyword">try</span>
  4. {
  5. <span class="comment">// Creating an instance of the signed message class.</span>
  6. TElSignedCMSMessage cms = <span class="keyword">new</span> TElSignedCMSMessage();
  7. <span class="keyword">try</span>
  8. {
  9. <span class="comment">// Creating NEW signed message.</span>
  10. cms.CreateNew(sourceStream, <span class="number">0</span>, sourceStream.Length);
  11. &nbsp;
  12. <span class="comment">// Adding a signature.</span>
  13. TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());
  14. &nbsp;
  15. <span class="comment">// Binding the signature to the CAdES processor.</span>
  16. processor.Signature = sig;
  17. &nbsp;
  18. <span class="comment">// Creating timestamping components.</span>
  19. httpClient = <span class="keyword">new</span> TElHTTPSClient();
  20. <span class="keyword">try</span>
  21. {
  22. <span class="comment">// (!) Remember to handle the httpClient’s OnCertificateValidate</span>
  23. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  24. &nbsp;
  25. tspClient = <span class="keyword">new</span> TElHTTPTSPClient();
  26. <span class="keyword">try</span>
  27. {
  28. tspClient.HTTPClient = httpClient;
  29. tspClient.URL = “http:<span class="comment">//tsa.myserver.com”;</span>
  30. httpClient.SocketTimeout = <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  31. &nbsp;
  32. <span class="comment">// Creating the signature.</span>
  33. processor.CreateT(cert, tspClient);
  34. <span class="comment">// Saving the CMS.</span>
  35. FileStream cmsStream = <span class="keyword">new</span> FileStream(“signature-T.bin”, FileMode.Create);
  36. <span class="keyword">try</span>
  37. {
  38. cms.Save(cmsStream);
  39. }
  40. <span class="keyword">finally</span>
  41. {
  42. cmsStream.Close();
  43. }
  44. }
  45. <span class="keyword">finally</span>
  46. {
  47. tspClient.Dispose();
  48. }
  49. }
  50. <span class="keyword">finally</span>
  51. {
  52. httpClient.Dispose();
  53. }
  54. }
  55. <span class="keyword">finally</span>
  56. {
  57. cms.Dispose();
  58. }
  59. }
  60. <span class="keyword">finally</span>
  61. {
  62. processor.Dispose();
  63. }

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 CAdES-T type with complete certificate and revocation element references to allow the verifier to reconstruct the PKI environment in revision it used to be in at the moment of signing. Only inclusion of 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]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. CAdESProcessor := TElCAdESSignatureProcessor.Create();
  3. <span class="keyword">try</span>
  4. <span class="comment">// Creating an instance of the signed message class.</span>
  5. CMS := TElSignedCMSMessage.Create(<span class="keyword">nil</span>);
  6. <span class="keyword">try</span>
  7. <span class="comment">// Creating NEW signed message.</span>
  8. CMS.CreateNew(SourceStream, <span class="number">0</span>, SourceStream.Size);
  9. &nbsp;
  10. <span class="comment">// Adding a signature.</span>
  11. Sig := CMS.Signatures[CMS.AddSignature()];
  12. &nbsp;
  13. <span class="comment">// Binding the signature to the CAdES processor.</span>
  14. CAdESProcessor.Signature := Sig;
  15. &nbsp;
  16. <span class="comment">// Creating timestamping components.</span>
  17. HttpClient := TElHTTPSClient.Create(<span class="keyword">nil</span>);
  18. <span class="keyword">try</span>
  19. <span class="comment">// (!) Remember to handle the HttpClient’s OnCertificateValidate</span>
  20. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  21. &nbsp;
  22. TspClient := TElHTTPTSPClient.Create(<span class="keyword">nil</span>);
  23. <span class="keyword">try</span>
  24. TspClient.HTTPClient := HttpClient;
  25. TspClient.URL := “http:<span class="comment">//tsa.myserver.com”;</span>
  26. HttpClient.SocketTimeout := <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  27. &nbsp;
  28. <span class="comment">// Creating the signature.</span>
  29. CAdESProcessor.CreateC(Cert, TspClient);
  30. <span class="comment">// Saving the CMS.</span>
  31. CMSStream := TFileStream.Create(‘signature-C.bin’, fmCreate);
  32. <span class="keyword">try</span>
  33. CMS.Save(CMSStream);
  34. <span class="keyword">finally</span>
  35. FreeAndNil(CMSStream);
  36. <span class="keyword">end</span>;
  37. <span class="keyword">finally</span>
  38. FreeAndNil(TspClient);
  39. <span class="keyword">end</span>;
  40. <span class="keyword">finally</span>
  41. FreeAndNil(HttpClient);
  42. <span class="keyword">end</span>;
  43. <span class="keyword">finally</span>
  44. FreeAndNil(CMS);
  45. <span class="keyword">end</span>;
  46. <span class="keyword">finally</span>
  47. FreeAndNil(CAdESProcessor);
  48. <span class="keyword">end</span>;

[C#]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. TElCAdESSignatureProcessor processor = <span class="keyword">new</span> TElCAdESSignatureProcessor();
  3. <span class="keyword">try</span>
  4. {
  5. <span class="comment">// Creating an instance of the signed message class.</span>
  6. TElSignedCMSMessage cms = <span class="keyword">new</span> TElSignedCMSMessage();
  7. <span class="keyword">try</span>
  8. {
  9. <span class="comment">// Creating NEW signed message.</span>
  10. cms.CreateNew(sourceStream, <span class="number">0</span>, sourceStream.Length);
  11. &nbsp;
  12. <span class="comment">// Adding a signature.</span>
  13. TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());
  14. &nbsp;
  15. <span class="comment">// Binding the signature to the CAdES processor.</span>
  16. processor.Signature = sig;
  17. &nbsp;
  18. <span class="comment">// Creating timestamping components.</span>
  19. httpClient = <span class="keyword">new</span> TElHTTPSClient();
  20. <span class="keyword">try</span>
  21. {
  22. <span class="comment">// (!) Remember to handle the httpClient’s OnCertificateValidate</span>
  23. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  24. &nbsp;
  25. tspClient = <span class="keyword">new</span> TElHTTPTSPClient();
  26. <span class="keyword">try</span>
  27. {
  28. tspClient.HTTPClient = httpClient;
  29. tspClient.URL = “http:<span class="comment">//tsa.myserver.com”;</span>
  30. httpClient.SocketTimeout = <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  31. &nbsp;
  32. <span class="comment">// Creating the signature.</span>
  33. processor.CreateC(cert, tspClient);
  34. <span class="comment">// Saving the CMS.</span>
  35. FileStream cmsStream = <span class="keyword">new</span> FileStream(“signature-C.bin”, FileMode.Create);
  36. <span class="keyword">try</span>
  37. {
  38. cms.Save(cmsStream);
  39. }
  40. <span class="keyword">finally</span>
  41. {
  42. cmsStream.Close();
  43. }
  44. }
  45. <span class="keyword">finally</span>
  46. {
  47. tspClient.Dispose();
  48. }
  49. }
  50. <span class="keyword">finally</span>
  51. {
  52. httpClient.Dispose();
  53. }
  54. }
  55. <span class="keyword">finally</span>
  56. {
  57. cms.Dispose();
  58. }
  59. }
  60. <span class="keyword">finally</span>
  61. {
  62. processor.Dispose();
  63. }

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 construction of 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]) signature extends a CAdES-C signature with a validation timestamp over the entire CAdES-C structure (type 1) or 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 that elements at the moment of signing.

[Delphi]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. CAdESProcessor := TElCAdESSignatureProcessor.Create();
  3. <span class="keyword">try</span>
  4. <span class="comment">// Creating an instance of the signed message class.</span>
  5. CMS := TElSignedCMSMessage.Create(<span class="keyword">nil</span>);
  6. <span class="keyword">try</span>
  7. <span class="comment">// Creating NEW signed message.</span>
  8. CMS.CreateNew(SourceStream, <span class="number">0</span>, SourceStream.Size);
  9. &nbsp;
  10. <span class="comment">// Adding a signature.</span>
  11. Sig := CMS.Signatures[CMS.AddSignature()];
  12. &nbsp;
  13. <span class="comment">// Binding the signature to the CAdES processor.</span>
  14. CAdESProcessor.Signature := Sig;
  15. &nbsp;
  16. <span class="comment">// Creating timestamping components.</span>
  17. HttpClient := TElHTTPSClient.Create(<span class="keyword">nil</span>);
  18. <span class="keyword">try</span>
  19. <span class="comment">// (!) Remember to handle the HttpClient’s OnCertificateValidate</span>
  20. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  21. &nbsp;
  22. TspClient := TElHTTPTSPClient.Create(<span class="keyword">nil</span>);
  23. <span class="keyword">try</span>
  24. TspClient.HTTPClient := HttpClient;
  25. TspClient.URL := “http:<span class="comment">//tsa.myserver.com”;</span>
  26. HttpClient.SocketTimeout := <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  27. &nbsp;
  28. <span class="comment">// Creating the signature. </span>
  29. CAdESProcessor.CreateX1(Cert, TspClient, TspClient);
  30. <span class="comment">// Saving the CMS.</span>
  31. CMSStream := TFileStream.Create(‘signature-X1.bin’, fmCreate);
  32. <span class="keyword">try</span>
  33. CMS.Save(CMSStream);
  34. <span class="keyword">finally</span>
  35. FreeAndNil(CMSStream);
  36. <span class="keyword">end</span>;
  37. <span class="keyword">finally</span>
  38. FreeAndNil(TspClient);
  39. <span class="keyword">end</span>;
  40. <span class="keyword">finally</span>
  41. FreeAndNil(HttpClient);
  42. <span class="keyword">end</span>;
  43. <span class="keyword">finally</span>
  44. FreeAndNil(CMS);
  45. <span class="keyword">end</span>;
  46. <span class="keyword">finally</span>
  47. FreeAndNil(CAdESProcessor);
  48. <span class="keyword">end</span>;

[C#]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. TElCAdESSignatureProcessor processor = <span class="keyword">new</span> TElCAdESSignatureProcessor();
  3. <span class="keyword">try</span>
  4. {
  5. <span class="comment">// Creating an instance of the signed message class.</span>
  6. TElSignedCMSMessage cms = <span class="keyword">new</span> TElSignedCMSMessage();
  7. <span class="keyword">try</span>
  8. {
  9. <span class="comment">// Creating NEW signed message.</span>
  10. cms.CreateNew(sourceStream, <span class="number">0</span>, sourceStream.Length);
  11. &nbsp;
  12. <span class="comment">// Adding a signature.</span>
  13. TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());
  14. &nbsp;
  15. <span class="comment">// Binding the signature to the CAdES processor.</span>
  16. processor.Signature = sig;
  17. &nbsp;
  18. <span class="comment">// Creating timestamping components.</span>
  19. httpClient = <span class="keyword">new</span> TElHTTPSClient();
  20. <span class="keyword">try</span>
  21. {
  22. <span class="comment">// (!) Remember to handle the httpClient’s OnCertificateValidate</span>
  23. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  24. &nbsp;
  25. tspClient = <span class="keyword">new</span> TElHTTPTSPClient();
  26. <span class="keyword">try</span>
  27. {
  28. tspClient.HTTPClient = httpClient;
  29. tspClient.URL = “http:<span class="comment">//tsa.myserver.com”;</span>
  30. httpClient.SocketTimeout = <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  31. &nbsp;
  32. <span class="comment">// Creating the signature.</span>
  33. processor.CreateX1(cert, tspClient, tspClient);
  34. <span class="comment">// Saving the CMS.</span>
  35. FileStream cmsStream = <span class="keyword">new</span> FileStream(“signature-X1.bin”, FileMode.Create);
  36. <span class="keyword">try</span>
  37. {
  38. cms.Save(cmsStream);
  39. }
  40. <span class="keyword">finally</span>
  41. {
  42. cmsStream.Close();
  43. }
  44. }
  45. <span class="keyword">finally</span>
  46. {
  47. tspClient.Dispose();
  48. }
  49. }
  50. <span class="keyword">finally</span>
  51. {
  52. httpClient.Dispose();
  53. }
  54. }
  55. <span class="keyword">finally</span>
  56. {
  57. cms.Dispose();
  58. }
  59. }
  60. <span class="keyword">finally</span>
  61. {
  62. processor.Dispose();
  63. }

Note that 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, 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 values of the referenced validation elements (certificates, CRLs and OCSP responses) to the signature blob. 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]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. CAdESProcessor := TElCAdESSignatureProcessor.Create();
  3. <span class="keyword">try</span>
  4. <span class="comment">// Creating an instance of the signed message class.</span>
  5. CMS := TElSignedCMSMessage.Create(<span class="keyword">nil</span>);
  6. <span class="keyword">try</span>
  7. <span class="comment">// Creating NEW signed message.</span>
  8. CMS.CreateNew(SourceStream, <span class="number">0</span>, SourceStream.Size);
  9. &nbsp;
  10. <span class="comment">// Adding a signature.</span>
  11. Sig := CMS.Signatures[CMS.AddSignature()];
  12. &nbsp;
  13. <span class="comment">// Binding the signature to the CAdES processor.</span>
  14. CAdESProcessor.Signature := Sig;
  15. &nbsp;
  16. <span class="comment">// Creating timestamping components.</span>
  17. HttpClient := TElHTTPSClient.Create(<span class="keyword">nil</span>);
  18. <span class="keyword">try</span>
  19. <span class="comment">// (!) Remember to handle the HttpClient’s OnCertificateValidate</span>
  20. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  21. &nbsp;
  22. TspClient := TElHTTPTSPClient.Create(<span class="keyword">nil</span>);
  23. <span class="keyword">try</span>
  24. TspClient.HTTPClient := HttpClient;
  25. TspClient.URL := “http:<span class="comment">//tsa.myserver.com”;</span>
  26. HttpClient.SocketTimeout := <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  27. &nbsp;
  28. <span class="comment">// Creating the signature. </span>
  29. CAdESProcessor.CreateXL1(Cert, TspClient, TspClient);
  30. <span class="comment">// Saving the CMS.</span>
  31. CMSStream := TFileStream.Create(‘signature-XL1.bin’, fmCreate);
  32. <span class="keyword">try</span>
  33. CMS.Save(CMSStream);
  34. <span class="keyword">finally</span>
  35. FreeAndNil(CMSStream);
  36. <span class="keyword">end</span>;
  37. <span class="keyword">finally</span>
  38. FreeAndNil(TspClient);
  39. <span class="keyword">end</span>;
  40. <span class="keyword">finally</span>
  41. FreeAndNil(HttpClient);
  42. <span class="keyword">end</span>;
  43. <span class="keyword">finally</span>
  44. FreeAndNil(CMS);
  45. <span class="keyword">end</span>;
  46. <span class="keyword">finally</span>
  47. FreeAndNil(CAdESProcessor);
  48. <span class="keyword">end</span>;

[C#]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. TElCAdESSignatureProcessor processor = <span class="keyword">new</span> TElCAdESSignatureProcessor();
  3. <span class="keyword">try</span>
  4. {
  5. <span class="comment">// Creating an instance of the signed message class.</span>
  6. TElSignedCMSMessage cms = <span class="keyword">new</span> TElSignedCMSMessage();
  7. <span class="keyword">try</span>
  8. {
  9. <span class="comment">// Creating NEW signed message.</span>
  10. cms.CreateNew(sourceStream, <span class="number">0</span>, sourceStream.Length);
  11. &nbsp;
  12. <span class="comment">// Adding a signature.</span>
  13. TElCMSSignature sig = cms.get_Signatures(cms.AddSignature());
  14. &nbsp;
  15. <span class="comment">// Binding the signature to the CAdES processor.</span>
  16. processor.Signature = sig;
  17. &nbsp;
  18. <span class="comment">// Creating timestamping components.</span>
  19. httpClient = <span class="keyword">new</span> TElHTTPSClient();
  20. <span class="keyword">try</span>
  21. {
  22. <span class="comment">// (!) Remember to handle the httpClient’s OnCertificateValidate</span>
  23. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  24. &nbsp;
  25. tspClient = <span class="keyword">new</span> TElHTTPTSPClient();
  26. <span class="keyword">try</span>
  27. {
  28. tspClient.HTTPClient = httpClient;
  29. tspClient.URL = “http:<span class="comment">//tsa.myserver.com”;</span>
  30. httpClient.SocketTimeout = <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  31. &nbsp;
  32. <span class="comment">// Creating the signature.</span>
  33. processor.CreateXL1(cert, tspClient, tspClient);
  34. <span class="comment">// Saving the CMS.</span>
  35. FileStream cmsStream = <span class="keyword">new</span> FileStream(“signature-XL1.bin”, FileMode.Create);
  36. <span class="keyword">try</span>
  37. {
  38. cms.Save(cmsStream);
  39. }
  40. <span class="keyword">finally</span>
  41. {
  42. cmsStream.Close();
  43. }
  44. }
  45. <span class="keyword">finally</span>
  46. {
  47. tspClient.Dispose();
  48. }
  49. }
  50. <span class="keyword">finally</span>
  51. {
  52. httpClient.Dispose();
  53. }
  54. }
  55. <span class="keyword">finally</span>
  56. {
  57. cms.Dispose();
  58. }
  59. }
  60. <span class="keyword">finally</span>
  61. {
  62. processor.Dispose();
  63. }

Note that 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, creation of CAdES-X signatures involves deep certificate validation.


Creating a CAdES-A (archival) signature

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 expiration/termination of the PKI services used at the time when the signature and/or previous archival timestamps were created.

[Delphi]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. CAdESProcessor := TElCAdESSignatureProcessor.Create();
  3. <span class="keyword">try</span>
  4. <span class="comment">// Creating an instance of the signed message class.</span>
  5. CMS := TElSignedCMSMessage.Create(<span class="keyword">nil</span>);
  6. <span class="keyword">try</span>
  7. <span class="comment">// Opening existing signed message. </span>
  8. CMS.Open(SigStream, <span class="keyword">nil</span>);
  9. &nbsp;
  10. <span class="comment">// Obtaining the signature object.</span>
  11. Sig := CMS.Signatures[<span class="number">0</span>];
  12. &nbsp;
  13. <span class="comment">// Binding the signature to the CAdES processor.</span>
  14. CAdESProcessor.Signature := Sig;
  15. &nbsp;
  16. <span class="comment">// Creating timestamping components.</span>
  17. HttpClient := TElHTTPSClient.Create(<span class="keyword">nil</span>);
  18. <span class="keyword">try</span>
  19. <span class="comment">// (!) Remember to handle the HttpClient’s OnCertificateValidate</span>
  20. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  21. &nbsp;
  22. TspClient := TElHTTPTSPClient.Create(<span class="keyword">nil</span>);
  23. <span class="keyword">try</span>
  24. TspClient.HTTPClient := HttpClient;
  25. TspClient.URL := “http:<span class="comment">//tsa.myserver.com”;</span>
  26. HttpClient.SocketTimeout := <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  27. &nbsp;
  28. <span class="comment">// Creating the signature. </span>
  29. <span class="keyword">if</span> FCAdESProcessor.IsT() <span class="keyword">then</span>
  30. <span class="comment">// A signature timestamp is already included.</span>
  31. CAdESProcessor.UpgradeToA(TspClient)
  32. <span class="keyword">else</span>
  33. <span class="comment">// No signature timestamp yet, passing two TSP client objects.</span>
  34. CAdESProcessor.UpgradeToA(TspClient, TspClient);
  35. &nbsp;
  36. <span class="comment">// Saving the CMS.</span>
  37. CMSStream := TFileStream.Create(‘signature-A.bin’, fmCreate);
  38. <span class="keyword">try</span>
  39. CMS.Save(CMSStream);
  40. <span class="keyword">finally</span>
  41. FreeAndNil(CMSStream);
  42. <span class="keyword">end</span>;
  43. <span class="keyword">finally</span>
  44. FreeAndNil(TspClient);
  45. <span class="keyword">end</span>;
  46. <span class="keyword">finally</span>
  47. FreeAndNil(HttpClient);
  48. <span class="keyword">end</span>;
  49. <span class="keyword">finally</span>
  50. FreeAndNil(CMS);
  51. <span class="keyword">end</span>;
  52. <span class="keyword">finally</span>
  53. FreeAndNil(CAdESProcessor);
  54. <span class="keyword">end</span>;

[C#]

  1. <span class="comment">// Creating an instance of signature processor.</span>
  2. TElCAdESSignatureProcessor processor = <span class="keyword">new</span> TElCAdESSignatureProcessor();
  3. <span class="keyword">try</span>
  4. {
  5. <span class="comment">// Creating an instance of the signed message class.</span>
  6. TElSignedCMSMessage cms = <span class="keyword">new</span> TElSignedCMSMessage();
  7. <span class="keyword">try</span>
  8. {
  9. <span class="comment">// Creating NEW signed message.</span>
  10. cms.Open(sigStream, <span class="keyword">null</span>, <span class="number">0</span>, <span class="number">0</span>);
  11. &nbsp;
  12. <span class="comment">// Adding a signature.</span>
  13. TElCMSSignature sig = cms.get_Signatures(<span class="number">0</span>);
  14. &nbsp;
  15. <span class="comment">// Binding the signature to the CAdES processor.</span>
  16. processor.Signature = sig;
  17. &nbsp;
  18. <span class="comment">// Creating timestamping components.</span>
  19. httpClient = <span class="keyword">new</span> TElHTTPSClient();
  20. <span class="keyword">try</span>
  21. {
  22. <span class="comment">// (!) Remember to handle the httpClient’s OnCertificateValidate</span>
  23. <span class="comment">// event if the TSA server is accessible via HTTPS protocol.</span>
  24. &nbsp;
  25. tspClient = <span class="keyword">new</span> TElHTTPTSPClient();
  26. <span class="keyword">try</span>
  27. {
  28. tspClient.HTTPClient = httpClient;
  29. tspClient.URL = “http:<span class="comment">//tsa.myserver.com”;</span>
  30. httpClient.SocketTimeout = <span class="number">20000</span>; <span class="comment">// 20 seconds</span>
  31. &nbsp;
  32. <span class="comment">// Creating the signature. </span>
  33. <span class="keyword">if</span> (processor.IsT())
  34. {
  35. <span class="comment">// A signature timestamp is already included.</span>
  36. processor.UpgradeToA(tspClient)
  37. }
  38. <span class="keyword">else</span>
  39. {
  40. <span class="comment">// No signature timestamp yet, passing two TSP client objects.</span>
  41. processor.UpgradeToA(tspClient, tspClient);
  42. }
  43. <span class="comment">// Saving the CMS.</span>
  44. FileStream cmsStream = <span class="keyword">new</span> FileStream(“signature-A.bin”, FileMode.Create);
  45. <span class="keyword">try</span>
  46. {
  47. cms.Save(cmsStream);
  48. }
  49. <span class="keyword">finally</span>
  50. {
  51. cmsStream.Close();
  52. }
  53. }
  54. <span class="keyword">finally</span>
  55. {
  56. tspClient.Dispose();
  57. }
  58. }
  59. <span class="keyword">finally</span>
  60. {
  61. httpClient.Dispose();
  62. }
  63. }
  64. <span class="keyword">finally</span>
  65. {
  66. cms.Dispose();
  67. }
  68. }
  69. <span class="keyword">finally</span>
  70. {
  71. processor.Dispose();
  72. }

Note that unlike previous subtypes, you can’t create a CAdES-A signature from scratch. Instead, you should create a signature of 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 there are plenty of configuration aspects that might affect deep validation process (such as locations of revocation status provisioning sources, connectivity options), but 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 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 current time from local computer.
ForceCompleteChainValidation Controls whether the component should validate the whole certificate chain up to the trusted certificate. Can be switched off for debugging or testing purposes to suppress validation exceptions.
IgnoreChainValidationErrors Set this property to true to suppress validation exceptions from throwing if the component fails to validate the chain for some reason (e.g. missing CRL or CA certificate). This option may be useful when creating signatures using non-validatable 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 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 to provide a separate list of trusted certificates for using 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 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 propagation of possible revocation status update through the PKI environment up to 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 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 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 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 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

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 .NET, Java and C++ product editions the factories should be populated manually with the following code:


  1. <span class="comment">// Registering HTTP OCSP client </span>
  2. SBHTTPOCSPClient.<span class="keyword">Unit</span>.RegisterHTTPOCSPClientFactory();
  3. &nbsp;
  4. <span class="comment">// Registering HTTP CRL retriever</span>
  5. SBHTTPCRL.<span class="keyword">Unit</span>.RegisterHTTPCRLRetrieverFactory();
  6. &nbsp;
  7. <span class="comment">// Registering LDAP CRL retriever</span>
  8. SBLDAPCRL.<span class="keyword">Unit</span>.RegisterLDAPCRLRetrieverFactory();
  9. &nbsp;
  10. <span class="comment">// Registering LDAP certificate retriever</span>
  11. SBLDAPCertRetriever.<span class="keyword">Unit</span>.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:

  1. <span class="keyword">uses</span>
  2. SBHTTPOCSPClient, SBHTTPCRL, SBLDAPCRL, SBLDAPCertRetriever;

References

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

Ready to get started?

Learn more about SecureBlackbox or download a free trial.

Download Now