Getting Started with PDFSign and PDFVerify

Requirements: Secure PDF

Introduction

Secure PDF is a suite of components that can sign, verify, encrypt, and decrypt PDF documents, following modern PDF and PAdES security standards.

This guide will focus specifically on the PDFSign and PDFVerify components for signing and verifying PDF documents respectively. Before continuing, it is recommended to download the latest version of Secure PDF in order to follow along with this guide.

Contents

Overview

PDF signatures establish proof of authenticity and document integrity. Their role is to confirm that documents are genuinely created by the entity claiming authorship. Once the document is signed, recipients can later verify the signature to ensure that the document was indeed published by the expected entity and has not been tampered with. Like encrypted documents, signed PDF documents are still valid PDF documents and can be opened with PDF management software without taking extra action.

Chain Validation Overview

Before diving into the specifics of each component, it is important to understand how certificate chain validation works. For advanced PDF signatures, particularly PAdES signatures, full-scale chain validation plays a central role in the signing, updating, and verification processes. It ensures that each certificate in the chain, from the signing certificate up to the root, is valid and was issued by a Certificate Authority (CA) that is trusted in the current environment.

To establish trust for a particular certificate, an intricate procedure is performed that involves:

  • Validating a linked list of certificate signatures,
  • Checking certificates' validity against revocation sources including CRL (Certificate Revocation Lists) endpoints or OCSP (Online Certificate Status Protocol) responders,
  • Checking certificate validity periods, key usages, and policies, and
  • Establishing whether anchor certificates reside in designated trust sources (local trust stores or Trusted Lists).
Essentially, the procedure consists of a chain of individual validations of a collection of elementary objects (certificates, OCSP responses, CRLs, etc.), with the purpose of building a chain of trust to a known trust anchor – a root certificate that typically resides somewhere on the system. Complete validation is the only way to determine with certainty that a certificate was valid and trusted at the time of signing.

Note that full chain validation is required not only when verifying signatures but also often during the signing process. This is because it collects revocation information which, for example, must be embedded into the document to ensure proper validation of long-term validation (LTV) signatures.

PDFSign

The PDFSign component can sign PDF documents in accordance with a selection of PDF and PAdES signature standards, including basic Adobe signatures (ISO 32000) and PAdES signatures (ETSI EN 319 142-1).

Preparing the Signature

To configure PDFSign to produce the desired signature, first provide the input document as a file (InputFile), byte array (InputData), or stream (SetInputStream) and assign your signing certificate to the SigningCert property. Then indicate where to save the output document by setting OutputFile or calling SetOutputStream.

Optionally specify the Signature* properties and the TimestampServer property, and adjust any chain validation parameters as necessary (please see the Chain Validation Setup section for more details). Finally, call the Sign method.

