Blog Post

How to Sign a PDF on iOS with PSPDFKit's Signature Library

Stefan Kieleithner
Illustration: How to Sign a PDF on iOS with PSPDFKit's Signature Library

In this post, you’ll learn how to programmatically add electronic and digital signatures to a PDF in your iOS application using PSPDFKit’s iOS signature library.

This post will also cover how to generate a self-signed certificate authority (CA) certificate, a CA private key, a signer certificate, and a private key required for a digital signature.

Requirements

To get started, you’ll need:

Getting Started

To follow along, create a fresh Xcode project and add PSPDFKit to your project. For step-by-step instructions, follow our Getting Started on iOS guide.

Adding Electronic Signatures Programmatically on iOS

Information

If you want users to provide their signature, you can also use PSPDFKit’s built-in signing user interface. See our adding electronic signatures guide to learn more.

Electronic signatures in PSPDFKit are sometimes referred to as signature annotations because they’re modeled using annotations.

Electronic signatures can either be an ink annotation or a stamp annotation. You can mark an annotation as a signature by setting the isSignature property to true.

Information

Signature annotations can be created, updated, and deleted if your license includes either the Annotations component or the Electronic Signatures component. If your license includes Electronic Signatures but not Annotations, then signatures are the only type of annotation that can be modified.

  1. Import PSPDFKit and PSPDFKitUI at the top of your UIViewController subclass implementation:

    import PSPDFKit
    import PSPDFKitUI
  2. Get the document you want to sign. You can use our sample PDF, which has a signature form element. After downloading the document, add it to your project:

    let fileURL = Bundle.main.url(forResource: "Form", withExtension: "pdf")!
    let document = Document(url: fileURL)
  3. Create an ink annotation:

    let annotation = InkAnnotation()
    annotation.color = UIColor(red: 0.7, green: 0.3, blue: 0.8, alpha: 1)
    annotation.lineWidth = 5
    
    // This example code is just hardcoding a stroke with three points.
    let lines = [[
        DrawingPoint(location: CGPoint(x: 450, y: 130), intensity: 0.5),
        DrawingPoint(location: CGPoint(x: 550, y: 30), intensity: 0.5),
        DrawingPoint(location: CGPoint(x: 650, y: 100), intensity: 0.5)
    ]]
    annotation.lines = lines
  4. Mark the annotation as a signature:

    annotation.isSignature = true
  5. Add the annotation to the document:

    document.add(annotations: [annotation])
  6. Present the PDF view controller:

    let pdfController = PDFViewController(document: document)
    // Present the PDF view controller within a `UINavigationController` to show built-in toolbar buttons.
    present(UINavigationController(rootViewController: pdfController), animated: true)
  7. You’ll now have the following in your ViewController.swift file:

    import UIKit
    import PSPDFKit
    import PSPDFKitUI
    
    class ViewController: UIViewController {
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
            // Update to use your document name.
            let fileURL = Bundle.main.url(forResource: "Form", withExtension: "pdf")!
            let document = Document(url: fileURL)
    
            // Create the ink annotation.
            let annotation = InkAnnotation()
            annotation.color = UIColor(red: 0.7, green: 0.3, blue: 0.8, alpha: 1)
            annotation.lineWidth = 5
    
            // This example code is just hardcoding a stroke with three points.
            let lines = [[
                DrawingPoint(location: CGPoint(x: 450, y: 130), intensity: 0.5),
                DrawingPoint(location: CGPoint(x: 550, y: 30), intensity: 0.5),
                DrawingPoint(location: CGPoint(x: 650, y: 100), intensity: 0.5)
            ]]
            annotation.lines = lines
    
            // Mark this ink annotation as a signature.
            annotation.isSignature = true
    
            // Add the annotation.
            document.add(annotations: [annotation])
    
            let pdfController = PDFViewController(document: document)
            // Present the PDF view controller within a `UINavigationController` to show built-in toolbar buttons.
            present(UINavigationController(rootViewController: pdfController), animated: true)
        }
    }
Information

For a working example, replace the contents of your ViewController.swift with the code above.

  1. Run your application:

Similarly, to add an image signature, you’ll have the following in your ViewController.swift file:

import UIKit
import PSPDFKit
import PSPDFKitUI

class ViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // Update to use your document name.
        let fileURL = Bundle.main.url(forResource: "Form", withExtension: "pdf")!
        let document = Document(url: fileURL)

        let signatureImage = UIImage(named: "signatureImage.png")

        // Create the stamp annotation.
        let annotation = StampAnnotation(image: signatureImage)
        annotation.boundingBox = CGRect(x: 450, y: 50, width: 240, height: 100)

        // Mark this stamp annotation as a signature.
        annotation.isSignature = true

        // Add the annotation.
        document.add(annotations: [annotation])

        let pdfController = PDFViewController(document: document)
        // Present the PDF view controller within a `UINavigationController` to show built-in toolbar buttons.
        present(UINavigationController(rootViewController: pdfController), animated: true)
    }
}

For more information on electronic signatures, refer to our guide on how to add an electronic signature.

Adding Digital Signatures Programmatically on iOS

Digital signatures are signed with a certificate. For demonstration purposes, this next section uses a self-signed certificate.

Information

Never use self-signed certificates in a production application. Always obtain them from a trust service provider (TSP) to ensure the verification of the signer’s identity.

Information

If you want to use the Digital Signatures component, make sure it’s included in your license. Please contact Sales for more information.

Generating a Self-Signed Certificate

To generate a self-signed certificate with OpenSSL, follow the steps outlined below.

  1. Generate a private key file named test-ca.key:

    openssl genrsa -out test-ca.key 2048
  2. Create and sign a certificate file named test-ca.cert for a CA with the common name (CN) My Test CA v1:

    openssl req \
    -x509 -new -nodes -key test-ca.key \
    -subj "/CN=My Test CA v1" \
    -days 3650 -reqexts v3_req -extensions v3_ca \
    -out test-ca.cert
  3. Create a signing certificate. Generate a private key file named test-signer.key and a certificate signing request file named test-signer.csr with the CN My Testing Document Signer:

    openssl req \
    -utf8 -nameopt oneline,utf8 -new -newkey rsa:2048 -nodes \
    -subj "/CN=My Testing Document Signer" \
    -keyout test-signer.key -out test-signer.csr
  4. Create a signing certificate file from the request and name it test-signer.cert:

    openssl x509 \
    -days 365 \
    -CA test-ca.cert -CAkey test-ca.key -CAcreateserial \
    -in test-signer.csr -req \
    -out test-signer.cert
  5. Generate a personal information exchange (.p12) file with:

    openssl pkcs12 -export -legacy -in test-signer.cert -inkey test-signer.key -out test-signer.p12 -password pass:test
Information

This will create a .p12 file with test as its password.

Adding Digital Signatures to Your Document

  1. Add the test-signer.p12 and test-ca.cert files to your application by dragging them into your Xcode project.

  2. Get the document you want to sign:

    let fileURL = Bundle.main.url(forResource: "Form", withExtension: "pdf")!
    let document = Document(url: fileURL)
  3. Create a PKCS12 instance and get its certificates and private key. The signing process produces the signature by encrypting the message digest from the PDF file with a private key. The certificate, along with its public key, is added to the signature and saved in the PDF file:

    let p12URL = Bundle.main.url(forResource: "test-signer", withExtension: "p12")!
    guard let p12data = try? Data(contentsOf: p12URL) else {
        return print("Error reading p12 data from \(String(describing: p12URL))")
    }
    let p12 = PKCS12(data: p12data)
    let (certificates, privateKey) = try! p12.unlockCertificateChain(withPassword: "test")
Information

