Validating a Digital Signature in iOS

PSPDFKit supports validating digital signatures embedded in PDF documents. The digital signature validation process consists of two steps.

  • In the first step, we check if the signature certificate embedded during signing can be trusted. To do this, we need to obtain the trusted certificate from the authority that issued it, a root CA certificate, or an intermediate CA certificate. For your convenience, PSPDFKit already provides the Adobe Root CA. This CA is also typically loaded by third-party readers.

  • In the second step, we verify the signature. This process essentially decrypts the signature with a public key from the certificate embedded in the PDF file on signing and compares it with the message digest built from the PDF file, excluding the signature itself.

Here’s an example of how to provide the trusted certificate:

do {
    // Load a certificate (with a public key) from a `p7` archive.
    let certificateData = try Data(contentsOf: p7URL)
    let certificates = try X509.certificatesFromPKCS7Data(certificateData)

    for certificate in certificates {
        signatureManager.addTrustedCertificate(certificate)
    }
} catch {
    // Don't forget to check for errors here.
}
// Load a certificate (with a public key) from a `p7` archive.
NSData *certificateData = [NSData dataWithContentsOfURL:p7URL];

NSError *error = nil;
NSArray *certificates = [PSPDFX509 certificatesFromPKCS7Data:certData error:&err];

// Don't forget to check for errors here.

for (PSPDFX509 *certificate in certificates) {
	[signatureManager addTrustedCertificate:certificate];
}

The PDFSignatureValidator can then validate the signature in the SignatureFormElement with verifySignature(withTrustedCertificates:).

Here’s an example showing how to validate a signature and get its status:

// Validate the signed document.
let validator = PDFSignatureValidator(signatureFormElement: signatureFormElement)
do {
	let status = try validator.verifySignature(withTrustedCertificates: certificates)
	// Decide what to do with the status.
} catch {
	// Handle errors.
}
// Validate the signed document.
PSPDFSignatureValidator *validator = [[PSPDFSignatureValidator alloc] initWithSignatureFormElement:signatureFormElement];
PSPDFSignatureStatus *status = [validator verifySignatureWithTrustedCertificates:certificates error:error];

This can be very useful for the topic that comes next.

Validation Statuses

If you validate a digital signature with PSPDFKit, either programmatically or using our UI, there can be several possible statuses for the signature. Programmatically, the PDFSignatureStatus class contains a property, signatureIntegrityStatus, that can be queried to determine if the document was altered in some way after it was digitally signed. Additionally, the coversEntireDocument Boolean property is useful if the document has many digital signatures. If coversEntireDocument returns false, it means the digital signature only covers a particular revision of the document — that is, there may be subsequent revisions covered by digital signatures that were applied later on.

Let’s take a look at our validation UI when the document is signed with a self-signed certificate:

In this sample case, the first paragraph informs us of the general status of the digital signature. Next, the signer name and signing date is shown. This information always comes from the certificate itself, so you don’t have programmatic access to modify it. Following that paragraph, the integrity status of the document is displayed. In this case, the document has not been modified since it was signed, which is a good sign. Finally, the UI lets us know that the certificate used for signing was a self-signed certificate. This is not necessarily bad, but we find out about this situation with a severity level of “warning.”

Below we can see what happens if we try to validate a signature with an expired certificate.

In this case, we are informed that the certificate is not valid because it has expired. To prevent confusing our users, our default UI does not show the integrity status of a document if the certificate validation failed (that is, if the general signature status is “error”).

Below is the validation UI that is shown when the certificate is not self-signed or hasn’t expired but is not yet trusted by PSPDFKit.

Validation in Adobe Acrobat

Once you’ve signed a PDF document using PSPDFKit, you’ll notice that after opening it in Adobe Acrobat, you might get the following validation status.

This warning is informing you that the reader application has verified that the document has not been modified since the last time it was signed, but that the certificate is not yet trusted. You can configure the certificate as a trusted anchor in Adobe Acrobat by following the instructions provided by Adobe.

Alternatively, if the PDF is opened in a Windows environment, you can configure Adobe Acrobat to automatically trust every certificate in the Windows Certificate Store by clicking Edit > Preferences > Security > Advanced Preferences, and then checking Enable searching the Windows Certificate Store for the following operations. Use this option with caution, as it might pose a security risk.

Adobe Acrobat 9 introduced a new program to make the validation process more user-friendly: the Adobe Approved Trust List (AATL). Businesses that provide certificates to their users can apply to this program by submitting application materials and their root certificates. Once approved, Adobe Acrobat will automatically download and trust every certificate that is part of this program.