Digital Signatures

What are Digital Signatures

A digital signature is an electronic fingerprint, uniquely identifying the signing person. For more information on digital signatures please look at Digital Signatures in PDF. Also have a look at Section 12.8 Digital Signatures of the PDF 1.7 Specification.

For general information on how digital signatures work have a look here.

Considerations

PSPDFKit allows both signing existing signature form elements, as well as documents without a signature form element.

Supported signing algorithms are:

  • RSA
  • ECDSA

Supported hashing algorithms include:

  • MD4
  • MD5
  • SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512, SHA-512-256)

A hashing algorithm is an algorithm that converts a large amount of data (your PDF document) to a fixed-length string. If someone changes one bit of data in your PDF document, the hashing algorithm produces a different string, so if you store that hash inside the PDF document you could potentially know when it has been changed by a third party. However, as easy as it sounds, this approach is insecure. If someone knows the hashing algorithm that was used to sign the PDF, they could replace the hash inside the PDF so that it validates as authentic. To avoid this, PSPDFKit supports the concept of encryption algorithm.

Concretely, PSPDFKit supports RSA, one of the most popular public key encryption algorithms. ECDSA, an algorithm that is based on elliptic curve cryptography, is also supported. Cryptographic systems based on ECDSA are becoming the 'the facto' standard for messaging and systems security. For example, in their iOS Security white paper, Apple explains how they use ECDSA extensively in their mobile operating system, and its benefits compared to other algorithms. You can use OpenSSL to generate a self-signed RSA certificate using this OpenSSL command:

1
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem

ECDSA certificates can be created using the openssl ecparam command.

You can use a self-signed certificate for testing purposes, but you will need to make sure that certificate is trusted by all the devices the PDF is opened on (including PCs/Macs with Acrobat). A self signed certificate will probably also generate warnings about it's keyUsage extension (the self-signed certificate must permit certificate signing - keyCertSign, see RFC 5280).

In production always use a certificate from a valid Certificate Authority. Make sure that the certificate's keyUsage has digitalSignature permission set (see RFC 5280).

How to create Digital Signatures

To create a digital signature, you need 2 things:

  • An X509 certificate that contains your public key and your signer information.
  • Your private key.

The signing process produces the signature by encrypting the message digest from the PDF file with a private key. The certificate with its public key is added to the signature and saved in the PDF file. PSPDFKit provides a PSPDFPKCS12Signer for your convenience that loads a certificate with public and private key from a p12 archive. If you want to customize the signing process, you need to subclass PSPDFSigner. Keep in mind that certificates installed by user via opening .p12 container with built-in apps (via "Install Profile") will go to Apple access group and will only be available to Apple-provided apps such as Safari or Mail. See Apple Technical Q&A for more details and a suggested workaround - Technical Q&A QA1745

Here is an example of how to register a PSPDFPKCS12Signer:

Copy
1
2
3
4
5
6
7
8
9
// p12Data is an p12 archive NSData object
let p12 = PSPDFPKCS12(data: p12Data)

// Create a signer with a display name. the display name will shop up in the list of identities when you tap on a signature form field
let p12Signer = PSPDFPKCS12Signer(displayName: "John Appleseed", pkcs12: p12)

// Finally register your signer with the signature manager
let signatureManager = PSPDFKit.sharedInstance.signatureManager
signatureManager.register(p12Signer)
Copy
1
2
3
4
5
6
7
8
9
// p12Data is an p12 archive NSData object
PSPDFPKCS12 *p12 = [[PSPDFPKCS12 alloc] initWithData:p12Data];

// Create a signer with a display name. the display name will shop up in the list of identities when you tap on a signature form field
PSPDFPKCS12Signer *p12Signer = [[PSPDFPKCS12Signer alloc] initWithDisplayName:@"John Appleseed" PKCS12:p12];

// Finally register your signer with the signature manager
PSPDFSignatureManager *signatureManager = PSPDFKit.sharedInstance.signatureManager;
[signatureManager registerSigner:p12Signer];

User Interface

When creating a signature in the user interface, you need to provide either a certificate, draw an ink signature or use both. The document is only digitally signed if a certificate has been provided. Otherwise only the ink signature is added to the document.

By default, the user is able to select a certificate, if there are registeredSigners available. This behavior can be customized via PSPDFConfiguration.signatureCertificateSelectionMode.

Signing with a Form Element

If there are no stored signatures in the shared PSPDFSignatureStore, then tapping an empty signature form element shows a PSPDFSignatureViewController, where you can sign a document with an ink signature as well as assign a certificate to your signature:

If there are already stored signatures, a PSPDFSignatureSelectorViewController is shown instead, allowing you to choose an existing signature or create a new one:

Signing without a Form Element

If a document doesn't have a signature form element, you can still digitally sign this document. The way to initiate this flow is to tap on the signature toolbar button, then select or create a signature like shown above. If you added a certificate to the signature, you will be asked select the signature placement on the page, otherwise the signature is placed into the document and you can move and resize it to your liking. After making the selection, you are asked for the password of the certificate. After entering the password, the document is signed.

Biometric Signatures

Starting with PSPDFKit 7.0 for iOS, we automatically store biometric properties encrypted in the digital signature. These biometric properties are stored via PSPDFSignatureBiometricProperties, and includes data points about the creation of the ink signature. If no ink signature was used to digitally sign a document, this will be empty.

