Documents for PDF .NET Edition
Features / Digital Signature
In This Topic
    Digital Signature
    In This Topic

    GcPdf enables a user to digitally sign a PDF document to secure the authenticity of the content. The library supports digital signature in the PDF document using the SignatureField class. You can also add digital signatures with timestamps to mark the time and date of the signature in the PDF document. GcPdf supports legal stamps created by trustworthy authority like the Time Stamp Authority (TSA). GcPdf provides Sign method to sign and save a document which by default updates the document incrementally. Alternatively, you can also set the SaveMode enumeration to IncrementalUpdate and pass it as a parameter to Sign method. Both these methods let you sign a document multiple times without invalidating the original signature and without changing its original content. GcPdf allows three levels of subsequent changes on a signed document:

    Note that once a document has been signed, adding a new field invalidates the existing signature. Hence, a document must already have enough signature fields to accommodate all the subsequent signatures. Also, if you run a sample that uses a signed PDF without a valid license key of GcPdf, then the original signature in the generated PDF is invalidated. This happens because a license header is added to the PDF in such cases which changes the original signed document.

    Further, GcPdf allows a user to reuse a signed PDF template by removing the signatures and keeping the Signature Field, or simply removing the Signature Field.

    Add Digital Signature

    To add digital signature in a PDF document:

    1. Use the SignatureProperties class to set up the certificate for digital signature.
    2. Initialize the SignatureField class to hold the signature.
    3. Add the signature field to the PDF document using the Add method.
    4. Connect the signature field to signature properties.
    5. Sign the document using the Sign method of GcPdfDocument class. It also saves the document.
      C#
      Copy Code
      public static void CreatePDF(Stream stream)
      {
          GcPdfDocument doc = new GcPdfDocument();
          Page page = doc.NewPage();
          TextFormat tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 14 };
          page.Graphics.DrawString(
              "Hello, World!\r\nSigned below by GcPdfWeb SignDoc sample." +
              "\r\n(Note that some browser built-in viewers may not show the signature.)",
              tf, new PointF(72, 72));
      
          // Initialize a test certificate:
          var pfxPath = Path.Combine("Resources", "Misc", "GcPdfTest.pfx");
          X509Certificate2 cert = new X509Certificate2(File.ReadAllBytes(pfxPath), "qq",
          X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet
          | X509KeyStorageFlags.Exportable);
          SignatureProperties sp = new SignatureProperties();
          sp.Certificate = cert;
          sp.Location = "GcPdfWeb Sample Browser";
          sp.SignerName = "GcPdfWeb";
          // Add timestamp            
          sp.TimeStamp = new TimeStamp("https://freetsa.org/tsr");
      
          // Initialize a signature field to hold the signature:
          SignatureField sf = new SignatureField();
          sf.Widget.Rect = new RectangleF(72, 72 * 2, 72 * 4, 36);
          sf.Widget.Page = page;
          sf.Widget.BackColor = Color.LightSeaGreen;
          sf.Widget.TextFormat.Font = StandardFonts.Helvetica;
          sf.Widget.ButtonAppearance.Caption = $"Signer: " +
              $"{sp.SignerName}\r\nLocation: {sp.Location}";
          // Add the signature field to the document:
          doc.AcroForm.Fields.Add(sf);
      
          // Connect the signature field and signature properties:
          sp.SignatureField = sf;
      
          // Sign and save the document:
          // NOTES:
          // - Signing and saving is an atomic operation, the two cannot be separated.
          // - The stream passed to the Sign() method must be readable.
          doc.Sign(sp, stream);
      
          // Rewind the stream to read the document just created 
          // into another GcPdfDocument and verify the signature:
          stream.Seek(0, SeekOrigin.Begin);
          GcPdfDocument doc2 = new GcPdfDocument();
          doc2.Load(stream);
          SignatureField sf2 = (SignatureField)doc2.AcroForm.Fields[0];
          if (!sf2.Value.VerifySignature())
              throw new Exception("Failed to verify the signature");
      
          // Done (the generated and signed document has already been saved to 'stream').
      }
      

    Back to Top

    Remove Digital Signature

    With GcPdf, it is easy to remove a digital signature from a PDF file. The library allows users to remove a signature from signature field, so that the contents of the PDF file can be used again.

    Pdf without a digital signature

    To remove the signature and keep the signature field in the PDF document, follow these steps:

    1. Initialize an instance of GcPdfDocument class and load the PDF file.
    2. To remove all the signatures in the document, call a recursive method which loops through all the signature fields in the PDF file and set the Value property of the SignatureField class to null.
    3. Save the document.
      C#
      Copy Code
      var doc = new GcPdfDocument();
      using (var fs = new FileStream( "TimeSheet.pdf", FileMode.Open, FileAccess.Read))
      {
          doc.Load(fs);
      
          // Fields can be children of other fields, so we use
          // a recursive method to iterate through the whole tree:
          removeSignatures(doc.AcroForm.Fields);
      
          doc.Save("TimeSheet_NoSign.pdf"); //Save the document
      
          void removeSignatures(FieldCollection fields)
          {
              foreach (var f in fields)
              {
                  if (f is SignatureField sf)
                      sf.Value = null; //removes the signatures from the document
                  removeSignatures(f.Children);
              }
          }
      }
      

    Back to Top

    Extract Signature Properties

    GcPdf allows you to extract signature information from a digital signature in a PDF document by using Content property of Signature class. The signature information provides necessary details about the signature which can be used to verify its validity. Some of the information fields which can be extracted from a signature are Issuer, IssuerName, SerialNumber, Subject, Thumbprint, NotAfter, NotBefore, SignatureAlgorithm etc.

    To extract signature information from a digital signature in PDF document, follow these steps:

    1. Load the signed document and get the signature using Fields property of AcroForm class.
    2. Use the Content property of Signature class to get the additional information about the signature.
      C#
      Copy Code
      MemoryStream ms = new MemoryStream(File.ReadAllBytes(@"AdobePDFWithEmptySignatureField.pdf"));
      GcPdfDocument doc = new GcPdfDocument();
      doc.Load(ms);
      
      //initialize a certificate
      X509Certificate2 cert = new X509Certificate2(@"User.pfx", "User12");
      SignatureProperties sp = new SignatureProperties();
      sp.Location = "MACHINE";
      sp.SignerName = "USER";
      sp.SigningDateTime = null;
      sp.SignatureField = doc.AcroForm.Fields["EmptySignatureField"];
       
      using (MemoryStream ms2 = new MemoryStream())
      {
          //sign document
          doc.Sign(sp, ms2, false);
          ms2.Seek(0, SeekOrigin.Begin);
       
          //load signed document
          GcPdfDocument doc2 = new GcPdfDocument();
          doc2.Load(ms2);
       
          //get signature field and signature
          SignatureField sf2 = (SignatureField)doc2.AcroForm.Fields["EmptySignatureField"];
          var sk = sf2.Value.Content;
      
          //get certificate and print its props
          var sc = sk.SigningCertificate;
          Console.WriteLine($"Subject: {sc.Subject}");
          Console.WriteLine($"Issuer: {sc.Issuer}");
          Console.WriteLine($"GetEffectiveDateString: {sc.GetEffectiveDateString()}");
          Console.WriteLine($"GetExpirationDateString: {sc.GetExpirationDateString()}");
      }
      

    Back to Top

    Custom Implementation of Digital Signature

    GcPdf provides ISignatureBuilder and IPkcs7SignatureGenerator interfaces which can be used to achieve the custom implementation of digital signatures. The Pkcs7SignatureBuilder class implements the ISignatureBuilder interface and provides various methods and properties such as:

    Some of the custom signature implementations are described below:

    Sign Document using Certificate from .p12 file

    To sign a document using certificate from .p12 file, follow these steps:

    1. Instantiate SignatureProperties class and use its object to initialize Pkcs7SignatureBuilder class.
    2. Build a chain of certificates by passing a .p12 filename and its password to GetCertificateChain method of SecurityUtils class.
    3. Add the signature field to the document using Fields property of AcroForm class.
    4. Sign and save the PDF document using Sign method of GcPdfDocument class. 
      C#
      Copy Code
      using (FileStream fs = new FileStream(@"AdobePDFWithEmptySignatureField.pdf", FileMode.Open))
      {
          GcPdfDocument doc = new GcPdfDocument();
          doc.Load(fs);
      
          SignatureProperties sp = new SignatureProperties();
          sp.SignatureBuilder = new Pkcs7SignatureBuilder()
          {
              CertificateChain = SecurityUtils.GetCertificateChain("1571753451.p12", "test"),
          };
          sp.SignatureField = doc.AcroForm.Fields[0];
          doc.Sign(sp, "signed.pdf");
      }
      

    Back to Top

    Sign Document using USB Token

    You can sign a document using a USB token with a valid certificate. For details, please refer to this demo.

    Sign Document using Certificate from Azure Key Vault

    You can sign a document using a certificate stored in Azure Key Vault. For details, please refer to this demo.

    PDF Advanced Electronic Signatures

    GcPdf lets you digitally sign PDF documents using PDF Advanced Electronic Signatures (PAdES). PAdES is a set of standards referring to a group of extensions and restrictions used when PDF documents are signed electronically. The documents signed using PAdES format remain valid for longer periods.

    In PAdES, the following levels of verification of digital signatures are supported by GcPdf:

    In GcPdf, you can use CreatePAdES_B_B and CreatePAdES_B_T methods of SignatureProperties class to create B-B and B-T level of signatures in a PDF document. It further provides GrapeCity.Documents.Pdf.Security.DocumentSecurityStore class and GcPdfDocument.TimeStamp() method to facilitate creation of advanced electronic signatures such as B-LT and B-LTA levels.

    Create PAdES B-B Signature

    To create a PAdES B-B signature, follow these steps:

    1. Initialize a certificate using the X509Certificate2 class and pass the certificate file name and password to access the certificate.
    2. Pass the certificate instance to CreatePAdES_B_B method of SignatureProperties class to create a PAdES B-B signature.
    3. Set the first AcroForm field to store the signature using SignatureField property.
    4. Sign and save the PDF document using Sign method of GcPdfDocument class. 
      C#
      Copy Code
      using (FileStream fs = new FileStream(@"AdobePDFWithEmptySignatureField.pdf", FileMode.Open))
      {
          GcPdfDocument doc = new GcPdfDocument();
          doc.Load(fs);
      
          X509Certificate2 cert = new X509Certificate2("User.pfx", "User12");
          SignatureProperties sp = SignatureProperties.CreatePAdES_B_B(cert);
          sp.SignatureAppearance.Caption = "PAdES B-B";
          sp.SignatureField = doc.AcroForm.Fields[0];
          doc.Sign(sp, "signed_PAdES_B_B.pdf");
      }
      

    Back to Top

    Create PAdES B-T Signature

    To create a PAdES B-T signature, follow these steps:

    1. Initialize a certificate using the X509Certificate2 class and pass the certificate file name and password to access the certificate.
    2. Pass the timestamp and certificate instance to CreatePAdES_B_T method of SignatureProperties class to create a PAdES B-T signature.
    3. Set the first AcroForm field to store the signature using SignatureField property.
    4. Sign and save the PDF document using Sign method of GcPdfDocument class.
      C#
      Copy Code
      using (FileStream fs = new FileStream(@"AdobePDFWithEmptySignatureField.pdf", FileMode.Open))
      {
          GcPdfDocument doc = new GcPdfDocument();
          doc.Load(fs);
      
          X509Certificate2 cert = new X509Certificate2("User.pfx", "User12");
          SignatureProperties sp = SignatureProperties.CreatePAdES_B_T(new TimeStamp("https://freetsa.org/tsr"), cert);
          sp.SignatureAppearance.Caption = "PAdES B-T";
          sp.SignatureField = doc.AcroForm.Fields[0];
          doc.Sign(sp, "signed_PAdES_B_T.pdf");
      }
      

    Back to Top

    Create PAdES B-LT Signature

    B-LT signature is built on the B-T signature by adding all the properties required for long-term validation of the signature. To create a PAdES B-LT signature, follow these steps:

    1. Create a PAdES B-T signature and save the PDF document.
    2. Add LTV information to the signatures using AddVerification method of the DocumentSecurityStore class.
    3. Sign and save the document in incremental update mode using the Save method.
      C#
      Copy Code
      public int CreatePDF(Stream stream)
      {
          var doc = new GcPdfDocument();
          using var s = File.OpenRead(Path.Combine("Resources", "PDFs", "SignPAdESBT.pdf"));
          doc.Load(s);
      
          //Add a B-T Level signature
          var pfxPath = Path.Combine("Resources", "Misc", "GcPdfTest.pfx");
          var cert = new X509Certificate2(pfxPath, "qq");
          var sp = SignatureProperties.CreatePAdES_B_T(new TimeStamp("https://freetsa.org/tsr"), cert);
          sp.SignatureAppearance.Caption = "PAdES B-LT";
          sp.SignatureField = doc.AcroForm.Fields[0];
          doc.Sign(sp, stream);
          doc.Load(stream);
      
          // Adds LTV information which makes the signature compliant with PAdES B-LT:
          SignatureField signField = (SignatureField)doc.AcroForm.Fields[0];
          var sig = signField.Value;
          var vp = new DocumentSecurityStore.VerificationParams();
          var pfxPath = Path.Combine("CACertCertificate.pfx");
          var cert = new X509Certificate2(pfxPath, "1234");
          vp.Certificates = new X509Certificate2[] { cert };
          if (!doc.SecurityStore.AddVerification(sig, vp))
              throw new Exception($"Could not add verification for {sig.Name}.");
          doc.Save("SignedLTV.pdf", SaveMode.IncrementalUpdate);
      
          //Done.
          return doc.Pages.Count;
      
      }
      

    Create PAdES B-LTA Signature

    B-LTA signature is built on the B-LT signature by adding time stamp token on the validation material. To create a PAdES B-LTA signature, follow these steps:

    1. Create a PAdES B-LT signature and save the PDF document.
    2. Add timestamp to the B-LT signed PDF by using TimeStampProperties class to make it compliant with PAdES B-LTA level.
    3. Call the TimeStamp() method and save the document with time stamp properties.
      C#
      Copy Code
      public int CreatePDF(Stream stream)
      {
          var doc = new GcPdfDocument();
          using var s = File.OpenRead(Path.Combine("Resources", "PDFs", "SignPAdESBT.pdf"));
          doc.Load(s);
      
          //Add a B-T Level signature
          var pfxPath = Path.Combine("Resources", "Misc", "GcPdfTest.pfx");
          var cert = new X509Certificate2(pfxPath, "qq");
          var sp = SignatureProperties.CreatePAdES_B_T(new TimeStamp("https://freetsa.org/tsr"), cert);
          sp.SignatureAppearance.Caption = "PAdES B-LTA";
          sp.SignatureField = doc.AcroForm.Fields[0];
          doc.Sign(sp, stream);
          doc.Load(stream);
      
          // Adds LTV information 
          SignatureField signField = (SignatureField)doc.AcroForm.Fields[0];
          var sig = signField.Value;
          var vp = new DocumentSecurityStore.VerificationParams();
          var pfxPath = Path.Combine("CACertCertificate.pfx");
          var cert = new X509Certificate2(pfxPath, "1234");
          vp.Certificates = new X509Certificate2[] { cert };
          if (!doc.SecurityStore.AddVerification(sig, vp))
              throw new Exception($"Could not add verification for {sig.Name}.");
          doc.Save("SignedLTV.pdf", SaveMode.IncrementalUpdate);
      
          doc.Load(stream);
          //Adds time stamp to a signed PDF which makes the document compliant with B-LTA level
          TimeStampProperties ts = new TimeStampProperties()
          {
              TimeStamp = new TimeStamp(@"http://ts.ssl.com"),
          };
          // Save the PDF to a file adding a time stamp to it:
          doc.TimeStamp(ts, stream);
      
          //Done.
          return doc.Pages.Count;
      }