Skip to main content
A newer version of this page is available. .

Sign Documents

  • 9 minutes to read

You can use the PDF Document API to apply multiple signatures. A signature is used to authenticate the user’s identity and document contents.

VisualSignature

A signature contains validation data (certificate, hash algorithm, timestamp, etc.) and visual parameters (image and signer information). The signature appears in the corresponding form field that defines that signature’s location and size.

You can apply a signature to an existing form field or create a new signature field and sign it.

Create a Signature Form Field

You can use the PdfSignatureFieldInfo class to specify the signature field’s parameters (name, location and rotation angle).

The code sample below creates a new signature field:

//Specify the name and location of the signature field
var signatureFieldInfo = new PdfSignatureFieldInfo(1);
signatureFieldInfo.Name = "SignatureField";
signatureFieldInfo.SignatureBounds = new PdfRectangle(10, 10, 150, 150);
signatureFieldInfo.RotationAngle = PdfAcroFormFieldRotation.Rotate90;

Sign a Form Field

Use the PdfSignatureBuilder class to apply a signature to the form field. The PDF Document API supports PKCS#7 signatures with X.509 certificates and document-level time timestamps. The PdfDocumentSigner class allows you to sign and save a document.

The table below lists API used to sign a form field:

API Description
PdfDocumentSigner Signs the document. Pass the document to sign to the object’s constructor.
Pkcs7Signer Creates a PKCS#7 signature. Specify the signature certificate and password in the object’s constructor. Use the PdfSignatureProfile enumeration to specify the signature profile (PAdES or standard PDF).
PdfSignatureBuilder Applies a signature to a form field. Specify the signature field’s name in the object’s constructor to sign this field. If the field with the specified name does not exist, an ArgumentException is thrown.
Use the PdfSignatureFieldInfo object to create a new form field. Refer to the previous section for a code sample.
PdfSignatureBuilder.SetImageData Specifies the signature’s image data. You can provide data in the BMP, JPEG, PNG, and EMF+ formats. The image is not displayed if the form field’s SignatureBounds property is not specified.
PdfSignatureBuilder.Name Gets or sets the name of the person or authority who signs the document.
PdfSignatureBuilder.Location Gets or sets the location associated with the signer’s identity.
PdfSignatureBuilder.ContactInfo Specifies the signer’s contact information.
PdfSignatureBuilder.Reason Gets or sets the reason to sign the document (for example, “I Agree”).
PdfSignatureBuilder.CertificationLevel Defines what changes are available to users when the signature is applied. If a user makes a restricted change, the signature becomes invalid.
PdfDocumentSigner.SaveDocument Applies the signature(s) and saves the document.

The code sample below applies a digital signature to a new and existing form field and signs a document with these signatures:

Note

A complete sample project is available in the following repository: How to Apply Multiple Signatures.

using System;
using DevExpress.Pdf;
using System.Diagnostics;
using System.IO;

//Load a document to sign:
using (var signer = new PdfDocumentSigner("Document.pdf"))
{
    //Create a PAdES PKCS#7 signature
     Pkcs7Signer pkcs7Signature = new Pkcs7Signer("Signing Documents/certificate.pfx", "123", PdfHashAlgorithm.SHA256,
      tsaClient, null, null, PdfSignatureProfile.PAdES_BES);

    //Apply a signature to a newly created signature field:
    var cooperSignature = 
    new PdfSignatureBuilder(pkcs7Signature, signatureFieldInfo);

    //Specify an image and signer information:
    cooperSignature.SetImageData(File.ReadAllBytes
    ("Signing Documents//JaneCooper.jpg"));
    cooperSignature.Location = "USA";
    cooperSignature.Name = "Jane Cooper";
    cooperSignature.Reason = "Acknowledgement";

    //Apply a signature to an existing form field:
    var santuzzaSignature = 
    new PdfSignatureBuilder(pkcs7Signature, "Sign");

    //Specify an image and signer information:
    santuzzaSignature.SetImageData(File.ReadAllBytes
    ("Signing Documents//SantuzzaValentina.jpg"));
    santuzzaSignature.Location = "Australia";
    santuzzaSignature.Name = "Santuzza Valentina";
    santuzzaSignature.Reason = "I Agree";
    santuzzaSignature.CertificationLevel = PdfCertificationLevel.FillFormsAndAnnotate;
    //Add signatures to an array:
    PdfSignatureBuilder[] signatures = { cooperSignature, santuzzaSignature };

    //Sign and save the document:
    signer.SaveDocument("SignedDocument.pdf", signatures);
}

You can create the Pkcs7SignerBase descendant and use a custom PKCS#7 signature builder. Refer to the following repository for a code sample: How to: Use a Custom Signer Class to Apply Signatures to the PDF Document.

Re-Sign the Form Field

You can remove a signature from a form field and sign it with another signature. Call the PdfDocumentSigner.ClearSignatureField method with the form field’s name passed as a parameter. Use the PdfDocumentSigner.GetSignatureFieldNames method to retrieve signed field names.

The code sample below shows how to retrieve signed form field names and apply a new signature to the first field:

using DevExpress.Pdf;
using System.Diagnostics;
using System.IO;

