PadesLevels.cs
  1. //
  2. // This code is part of Document Solutions for PDF demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using System.Text;
  9. using System.Linq;
  10. using System.Collections.Generic;
  11. using System.Security.Cryptography;
  12. using System.Security.Cryptography.X509Certificates;
  13.  
  14. using GrapeCity.Documents.Pdf;
  15. using GrapeCity.Documents.Pdf.Security;
  16. using GrapeCity.Documents.Pdf.AcroForms;
  17. using GrapeCity.Documents.Text;
  18.  
  19.  
  20. namespace DsPdfWeb.Demos
  21. {
  22. // This sample shows how to sign an existing PDF file containing
  23. // an empty signature field with a signature that complies with
  24. // the various PAdES (PDF Advanced Electronic Signatures) levels.
  25. // Note that when run online, this sample simply returns an unsigned
  26. // PDF with an empty signature field. To actually sign the PDF
  27. // you will need to provide a valid .pfx file (see "JohnDoe.pfx").
  28. // The sample contains 5 methods that can be used to sign a PDF
  29. // with the various PAdES levels, the last 3 methods can be
  30. // used in a chain to incrementally increase the signature strength.
  31. // To check the signature compliance, open the signed PDF in Acrobat
  32. // Reader and inspect the signature properties.
  33. //
  34. // IMPORTANT! The code in this sample WILL NOT work correctly
  35. // unless DsPdf is licensed with a valid license key.
  36. // Email us.sales@mescius.com to obtain a trial key.
  37. public class PadesLevels
  38. {
  39. // Certificate issued by CA Cert Signing Authority, used for verification:
  40. static X509Certificate2 s_caCertRoot = new X509Certificate2(Path.Combine("Resources", "Misc", "CACertRoot.crt"));
  41. // TODO: replace with a real certificate:
  42. static X509Certificate2 s_cert = new X509Certificate2(Path.Combine("Resources", "Misc", "JohnDoe.pfx"), "secret");
  43.  
  44. static PadesLevels()
  45. {
  46. // TODO: GcPdfDocument MUST BE LICENSED for the signatures to remain valid,
  47. // as otherwise the license nag text added when saving the PDF invalidates
  48. // incremental updates. Email us.sales@mescius.com to obtain a trial key.
  49. // GcPdfDocument.SetLicenseKey("my key");
  50. }
  51.  
  52. public void CreatePDF(Stream stream, int paramsIdx = 0)
  53. {
  54. CreatePDF(stream, GetSampleParamsList()[paramsIdx]);
  55. }
  56.  
  57. // While this sample includes code that does the actual signing and time stamping,
  58. // that code is NOT executed by the online demo. So the online sample driver
  59. // simply returns the PDF that includes info about the selected PAdES level,
  60. // and can be signed or time stamped using a valid certificate.
  61. // You can copy the corresponding code and use it in your applications.
  62. public void CreatePDF(Stream stream, string[] sampleParams)
  63. {
  64. // TODO: change to true to actually run the signing/time stamping code:
  65. bool doSigning = false;
  66.  
  67. // The unsigned PDF with a signature field to sign:
  68. var fn = Path.Combine("Resources", "PDFs", sampleParams[3]);
  69.  
  70. if (doSigning)
  71. {
  72. // Running this code will produce 5 PDFs with increasing PAdES levels:
  73.  
  74. // PAdES B-B:
  75. Do_B_B(fn);
  76. // PAdES B-T:
  77. Do_B_T(fn);
  78. // Note that the next 3 steps use PDFs produced by the previous step,
  79. // incrementally adding verification info:
  80. // PAdES B-LT:
  81. Do_B_LT("B-T.pdf");
  82. // PAdES B-LTA:
  83. Do_B_LTA("B-LT.pdf");
  84. // LTV Enabled:
  85. Do_B_LTA_LTV("B-LTA.pdf");
  86. }
  87.  
  88. // Copy the source PDF to output stream
  89. // to provide the demo result:
  90. using var fs = File.OpenRead(fn);
  91. fs.CopyTo(stream);
  92. }
  93.  
  94. // Signs a PDF with a PAdES B-B Level signature:
  95. void Do_B_B(string fn)
  96. {
  97. using FileStream fs = File.OpenRead(fn);
  98. var doc = new GcPdfDocument();
  99. doc.Load(fs);
  100.  
  101. var signField = doc.AcroForm.Fields.FirstOrDefault(f_ => f_ is SignatureField);
  102. if (signField == null)
  103. throw new Exception("Could not find a signature field.");
  104.  
  105. var sp = new SignatureProperties()
  106. {
  107. SignatureField = signField,
  108. SignatureBuilder = new Pkcs7SignatureBuilder(s_cert)
  109. {
  110. Format = Pkcs7SignatureBuilder.SignatureFormat.ETSI_CAdES_detached,
  111. },
  112. };
  113. // Sign and save the PDF to a file:
  114. doc.Sign(sp, "B-B.pdf");
  115. }
  116.  
  117. // Signs a PDF with a PAdES B-T Level signature:
  118. void Do_B_T(string fn)
  119. {
  120. using FileStream fs = File.OpenRead(fn);
  121. var doc = new GcPdfDocument();
  122. doc.Load(fs);
  123.  
  124. var signField = doc.AcroForm.Fields.FirstOrDefault(f_ => f_ is SignatureField);
  125. if (signField == null)
  126. throw new Exception("Could not find a signature field.");
  127.  
  128. var sp = new SignatureProperties()
  129. {
  130. SignatureField = signField,
  131. SignatureBuilder = new Pkcs7SignatureBuilder(s_cert)
  132. {
  133. Format = Pkcs7SignatureBuilder.SignatureFormat.ETSI_CAdES_detached,
  134. },
  135. TimeStamp = new TimeStamp(@"http://ts.ssl.com"),
  136. };
  137. // Sign and save the PDF to a file:
  138. doc.Sign(sp, "B-T.pdf");
  139. }
  140.  
  141. // Adds LTV information to a B-T level signature (e.g. as created by the do_B_T method above),
  142. // which makes the signature compliant with PAdES B-LT:
  143. void Do_B_LT(string fn)
  144. {
  145. using FileStream fs = File.OpenRead(fn);
  146. var doc = new GcPdfDocument();
  147. doc.Load(fs);
  148.  
  149. var signField = doc.AcroForm.Fields.FirstOrDefault(f_ => f_ is SignatureField);
  150. if (signField == null)
  151. throw new Exception("Could not find a signature field.");
  152.  
  153. // Get the signature and add verification information for it:
  154. var sig = (Signature)signField.Value;
  155. var vp = new DocumentSecurityStore.VerificationParams();
  156. vp.Certificates = new X509Certificate2[] { s_caCertRoot };
  157. if (!doc.SecurityStore.AddVerification(sig, vp))
  158. throw new Exception($"Could not add verification for {sig.Name}.");
  159.  
  160. // Save the PDF to a file using incremental update so that the signature remains valid:
  161. doc.Save("B-LT.pdf", SaveMode.IncrementalUpdate);
  162. }
  163.  
  164. // Adds time stamp to a signed PDF (e.g. as created by the do_B_LT method above),
  165. // which makes the document compliant with B-LTA level:
  166. void Do_B_LTA(string fn)
  167. {
  168. using FileStream fs = File.OpenRead(fn);
  169. var doc = new GcPdfDocument();
  170. doc.Load(fs);
  171.  
  172. var ts = new TimeStampProperties()
  173. {
  174. TimeStamp = new TimeStamp(@"http://ts.ssl.com"),
  175. };
  176. // Save the PDF to a file adding a time stamp to it:
  177. doc.TimeStamp(ts, "B-LTA.pdf");
  178. }
  179.  
  180. // Adds verification information for a PDF time-stamp (e.g. as created by the do_B_LTA method above)
  181. // which makes the signature LTV enabled:
  182. void Do_B_LTA_LTV(string fn)
  183. {
  184. using FileStream fs = File.OpenRead(fn);
  185. var doc = new GcPdfDocument();
  186. doc.Load(fs);
  187.  
  188. var signField = doc.AcroForm.Fields.FirstOrDefault(f_ => f_ is SignatureField);
  189. if (signField == null)
  190. throw new Exception("Could not find a signature field.");
  191.  
  192. // Get the signature and add verification information for it:
  193. var sig = (Signature)signField.Value;
  194. if (!doc.SecurityStore.AddVerification(sig))
  195. throw new Exception($"Could not add verification for {sig.Name}.");
  196.  
  197. // Save the PDF to a file using incremental update so that the signature remains valid:
  198. doc.Save("B-LTA_LTV.pdf", SaveMode.IncrementalUpdate);
  199. }
  200.  
  201. public static List<string[]> GetSampleParamsList()
  202. {
  203. // Strings are name, description, info, rest are arbitrary strings:
  204. return new List<string[]>()
  205. {
  206. new string[] { "@b-sign/PAdES B-B Level", "How to sign a PDF complying with PAdES B-B level", "",
  207. "PAdES-B-B.pdf" },
  208. new string[] { "@b-sign/PAdES B-T Level", "How to sign a PDF complying with PAdES B-T level", "",
  209. "PAdES-B-T.pdf" },
  210. new string[] { "@b-sign/PAdES B-LT Level", "How to add LTV information to a signature", "",
  211. "PAdES-B-LT.pdf" },
  212. new string[] { "@b-sign/PAdES B-LTA Level", "How to time stamp a signed PDF", "",
  213. "PAdES-B-LTA.pdf" },
  214. new string[] { "@b-sign/LTV Enabled Signature", "How to make a signature LTV enabled", "",
  215. "PAdES-B-LTA-LTV.pdf" },
  216. };
  217. }
  218. }
  219. }
  220.