Implementing PAdES signing of PDF documents using SecureBlackbox

PAdES (PDF Advanced Electronic Signatures) standard extends the generic PDF signatures mechanism to address increasing demand for native long-term digital signature capabilities. The standard in particular introduces provisions for signature archival and update operations.

Generally speaking, PAdES signatures are not compatible with standard PDF signatures and in SecureBlackbox are handled by a separate TElPDFAdvancedPublicKeySecurityHandler component. The component is available for users holding both PDFBlackbox and PKIBlackbox licenses.


Creating basic (PAdES-Basic) signatures

A PAdES-Basic signature (ETSI TS 102-778-2) is de facto a ‘classic’ generic PDF signature. It was included to the PAdES standard for backward compatibility purposes. This type of signature does not provide long term validity capabilities. To create a basic signature, set the PAdESSignatureType property of the PAdES handler to pastBasic.

[Delphi]

  1. Doc := TElPDFDocument.Create(<span class="keyword">nil</span>);
  2. <span class="keyword">try</span>
  3. <span class="comment">// Opening the document.</span>
  4. Doc.Open(docStream);
  5. &nbsp;
  6. <span class="comment">// Adding new signature.</span>
  7. <span class="keyword">Index</span> := Doc.AddSignature();
  8. Sig := Doc.Signatures[<span class="keyword">Index</span>];
  9. Sig.SigningTime := UTCNow;
  10. &nbsp;
  11. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  12. Handler := TElPDFAdvancedPublicKeySecurityHandler.Create(<span class="keyword">nil</span>);
  13. <span class="keyword">Try</span>
  14. Sig.Handler := Handler;
  15. &nbsp;
  16. <span class="comment">// CertStorage should contain at least one certificate</span>
  17. <span class="comment">// with an associated private key.</span>
  18. Handler.CertStorage := CertStorage;
  19. &nbsp;
  20. <span class="comment">// Basic signature type.</span>
  21. Handler.PAdESSignatureType := pastBasic;
  22. &nbsp;
  23. <span class="comment">// Adobe PDF security filter name.</span>
  24. Handler.CustomName := ‘Adobe.PPKLite’;
  25. &nbsp;
  26. <span class="comment">// Saving and closing the document.</span>
  27. Doc.Close(true);
  28. <span class="keyword">finally</span>
  29. FreeAndNil(Handler);
  30. <span class="keyword">end</span>;
  31. <span class="keyword">finally</span>
  32. FreeAndNil(Doc);
  33. <span class="keyword">end</span>;