//Load a document to sign
using (var signer = new PdfDocumentSigner("Document.pdf"))
{
    //Create a PKCS#7 signature
    Pkcs7Signer pkcs7Signature = new Pkcs7Signer("Signing Documents//certificate.pfx", "123", PdfHashAlgorithm.SHA256);

    //Retrieve all signed form fields:
    var signedFields = signer.GetSignatureNames(false);

    //Clear the first signature field:
    signer.ClearSignatureField(signedFields[0]);

    //Apply a new signature to this form field
    var santuzzaSignature = new PdfSignatureBuilder(pkcs7Signature, signedFields[0]);

    //Specify image and signer information
    santuzzaSignature.SetImageData(File.ReadAllBytes("Signing Documents//SantuzzaValentina.jpg"));
    santuzzaSignature.Location = "Australia";
    santuzzaSignature.Name = "Santuzza Valentina";
    santuzzaSignature.Reason = "I Agree";

    //Sign and save the document
    signer.SaveDocument("SignedDocument.pdf", santuzzaSignature);
}

Call the PdfDocumentSigner.ClearSignatureFields() method to clear all signature fields.

Add a Signature Timestamp

Use the PdfTsaClient object to create a timestamp. Specify the URI of a timestamp server in the object constructor. You can specify the username and password to log into the server. If the server rejects the timestamp request, a TspValidationException is thrown.

Pass the PdfTsaClient object to the Pkcs7Signer instance as a constructor parameter. The code sample below shows how to create a signature with a timestamp:

ITsaClient tsaClient = 
new PdfTsaClient(new Uri(@"https://freetsa.org/tsr"), PdfHashAlgorithm.SHA256);
Pkcs7Signer pkcs7Signature = 
new Pkcs7Signer("Signing Documents//testcert.pfx", "123", PdfHashAlgorithm.SHA256, tsaClient);

You can create an ITsaClient interface implementation to create a custom timestamp client. Refer to the following repository for a code sample: How to: Use a Custom Timestamp Client to Apply Signatures to the PDF Document.

Sign a Form Field with a Document-Level Timestamp

The PdfTimeStamp object allows you to generate a document-level timestamp. Use the ITsaClient interface implementation to specify the timestamp client.

You can pass the PdfTimeStamp object to the PdfSignatureBuilder constructor to apply the document-level timestamp to the signature field.

using (var signer = new PdfDocumentSigner("Document.pdf"))
{
    //Create a timestamp:
    ITsaClient tsaClient = new PdfTsaClient(new Uri(@"https://freetsa.org/tsr"), PdfHashAlgorithm.SHA256);

    //Create a new signature form field:
    var signatureFieldInfo1 = new PdfSignatureFieldInfo(1);
    signatureFieldInfo1.Name = "SignatureField1";
    signatureFieldInfo1.SignatureBounds = new PdfRectangle(200, 200, 250, 250);

    //Create a document-level time stamp:
    PdfTimeStamp pdfTimeStamp = new PdfTimeStamp(tsaClient);

    //Apply this time stamp to the form field:
    var timeStampSignature = new PdfSignatureBuilder(pdfTimeStamp, signatureFieldInfo1);

    //Sign and save the document:
    signer.SaveDocument("SignedDocument.pdf", timeStampSignature);
}

Tip

Use the PdfDocumentProcessor to sign a PDF document. Refer to the following help topic for a code sample: How to: Use PdfDocumentProcessor to Add a Visual Signature into a PDF. Note, however, that this approach has limitations.

Sign a Document in Deferred Mode

Use the following API to apply a signature or a document-level timestamp to the document hash.

Member Description
ExternalSignerInfo Contains the signature parameters: type, size, hashing algorithm, etc.
PdfDeferredSignatureBuilder Allows you to build a signature for the document hash. Use the PdfSignatureFieldInfo object to apply a signature to a new form field. Specify the field name in the PdfDeferredSignatureBuilder object constructor to apply a signature to an existing form field.
PdfDocumentSigner.SignDeferred Adds the signature to the document and retrieves the document hash. The returned PdfDeferredSigner object contains the hash value.
PdfDeferredSigner.Sign Adds the signature contents and saves the document to the file or stream. Use the ITsaClient.GenerateTimeStamp(Byte[], String) or IExternalSigner.BuildSignature(Byte[], String) method to obtain the signature contents.

The code sample below uses a document hash to apply a signature externally:

using (var signer = new PdfDocumentSigner(File.OpenRead("SignDemo.pdf")))
{
  //Specify the information about the signature metadata:
  var digestCalculator = new PdfDigestCalculator(PdfHashAlgorithm.SHA256);

  var signerInfo = new ExternalSignerInfo(PdfSignatureType.Pkcs7, 8000, digestCalculator);

  //Create a new form field:
  var fieldInfo = new PdfSignatureFieldInfo(1) { SignatureBounds = new PdfRectangle(10, 10, 100, 100) };

  //Apply the metadata to the form field:
  var builder = new PdfDeferredSignatureBuilder(signerInfo, fieldInfo);

  //Add the signature to the document:
  var deferredSigner = signer.SignDeferred(builder);

  //Obtain the document hash and hash algorithm's object identifier:
  var digest = deferredSigner.HashValue;
  var digestAlgorithmOID = digestCalculator.AlgorithmOid;

  //Generate the signature content to insert into the document:
  byte[] signature = CreateSignature(digest, digestAlgorithmOID);

  //Add the signature contents and save the document to the file:
  deferredSigner.Sign("signed.pdf", signature);
}

static byte[] CreateSignature(byte[] digest, string digestAlgorithmOID)
{
  var signer = new Pkcs7Signer(@"SignDemo.pfx", "dxdemo");
  byte[] signature = signer.BuildSignature(digest, digestAlgorithmOID);
  return signature;
}
See Also