By default all available properties on PSPDFSignatureBiometricProperties are populated and stored. This can be customized to restrict this to only store specific properties via PSPDFConfiguration.signatureBiometricPropertiesOptions. When signing a document only the specified values are stored in the digital signature.

For example, to only store the touch radius and the input method biometric properties of the ink signature, you can use the following code:

Copy
1
2
3
let controller = PSPDFViewController(document: document, configuration: PSPDFConfiguration { builder in
    builder.signatureBiometricPropertiesOptions = [.touchRadius, .inputMethod]
})
Copy
1
2
3
PSPDFViewController *controller = [[PSPDFViewController alloc] initWithDocument:document configuration:[PSPDFConfiguration configurationWithBuilder:^(PSPDFConfigurationBuilder *builder) {
    builder.signatureBiometricPropertiesOptions = PSPDFSignatureBiometricPropertiesOptionTouchRadius | PSPDFSignatureBiometricPropertiesOptionInputMethod;
}]];

You can customize the properties that are stored by overriding -[PSPDFSignatureContainer initWithAnnotation:signer:biometricProperties:] and modifying the biometricProperties object to fit your needs.

The following biometric properties and data point are captured and stored in the digital signature when using the default document signing UI flow:

If you are creating digital signatures manually, you can pass a PSPDFSignatureBiometricProperties object to -[PSPDFSigner signFormElement:withCertificate:writeTo:appearance:biometricProperties:completionBlock:], which is then saved alongside the digital signature, encrypted with the signing certificate, in the document.

Signature Validation

PSPDFKit also needs to be able to validate signatures. The validation process consists of two steps.

  • In the first step we check if the signature certificate embedded on signing can be trusted. In order to do so, 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 is an example on how to provide the trusted certificate:

Copy
1
2
3
4
5
6
7
8
9
10
11
do {
    // Load a certificate (with a public key) from a p7 archive
    let certificateData = try Data(contentsOf: p7URL)
    let certificates = try PSPDFX509.certificatesFromPKCS7Data(certificateData)

    for certificate in certificates {
        signatureManager.addTrustedCertificate(certificate)
    }
} catch {
    // Don't forget to check for errors here
}
Copy
1
2
3
4
5
6
7
8
9
10
11
// 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];
}

You can also take a look at the PSPDFCatalog example project in the section FORMS AND DIGITAL SIGNATURES see the Digital signing process for the example of interactive (user driven) signing process and signature validation. In the Automated digital signing process see the example of non-interactive signing process.

Customizing Digital Signing

PSPDFKit offers various options to customize the digital signing experience, primarily via PSPDFDigitalSignatureCoordinator subclassing hooks.

A document that will be digitally signed will be copied, signed and saved to a new path, to keep the (unsigned) original document intact. You can customize the path where the digitally signed document should be saved by subclassing PSPDFDigitalSignatureCoordinator and overriding pathForDigitallySignedDocumentFromOriginalDocument:suggestedFileName: to return a custom path. The suggested file name parameter is a suggestion based on the title of the original document, if available, or the file name as a fallback. It can be used, as the last path component, in the path where the digitally signed document should be stored. The returned path will be sanitized, and it will be made sure that the suffix is .pdf.

You can also customize how the signed document should be presented. By default, this is done by pushing a new PSPDFViewController instance on the navigation controller, with the digitally signed document shown. This can be customized by overriding presentSignedDocument:showingPageIndex: in your PSPDFDigitalSignatureCoordinator subclass. By overriding this method, you are responsible to present/push the document, if that should be part of your digital signing experience. The pageIndex parameter is the page index of the signature form field, where the document was signed, where you can (optionally) automatically scroll to.

Customizing the Signature Appearance

During the signing process, you can customize how the final signature will be shown in the document.

PSPDFDigitalSignatureCoordinator provides configureSignatureAppearanceWithBuilder:document:signature:, which you can override to customize the signature appearance.

PSPDFSignatureAppearance has some boolean properties to decide whether the signer's name, date of signing, signature location, or signature reason should be shown after the document is signed. The appearanceMode property enables further configuration of the visual appearance, with two supported modes: PSPDFSignatureAppearanceModeSignatureAndDescription, and PSPDFSignatureAppearanceModeDescriptionOnly. If your signature field has some appearance that you want to keep after it's signed (for example, a border or watermark logo), set the reuseExistingAppearance property.

You can provide your own artwork (for example, a handwritten signature) that will be displayed on the left part of a signature field when its appearance mode is PSPDFSignatureAppearanceModeSignatureAndDescription. Set the signatureGraphic property of type PSPDFAnnotationAppearanceStream to accomplish that. You can create a PSPDFAnnotationAppearanceStream with either a JPEG image or a PDF document.

If you are signing a document programmatically, you can pass the PSPDFSignatureAppearance class to any of the signing methods in PSPDFSigner.

The default signature appearance, when proving an ink signature, looks like this:

Creating a Custom Signer

In order to customize the signing process you can subclass PSPDFSigner. Then you register the signer with the signature manager just like described above. Please have a look at the documentation in the PSPDFSigner header file for more information on what methods you need to override.

How does Adobe Acrobat validate a document signed by PSPDFKit?

Once you have 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 trusted yet. You can configure the certificate as a trusted anchor in Adobe Acrobat by following these instructions: Get Certificates from Other Users

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 check "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: 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. There's more information about this program at Adobe Approved Trust List