[C#]

  1. TElPDFDocument doc = <span class="keyword">new</span> TElPDFDocument();
  2. <span class="keyword">try</span>
  3. {
  4. <span class="comment">// Opening the document.</span>
  5. doc.Open(docStream);
  6. &nbsp;
  7. <span class="comment">// Adding new signature.</span>
  8. <span class="keyword">int</span> index = doc.AddSignature();
  9. TElPDFSignature sig = doc.get_Signatures(index);
  10. sig.SigningTime = DateTime.UtcNow;
  11. &nbsp;
  12. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  13. TElPDFAdvancedPublicKeySecurityHandler handler = <span class="keyword">new</span> TElPDFAdvancedPublicKeySecurityHandler();
  14. <span class="keyword">try</span>
  15. {
  16. sig.Handler = handler;
  17. &nbsp;
  18. <span class="comment">// certStorage should contain at least one certificate</span>
  19. <span class="comment">// with an associated private key.</span>
  20. handler.CertStorage = certStorage;
  21. &nbsp;
  22. <span class="comment">// Basic signature type.</span>
  23. handler.PAdESSignatureType = TSBPAdESSignatureType.pastBasic;
  24. &nbsp;
  25. <span class="comment">// Adobe PDF security filter name.</span>
  26. handler.CustomName = “Adobe.PPKLite”;
  27. &nbsp;
  28. <span class="comment">// Saving and closing the document.</span>
  29. doc.Close(<span class="keyword">true</span>);
  30. }
  31. <span class="keyword">finally</span>
  32. {
  33. handler.Dispose();
  34. }
  35. }
  36. <span class="keyword">finally</span>
  37. {
  38. doc.Dispose();
  39. }

Creating enhanced (PAdES-BES and PAdES-EPES) signatures

PAdES-BES and PAdES-EPES signature types (ETSI TS 102-778-3), besides confirming the signer’s identity, provide additional cover for non-repudiation and guaranteed signing time. EPES subtype also allows to reference a signature policy in accordance with which the signature should be validated. To create a BES or EPES signature, set the PAdESSignatureType property of the handler to pastEnhanced.

[Delphi]

  1. Doc := TElPDFDocument.Create(<span class="keyword">nil</span>);
  2. <span class="keyword">try</span>
  3. <span class="comment">// Opening the document.</span>
  4. Doc.Open(docStream);
  5. &nbsp;
  6. <span class="comment">// Adding new signature.</span>
  7. <span class="keyword">Index</span> := Doc.AddSignature();
  8. Sig := Doc.Signatures[<span class="keyword">Index</span>];
  9. Sig.SigningTime := UTCNow;
  10. &nbsp;
  11. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  12. Handler := TElPDFAdvancedPublicKeySecurityHandler.Create(<span class="keyword">nil</span>);
  13. <span class="keyword">Try</span>
  14. Sig.Handler := Handler;
  15. &nbsp;
  16. <span class="comment">// CertStorage should contain at least one certificate</span>
  17. <span class="comment">// with an associated private key.</span>
  18. Handler.CertStorage := CertStorage;
  19. &nbsp;
  20. <span class="comment">// Enhanced signature type.</span>
  21. Handler.PAdESSignatureType := pastEnhanced;
  22. &nbsp;
  23. <span class="comment">// Adobe PDF security filter name.</span>
  24. Handler.CustomName := ‘Adobe.PPKLite’;
  25. &nbsp;
  26. <span class="comment">// Saving and closing the document.</span>
  27. Doc.Close(true);
  28. <span class="keyword">finally</span>
  29. FreeAndNil(Handler);
  30. <span class="keyword">end</span>;
  31. <span class="keyword">finally</span>
  32. FreeAndNil(Doc);
  33. <span class="keyword">end</span>;

[C#]

  1. TElPDFDocument doc = <span class="keyword">new</span> TElPDFDocument();
  2. <span class="keyword">try</span>
  3. {
  4. <span class="comment">// Opening the document.</span>
  5. doc.Open(docStream);
  6. &nbsp;
  7. <span class="comment">// Adding new signature.</span>
  8. <span class="keyword">int</span> index = doc.AddSignature();
  9. TElPDFSignature sig = doc.get_Signatures(index);
  10. sig.SigningTime = DateTime.UtcNow;
  11. &nbsp;
  12. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  13. TElPDFAdvancedPublicKeySecurityHandler handler = <span class="keyword">new</span> TElPDFAdvancedPublicKeySecurityHandler();
  14. <span class="keyword">try</span>
  15. {
  16. sig.Handler = handler;
  17. &nbsp;
  18. <span class="comment">// certStorage should contain at least one certificate</span>
  19. <span class="comment">// with an associated private key.</span>
  20. handler.CertStorage = certStorage;
  21. &nbsp;
  22. <span class="comment">// Basic signature type.</span>
  23. handler.PAdESSignatureType = TSBPAdESSignatureType.pastEnhanced;
  24. &nbsp;
  25. <span class="comment">// Adobe PDF security filter name.</span>
  26. handler.CustomName = “Adobe.PPKLite”;
  27. &nbsp;
  28. <span class="comment">// Saving and closing the document.</span>
  29. doc.Close(<span class="keyword">true</span>);
  30. }
  31. <span class="keyword">finally</span>
  32. {
  33. handler.Dispose();
  34. }
  35. }
  36. <span class="keyword">finally</span>
  37. {
  38. doc.Dispose();
  39. }

Long-term PDF signatures

PKI environment changes. Validation elements, such as certificates, CRLs and OCSP responses, expire with time. Online validation services that existed at the moment of signing might eventually be ceased. CAs might close or restructure due to market disturbances. Moreover, cryptographic algorithms expire as well, becoming weaker and less resistant to attacks.

Signatures that are supposed to remain valid and validatable for extremely long periods of time have to minimize their dependency on the state of the PKI environment at the moment of signing. This is generally achieved by the two methods that follow:

  1. when producing a signature, the signer embeds to it all the validation elements that might help the verifier to establish the validity of the signature without contacting online validation sources. Those elements include the entire certificate chain (up to the root certificate), and all the CRLs and OCSP responses that confirm the validity of all the certificates forming the chain at the moment of signing.
  2. the document is updated regularly to respond to changes in cryptographic environment. During such updates an external timestamping service is used for certifying the contents of the document and the time of update with an effective certificate and robust (at that moment of time) cryptographic algorithm. The certification is made by appending an additional signature, called a document timestamp (ETSI TS 102-778-4), to the end of the archived document. An archived document thus may contain a collection of document timestamp signatures, each of which certifies the document and all the preceding signatures with more robust algorithm and key.

Creating a long-term signature

As one can conclude from the above, creation of a long-term signature starts with creation of a basic or BES/EPES signature that has all the validation information included. The signature must contain a timestamp from a trusted TSA that confirms the time of signing:

[Delphi]

  1. Doc := TElPDFDocument.Create(<span class="keyword">nil</span>);
  2. <span class="keyword">try</span>
  3. <span class="comment">// Opening the document.</span>
  4. Doc.Open(docStream);
  5. &nbsp;
  6. <span class="comment">// Adding new signature.</span>
  7. Index := Doc.AddSignature();
  8. Sig := Doc.Signatures[Index];
  9. Sig.SigningTime := UTCNow;
  10. &nbsp;
  11. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  12. Handler := TElPDFAdvancedPublicKeySecurityHandler.Create(<span class="keyword">nil</span>);
  13. <span class="keyword">try</span>
  14. Sig.Handler := Handler;
  15. &nbsp;
  16. <span class="comment">// CertStorage should contain at least one certificate</span>
  17. <span class="comment">// with an associated private key.</span>
  18. Handler.CertStorage := CertStorage;
  19. &nbsp;
  20. <span class="comment">// Enhanced signature type.</span>
  21. Handler.PAdESSignatureType := pastEnhanced;
  22. &nbsp;
  23. <span class="comment">// Configuring the handler to make it perform deep chain validation </span>
  24. <span class="comment">// and collect all available revocation information from</span>
  25. <span class="comment">// online sources.</span>
  26. Handler.AutoCollectRevocationInfo := <span class="keyword">true</span>;
  27. Handler.ForceCompleteChainValidation := <span class="keyword">true</span>;
  28. Handler.IncludeRevocationInfoToAdbeAttribute := <span class="keyword">true</span>;
  29. <span class="comment">// Use the CustomRevocationInfo property to provide the handler </span>
  30. <span class="comment">// with revocation information not available online:</span>
  31. Handler.CustomRevocationInfo.Certificates.Add(IntmCACert, <span class="keyword">false</span>);
  32. Handler.CustomRevocationInfo.Certificates.Add(RootCACert, <span class="keyword">false</span>);
  33. Idx := Handler.CustomRevocationInfo.AddCRL();
  34. Handler.CustomRevocationInfo.CRLs[Idx].Assign(RootCACrl);
  35. &nbsp;
  36. <span class="comment">// Adobe PDF security filter name.</span>
  37. Handler.CustomName := ‘Adobe.PPKLite’;
  38. &nbsp;
  39. <span class="comment">// Creating and configuring TSP components.</span>
  40. HttpClient := TElHTTPSClient.Create(<span class="keyword">nil</span>);
  41. <span class="keyword">try</span>
  42. TspClient := TElHTTPTSPClient.Create(<span class="keyword">nil</span>);
  43. <span class="keyword">try</span>
  44. &nbsp;
  45. TspClient.HTTPClient := HttpClient;
  46. TspClient.URL := ‘http:<span class="comment">//tsa.myserver.com’;</span>
  47. Handler.TSPClient := TspClient;
  48. &nbsp;
  49. <span class="comment">// Saving and closing the document.</span>
  50. Doc.Close(<span class="keyword">true</span>);
  51. &nbsp;
  52. <span class="keyword">finally</span>
  53. FreeAndNil(TspClient);
  54. <span class="keyword">end</span>;
  55. <span class="keyword">finally</span>
  56. FreeAndNil(HttpClient);
  57. <span class="keyword">end</span>;
  58. <span class="keyword">finally</span>
  59. FreeAndNil(Handler);
  60. <span class="keyword">end</span>;
  61. <span class="keyword">finally</span>
  62. FreeAndNil(Doc);
  63. <span class="keyword">end</span>;

[C#]

  1. TElPDFDocument doc = <span class="keyword">new</span> TElPDFDocument();
  2. <span class="keyword">try</span>
  3. {
  4. <span class="comment">// Opening the document.</span>
  5. doc.Open(docStream);
  6. &nbsp;
  7. <span class="comment">// Adding new signature.</span>
  8. <span class="keyword">int</span> index = doc.AddSignature();
  9. TElPDFSignature sig = doc.get_Signatures(index);
  10. sig.SigningTime = DateTime.UtcNow;
  11. &nbsp;
  12. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  13. TElPDFAdvancedPublicKeySecurityHandler handler = <span class="keyword">new</span> TElPDFAdvancedPublicKeySecurityHandler();
  14. <span class="keyword">try</span>
  15. {
  16. sig.Handler = handler;
  17. &nbsp;
  18. <span class="comment">// certStorage should contain at least one certificate</span>
  19. <span class="comment">// with an associated private key.</span>
  20. handler.CertStorage = certStorage;
  21. &nbsp;
  22. <span class="comment">// Enhanced signature type.</span>
  23. handler.PAdESSignatureType = TSBPAdESSignatureType.pastEnhanced;
  24. &nbsp;
  25. <span class="comment">// Configuring the handler to make it perform deep chain validation </span>
  26. <span class="comment">// and collect all available revocation information from</span>
  27. <span class="comment">// online sources.</span>
  28. handler.AutoCollectRevocationInfo = <span class="keyword">true</span>;
  29. handler.ForceCompleteChainValidation = <span class="keyword">true</span>;
  30. handler.IncludeRevocationInfoToAdbeAttribute = <span class="keyword">true</span>;
  31. <span class="comment">// Use the CustomRevocationInfo property to provide the handler </span>
  32. <span class="comment">// with revocation information not available online:</span>
  33. handler.CustomRevocationInfo.Certificates.Add(intmCACert, <span class="keyword">false</span>);
  34. handler.CustomRevocationInfo.Certificates.Add(rootCACert, <span class="keyword">false</span>);
  35. index = handler.CustomRevocationInfo.AddCRL();
  36. handler.CustomRevocationInfo.get_CRLs(index).Assign(rootCACrl);
  37. &nbsp;
  38. <span class="comment">// Adobe PDF security filter name.</span>
  39. handler.CustomName = “Adobe.PPKLite”;
  40. &nbsp;
  41. <span class="comment">// Creating and configuring TSP components.</span>
  42. TElHTTPSClient httpClient = <span class="keyword">new</span> TElHTTPSClient();
  43. <span class="keyword">try</span>
  44. {
  45. TElHTTPTSPClient tspClient = <span class="keyword">new</span> TElHTTPTSPClient();
  46. <span class="keyword">try</span>
  47. {
  48. tspClient.HTTPClient = httpClient;
  49. tspClient.URL = “http:<span class="comment">//tsa.myserver.com”;</span>
  50. handler.TSPClient = tspClient;
  51. &nbsp;
  52. <span class="comment">// Saving and closing the document.</span>
  53. doc.Close(<span class="keyword">true</span>);
  54. }
  55. <span class="keyword">finally</span>
  56. {
  57. tspClient.Dispose();
  58. }
  59. }
  60. <span class="keyword">finally</span>
  61. {
  62. httpClient.Dispose();
  63. }
  64. }
  65. <span class="keyword">finally</span>
  66. {
  67. handler.Dispose();
  68. }
  69. }
  70. <span class="keyword">finally</span>
  71. {
  72. doc.Dispose();
  73. }

The document signed in the above way can be validated without contacting online validation sources, as the verifier can extract all the needed validation pieces from the signature.


Archiving PDF documents with a document timestamp

To maintain a long-term signed document ‘in good shape’ you will occasionally need to add document timestamps to it to extend the validity period of the signature. Document timestamps are normally added just before the certificate that was used to create the preceding signature expires (including the preceding document timestamp), or just before the cryptographic algorithm used to create the preceding signature is declared deprecated (note that it can be a signature policy that deprecates an algorithm, not only governments or cryptoanalysts). A document timestamp can be added in the following way:

[Delphi]

  1. Doc := TElPDFDocument.Create(<span class="keyword">nil</span>);
  2. <span class="keyword">try</span>
  3. <span class="comment">// Opening the document.</span>
  4. Doc.Open(docStream);
  5. &nbsp;
  6. <span class="comment">// Obtaining the last signature object.</span>
  7. <span class="keyword">Index</span> := Doc.SignatureCount - <span class="number">1</span>;
  8. Sig := Doc.Signatures[<span class="keyword">Index</span>];
  9. &nbsp;
  10. <span class="comment">// Checking if the signature references the correct handler.</span>
  11. <span class="keyword">if</span> <span class="keyword">not</span> (Sig.Handler is TElPDFAdvancedPublicKeySecurityHandler) <span class="keyword">then</span>
  12. <span class="keyword">raise</span> Exception.Create(‘Wrong security handler, PAdES is likely <span class="keyword">not</span> <span class="keyword">to</span> be initialized’);
  13. &nbsp;
  14. <span class="comment">// Ensuring that the existing signature contains the complete set</span>
  15. <span class="comment">// of revocation elements.</span>
  16. Handler := TElPDFAdvancedPublicKeySecurityHandler(Sig.Handler);
  17. &nbsp;
  18. <span class="comment">// Configuring the handler to make it perform deep chain validation </span>
  19. <span class="comment">// and collect all available revocation information from</span>
  20. <span class="comment">// online sources.</span>
  21. Handler.AutoCollectRevocationInfo := true;
  22. Handler.ForceCompleteChainValidation := true;
  23. <span class="comment">// Use the CustomRevocationInfo property to provide the handler </span>
  24. <span class="comment">// with revocation information not available online:</span>
  25. Handler.CustomRevocationInfo.Certificates.Add(IntmCACert, false);
  26. Handler.CustomRevocationInfo.Certificates.Add(RootCACert, false);
  27. <span class="keyword">Index</span> := Handler.CustomRevocationInfo.AddCRL();
  28. Handler.CustomRevocationInfo.CRLs[<span class="keyword">Index</span>].Assign(RootCACrl);
  29. &nbsp;
  30. <span class="comment">// Updating the signature (collecting missing revocation elements</span>
  31. <span class="comment">// and adding them to the document).</span>
  32. Sig.Update();
  33. &nbsp;
  34. <span class="comment">// Adding document timestamp. </span>
  35. <span class="keyword">Index</span> := Doc.AddSignature();
  36. Sig := Doc.Signatures[<span class="keyword">Index</span>];
  37. Sig.SigningTime := UTCNow;
  38. &nbsp;
  39. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  40. Handler := TElPDFAdvancedPublicKeySecurityHandler.Create(<span class="keyword">nil</span>);
  41. <span class="keyword">try</span>
  42. Sig.Handler := Handler;
  43. Handler.PAdESSignatureType := pastDocumentTimestamp;
  44. &nbsp;
  45. <span class="comment">// Creating and configuring TSP components.</span>
  46. HttpClient := TElHTTPSClient.Create(<span class="keyword">nil</span>);
  47. <span class="keyword">try</span>
  48. TspClient := TElHTTPTSPClient.Create(<span class="keyword">nil</span>);
  49. <span class="keyword">try</span>
  50. &nbsp;
  51. TspClient.HTTPClient := HttpClient;
  52. TspClient.URL := ‘http:<span class="comment">//tsa.myserver.com’;</span>
  53. Handler.TSPClient := TspClient;
  54. &nbsp;
  55. <span class="comment">// Saving and closing the document.</span>
  56. Doc.Close(true);
  57. &nbsp;
  58. <span class="keyword">finally</span>
  59. FreeAndNil(TspClient);
  60. <span class="keyword">end</span>;
  61. <span class="keyword">finally</span>
  62. FreeAndNil(HttpClient);
  63. <span class="keyword">end</span>;
  64. <span class="keyword">finally</span>
  65. FreeAndNil(Handler);
  66. <span class="keyword">end</span>;
  67. <span class="keyword">finally</span>
  68. FreeAndNil(Doc);
  69. <span class="keyword">end</span>;

[C#]

  1. TElPDFDocument doc = <span class="keyword">new</span> TElPDFDocument();
  2. <span class="keyword">try</span>
  3. {
  4. <span class="comment">// Opening the document.</span>
  5. doc.Open(docStream);
  6. &nbsp;
  7. <span class="comment">// Obtaining the last signature object.</span>
  8. <span class="keyword">int</span> index = doc.SignatureCount - <span class="number">1</span>;
  9. TElPDFSignature sig = doc.get_Signatures(Idx);
  10. &nbsp;
  11. <span class="comment">// Checking if the signature references the correct handler.</span>
  12. <span class="keyword">if</span> (!(sig.Handler <span class="keyword">is</span> TElPDFAdvancedPublicKeySecurityHandler))
  13. {
  14. <span class="keyword">throw</span> <span class="keyword">new</span> Exception(“Wrong security handler, PAdES <span class="keyword">is</span> likely not to be initialized”);
  15. }
  16. &nbsp;
  17. <span class="comment">// Ensuring that the existing signature contains the complete set</span>
  18. <span class="comment">// of revocation elements.</span>
  19. TElPDFAdvancedPublicKeySecurityHandler handler = (TElPDFAdvancedPublicKeySecurityHandler)(sig.Handler);
  20. &nbsp;
  21. <span class="comment">// Configuring the handler to make it perform deep chain validation </span>
  22. <span class="comment">// and collect all available revocation information from</span>
  23. <span class="comment">// online sources.</span>
  24. handler.AutoCollectRevocationInfo = <span class="keyword">true</span>;
  25. handler.ForceCompleteChainValidation = <span class="keyword">true</span>;
  26. <span class="comment">// Use the CustomRevocationInfo property to provide the handler </span>
  27. <span class="comment">// with revocation information not available online:</span>
  28. handler.CustomRevocationInfo.Certificates.Add(intmCACert, <span class="keyword">false</span>);
  29. handler.CustomRevocationInfo.Certificates.Add(rootCACert, <span class="keyword">false</span>);
  30. index = Handler.CustomRevocationInfo.AddCRL();
  31. handler.CustomRevocationInfo.get_CRLs(index).Assign(rootCACrl);
  32. &nbsp;
  33. <span class="comment">// Updating the signature (collecting missing revocation elements</span>
  34. <span class="comment">// and adding them to the document).</span>
  35. sig.Update();
  36. &nbsp;
  37. <span class="comment">// Adding document timestamp. </span>
  38. index = doc.AddSignature();
  39. sig = doc.get_Signatures(index);
  40. sig.SigningTime = DateTime.UtcNow;
  41. &nbsp;
  42. <span class="comment">// Creating a handler and assigning it to the new signature object.</span>
  43. handler = <span class="keyword">new</span> TElPDFAdvancedPublicKeySecurityHandler();
  44. <span class="keyword">try</span>
  45. {
  46. sig.Handler = handler;
  47. handler.PAdESSignatureType = TSBPAdESSignatureType.pastDocumentTimestamp;
  48. &nbsp;
  49. <span class="comment">// Creating and configuring TSP components.</span>
  50. httpClient = <span class="keyword">new</span> TElHTTPSClient();
  51. <span class="keyword">try</span>
  52. {
  53. tspClient = <span class="keyword">new</span> TElHTTPTSPClient();
  54. <span class="keyword">try</span>
  55. {
  56. tspClient.HTTPClient = httpClient;
  57. tspClient.URL = “http:<span class="comment">//tsa.myserver.com”;</span>
  58. handler.TSPClient = tspClient;
  59. &nbsp;
  60. <span class="comment">// Saving and closing the document.</span>
  61. doc.Close(<span class="keyword">true</span>);
  62. }
  63. <span class="keyword">finally</span>
  64. {
  65. tspClient.Dispose();
  66. }
  67. }
  68. <span class="keyword">finally</span>
  69. {
  70. httpClient.Dispose();
  71. }
  72. }
  73. <span class="keyword">finally</span>
  74. {
  75. handler.Dispose();
  76. }
  77. }
  78. <span class="keyword">finally</span>
  79. {
  80. doc.Dispose();
  81. }

The first part of the above code ensures that all the revocation information is available for the existing signature and collects it if it’s not. This way, it always converts a non-long-term signature to a long-term one before adding a document timestamp to it.


Preparing and Tuning the TElPDFAdvancedPublicKeySecurityHandler object

Each PKI environment is different, so you will probably need to tune up the TElPDFAdvancedPublicKeySecurityHandler object to match your particular one. The table below gives a breakdown of the most important properties of the handler object.

CustomRevocationInfo Use this property to pass your own revocation information (certificates, CRLs and OCSP responses) to the component if it can’t be obtained automatically from online sources.
CMS Provides access to the underlying TElSignedCMSMessage object and can be used to fine-tune inner CMS properties.
PAdESSignatureType Specifies the subtype of PAdES signature to create (PAdES-basic, PAdES-BES/EPES, Document Timestamp).
AutoCollectRevocationInfo Tells the component to attempt to automatically collect revocation information from online sources.
IgnoreChainValidationErrors Prevents the handler from throwing exceptions in case of chain validation errors. Use this property with care in real-world environments, as ignoring certain validation problems may pose a security risk.
ForceCompleteChainValidation Controls whether the component should validate the whole certificate chain up to the trusted certificate. Can be switched off for debug or testing purposes to suppress validation exceptions.
IncludeRevocationInfoToAdbeAttribute Specifies if revocation elements should be included to the document as a legacy adbeRevocationInfoArchival attribute, in addition to the methods offered by PAdES (mainly for compatibility purposes).
PAdESOptions Allows to tune-up various minor aspects of PAdES and inner CMS generation.
SignatureSizeEstimationStrategy Tells the component how exactly the size of signature window should be estimated:
  • psesBasic: very fast and rough estimation based on the component’s knowledge of typical validation element sizes. Suitable for most environments, but may expose problems in environments with extraordinal element sizes (e.g. CRLs of 200KB);
  • psesSmart: a smarter yet slower estimation strategy. Works well with both typical- and peculiar-sized validation elements.
  • psesSmartAndTrialTimestamp: same as psesSmart, but performs a ‘trial’ timestamp request before starting the signing process to find out the exact size of the timestamp. Can be useful if the timestamp server you are using returns very large timestamps.
  • psesPredefinedSize: a window of PredefinedSignatureSize bytes is allocated, no built-in estimation is performed.

Registering PAdES handlers

In default component configuration the priority of PAdES security handlers when processing the documents is lower than that of generic PDF handlers. While not affecting document signing operations, this leads to automatic creation and attachment of generic PDF handlers to basic signature objects when the document is opened (PAdES-BES and document timestamp signatures will be assigned with proper PAdES handlers). As a result, you will be unable to convert basic signatures to long-term ones with the Update() operation or use chain validation capabilities of PAdES handlers to validate basic signatures. To force the components to always create PAdES handlers for all supported types of signatures, including basic ones, PAdES handlers should be moved up in the registered handlers list. This can be done with the following code:

  1. UnregisterSecurityHandler(TElPDFPublicKeySecurityHandler);
  2. UnregisterSecurityHandler(TElPDFAdvancedPublicKeySecurityHandler);
  3. RegisterSecurityHandler(TElPDFAdvancedPublicKeySecurityHandler);
  4. RegisterSecurityHandler(TElPDFPublicKeySecurityHandler);

Registering revocation retriever factories

TElPDFAdvancedPublicKeySecurityHandler 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 build 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

[PADES]: Electronic Signatures and Infrastructures (ESI); PDF Advanced Electronic Signature Profiles; Parts 1-5, ETSI TS 102 778-1, -2, -3, -4, -5.

Ready to get started?

Learn more about SecureBlackbox or download a free trial.

Download Now