Replace test with your actual password.

  1. Add the CA certificate to the trust store for the signature validation process:

    let caCertificates = try! X509.certificates(fromPKCS7Data: Data(contentsOf: Bundle.main.url(forResource: "test-ca", withExtension: "cert")!))
    for certificate in caCertificates {
        SDK.shared.signatureManager.addTrustedCertificate(certificate)
    }
  2. Get the signature form element:

    let signatureFormElement = document.annotations(at: 0, type: SignatureFormElement.self).first!
  3. Now, sign the document:

    let fileName = "\(UUID().uuidString).pdf"
    let url = URL(fileURLWithPath: NSTemporaryDirectory().appending(fileName))
    Task {
        do {
            let configuration = SigningConfiguration(dataSigner: privateKey, certificates: certificates)
            try await document.sign(formElement: signatureFormElement, configuration: configuration, outputDataProvider: FileDataProvider(fileURL: url))
            let signedDocument = Document(url: url)
        } catch {
            print(error)
        }
    }
  4. Finally, present the PDF view controller showing the signed document:

    let pdfController = PDFViewController(document: signedDocument)
    // Present the PDF view controller within a `UINavigationController` to show built-in toolbar buttons.
    present(UINavigationController(rootViewController: pdfController), animated: true)
  5. Putting it all together will result in the following in your ViewController.swift file:

    import UIKit
    import PSPDFKit
    import PSPDFKitUI
    
    class ViewController: UIViewController {
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
            // Update to use your document name.
            let fileURL = Bundle.main.url(forResource: "Form", withExtension: "pdf")!
            let document = Document(url: fileURL)
    
            let p12URL = Bundle.main.url(forResource: "test-signer", withExtension: "p12")!
            guard let p12data = try? Data(contentsOf: p12URL) else {
                return print("Error reading p12 data from \(String(describing: p12URL))")
            }
            let p12 = PKCS12(data: p12data)
            let (certificates, privateKey) = try! p12.unlockCertificateChain(withPassword: "test")
    
            // Add CA certificates to the trust store for the signature validation process.
            let caCertificates = try! X509.certificates(fromPKCS7Data: Data(contentsOf: Bundle.main.url(forResource: "test-ca", withExtension: "cert")!))
            for certificate in caCertificates {
                SDK.shared.signatureManager.addTrustedCertificate(certificate)
            }
    
            let signatureFormElement = document.annotations(at: 0, type: SignatureFormElement.self).first!
            let fileName = "\(UUID().uuidString).pdf"
            let url = URL(fileURLWithPath: NSTemporaryDirectory().appending(fileName))
    
            Task {
                do {
                    let configuration = SigningConfiguration(dataSigner: privateKey, certificates: certificates)
                    try await document.sign(formElement: signatureFormElement, configuration: configuration, outputDataProvider: FileDataProvider(fileURL: url))
                    let signedDocument = Document(url: url)
                    let pdfController = PDFViewController(document: signedDocument)
                    // Present the PDF view controller within a `UINavigationController` to show built-in toolbar buttons.
                    present(UINavigationController(rootViewController: pdfController), animated: true)
                } catch {
                    print(error)
                }
            }
        }
    }
Information

For a working example, replace the contents of ViewController.swift with the code above.

  1. Run your application.

For more information on digital signatures, refer to our digital signatures guide.

FAQ

How Do I Make a PDF Signable on My iPhone?

Any PDF can be signed directly on your iPhone using electronic or digital signatures. This means you can open a PDF document and add your signature by drawing it on the screen or using a digital certificate, ensuring the document is authenticated and legally binding.

How Do I Add a Signature to a PDF Application?

You can add signature functionality to your app, like support for electronic signatures or digital signatures, using SDKs like PSPDFKit.

How Do I Add a Signature to a Document on My iPhone?

Open the PDF in an app using PSPDFKit, apply a digital certificate or select the signature tool and draw or type your signature, and save the signed document.

Conclusion

In this post, you learned how to add electronic and digital signatures to a document using the PSPDFKit library on iOS. If you hit any snags, don’t hesitate to reach out to our Support team for help.

At PSPDFKit, we offer a commercial, feature-rich, and completely customizable iOS PDF library that’s easy to integrate and comes with well-documented APIs to handle advanced use cases. For more information, visit our overview page.

Author
Stefan Kieleithner iOS Engineer

Stefan began his journey into iOS development in 2013 and has been passionate about it ever since. In his free time, he enjoys playing board and video games, spending time with his cats, and gardening on his balcony.

Free 60-Day Trial Try PSPDFKit in your app today.
Free Trial

Related Articles

Explore more
DEVELOPMENT  |  iOS • Android • Room • Kotlin Multiplatform • Tips

Seamless Room Database Integration for Kotlin Multiplatform Projects

DEVELOPMENT  |  iOS • Insights • Xcode

NSCopying in a Swift World

DEVELOPMENT  |  iOS • Swift • Insights

Generating API Documentation for Multiple Targets with DocC