PDFSign also provides means to customize the appearance of the signature widget to be shown on the document page. You can create your very own signatures (e.g., in the form of your company's logo) by adjusting the widget properties available in the SetWidgetProperty method. Alternatively, you can choose not to associate any widget with your signature by setting the Invisible widget property to true.

The Signing Process

Depending on the configuration, the signing process may be as straightforward as calculating the document hash and signing it with the private key, or it may involve the advanced chain validation routine. During the latter, the component may contact external revocation (i.e., CRL and OCSP endpoints) and trust sources to establish the validity of the signing certificate.

If an external TSA server was provided via the TimestampServer property, the component will also contact it to timestamp the new signature.

During signing, PDFSign may fire events to notify your code about certain conditions. For example, if the input document is encrypted but no decryption parameters were found in the Password or DecryptionCert properties, the component will fire either the Password or RecipientInfo event to tell your code that it needs decryption information to be able to continue with the signing. Additionally, the SSLServerAuthentication event will fire if one of the HTTP endpoints involved during the operation (which may be a TSA, CRL, OCSP, or Trusted List service) operates over TLS and needs its certificate to be validated.

Basic Adobe Signatures

A basic (also known as legacy) Adobe signature is an original Adobe Acrobat document signature. This is an outdated form of PDF signature – while PAdES is loosely built on it, this signature type does not support extended features and is not compliant with PAdES. Unless the recipient of your signed documents expects you to specifically use this kind of signature, it is unlikely that you will ever need it.

PAdES Signatures and Profiles

In PAdES, a given signature's profile describes the level of "completeness" of the validation material (i.e., certificates, CRLs, and OCSP responses) included in the signature. For example, signatures compliant with the PAdES B-B or PAdES B-T profiles do not require any validation material at all, whereas signatures compliant with the PAdES B-LTA profile must contain complete validation material.

PAdES B-B

The PAdES B-B profile is the baseline profile that uses the PAdES-BES signature level by default, meaning the signature only contains the signing time and signer information.

Use the following code to create a B-B signature:

pdfsign.InputFile = "input.pdf"; pdfsign.OutputFile = "signed.pdf"; pdfsign.SigningCert = new Certificate(CertStoreTypes.cstPFXFile, "cert.pfx", "password", "*"); pdfsign.SignatureProfile = PDFSignSignatureProfiles.pfBaselineB; pdfsign.ValidationPolicy = PDFSignValidationPolicies.vpNone; pdfsign.Sign();

PAdES-EPES

To instead create a PAdES-EPES signature that includes the signature-policy-identifier attribute, set the PolicyHash, PolicyHashAlgorithm, and PolicyId configuration settings before calling the Sign method.

This profile, in both the BES and EPES settings, creates a basic signature that remains valid as long as the signing certificate has not expired or been revoked. Signatures at this level need not contain any validation material.

PAdES B-T

The PAdES B-T profile extends the basic BES or EPES signature by adding a signature timestamp. This timestamp certifies that the signature was created at a specific moment in time. Similar to the B-B profile, signatures at this level need not contain any validation material.

Use the following code to create a B-T signature:

pdfsign.InputFile = "input.pdf"; pdfsign.OutputFile = "signed.pdf"; pdfsign.SigningCert = new Certificate(CertStoreTypes.cstPFXFile, "cert.pfx", "password", "*"); pdfsign.SignatureProfile = PDFSignSignatureProfiles.pfBaselineT; pdfsign.TimestampServer = "https://freetsa.org/tsr"; pdfsign.ValidationPolicy = PDFSignValidationPolicies.vpNone; pdfsign.Sign();

PAdES B-LTA

The PAdES B-LTA profile is used to achieve signatures that are equipped with long-term archival (LTA) or LTV capabilities. It incorporates into the signature all the material required to validate the signature, including signing certificates, timestamping certificates, and revocation information. It also adds a document timestamp, which certifies the integrity of both the document and the complete validation material at a specific moment in time. This guarantees that no relevant certificates were expired or revoked at the signature creation time, and enables the signature to be verified offline.

Creating a B-LTA signature with PDFSign is a two-step process. First Sign the document and add a signature timestamp, setting SignatureProfile appropriately. Then Update the signature to take care of the rest (collect and embed the validation material, and add a document timestamp):

pdfsign.InputFile = "input.pdf"; pdfsign.OutputFile = "signed.pdf"; pdfsign.SigningCert = new Certificate(CertStoreTypes.cstPFXFile, "cert.pfx", "password", "*"); pdfsign.SignatureProfile = PDFSignSignatureProfiles.pfBaselineLTA; pdfsign.TimestampServer = "https://freetsa.org/tsr"; pdfsign.Sign(); // Update the signature to LTV - this will retrieve the necessary revocation // elements, embed them into the document, and add a document timestamp pdfsign.Reset(); pdfsign.InputFile = "signed.pdf"; pdfsign.OutputFile = "updated.pdf"; pdfsign.TimestampServer = "https://freetsa.org/tsr"; pdfsign.Update();

Note that validation material "completeness" can be subjective and depends on several factors, including:

  • The working environment. For example, your organization may explicitly trust its own self-signed TSA certificate. Signatures timestamped with this certificate will be considered B-LTA by your organization, but for any external bodies, those signatures would be rendered as B-LT or even B-B, as they do not know or trust the custom TSA certificate.
  • The time that has passed since the last document timestamp. If an archived (B-LTA) document is not re-timestamped before its last timestamp expires, it will drop back to a lower signature level.

PDFVerify

The PDFVerify component verifies electronic signatures over PDF documents. Basic Adobe and PAdES signatures are supported.

PDFVerify validates each signature from two perspectives: the integrity and validity of the signature itself (i.e., its correspondence to the document data it covers), and the validity and trustworthiness of the signing certificate chain. These two signature aspects are generally independent of each other – the signature may be valid but the chain may not be trusted, or the chain may be trusted but the integrity of the signature may be violated. Under normal circumstances, both the signature and the chain must be valid for the signature to be considered good.

Preparing the Validation

To initiate the validation, first provide the signed PDF document as a file (InputFile), byte array (InputData), or stream (SetInputStream). Then adjust any chain validation parameters as necessary (please see the Chain Validation Setup section for more details) and call the Verify method.

For every signature in the document, PDFVerify will fire the SignatureInfo event, allowing you to specify whether you want the component to validate the signature, the chain, or both.

Once SignatureInfo returns, PDFVerify proceeds to the signature validation routine in accordance with the provided settings.

Validation Results

Upon completion of the validation, the SignatureProcessed event is fired, and the validation results are published here as well as in the following fields of the associated PDFSignature object:

  • SignatureValidationResult contains the outcome of the signature validation: valid, corrupted, the signing certificate was missing, or failed.
  • ChainValidationResult contains the primary result of the chain validation routine: valid, valid but untrusted, invalid, or undefined.
  • ChainValidationDetails provides the details of the factors that contributed to the chain validation result, such as an outdated certificate, a missing CRL, or a missing CA certificate.
Other information about the signature can be accessed via the Signatures property.

Checking Signature Coverage

The PDF format uses incremental updates to introduce changes to the document. This implies that a signature may not cover the whole document, but rather a certain revision of it. Strictly speaking, every signature in a PDF document, apart from potentially the last one, covers just some part of the document. In most cases, that part matches the revision of the document that existed before all the subsequent signatures were added.

Because of these specifics of the PDF format, it is crucially important to understand which part of the document is covered by a specific signature. Use the CoverageEndsAt field of the associated PDFSignature object to establish the scope of a signature. The revision of the document covered by that specific signature ranges from byte 0 to CoverageEndsAt. Alternatively, you can use the GetSignedVersion method to extract the signed revision to a file.

Chain Validation Setup

Chain validation is a sophisticated, multi-faceted procedure that involves a lot of variables. Depending on the configuration of your operating environment, the specifics of the PKI framework being used, and the validation policy you need to follow, you may want to adjust your chain validation parameters to best fit your requirements. A summary of these parameters is given below.

Note that these parameters apply to the Sign and Update methods in PDFSign as well as the Verify method in PDFVerify, as all three methods execute the chain validation procedure (if it is enabled).

Validation Policy

The ValidationPolicy property dictates how thoroughly the chain will be validated. It includes options to control which checks the component will perform, allowing you to tailor the validation process to meet your specific security needs. For example, if it is not essential to check each certificate's revocation status, set this property to vpFullNoRevocation.

Revocation

The revocation aspect of chain validation is controlled by the RevocationCheck property, which allows you to choose between and prioritize revocation origins. Note that OCSP sources are often preferred to CRL endpoints because of their real-time capability and the smaller size of the responses they produce.

Trust

The trust aspect of chain validation is controlled by the TrustSources property, which allows you to specify the locations in which the component will search for trust anchors. Local system stores, your own trusted root certificates (via the TrustedCerts property), and Trusted Lists (via the TrustedLists property) are all supported.

Offline Mode

The OfflineMode property provides the ability to verify the document without contacting online sources. If this property is enabled, the component will only use KnownCerts, TrustedCerts, data structures within the document itself, and revocation and Trusted List data that it previously saved to its internal cache when looking for missing validation material.

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.