This article explores how digital signatures in PDF work and how to digitally sign a PDF document when the signature is created in a remote app, device, or service. In the end, you'll find references that will help you implement external PDF digital signatures.
PDF Signature Standards
There are two main types of digital signatures in PDFs:
- PKCS7 (also known as
adbe.pkcs7.detached
) - ETSI.CAdES.detached, compliant with eIDAS specifications
The key difference is that ETSI.CAdES.detached is stricter—it ensures the signature covers the entire PDF except for the immediate signature bytes. PKCS#7, on the other hand, is more flexible, allowing more post-signature changes without invalidation.
Multiple Signatures in One PDF
PDFs support multiple digital signatures, added serially. Once the first digital signature is in place, any further edits to the PDF are stored as incremental updates, creating a new revision of the file with each new signature appended to the end.
Modifying PDF After Signing
Generally, you can’t modify PDF contents or appearance after the first signature. However, visual signatures (like stamps or name overlays) can still be added to subsequent digital signatures. While visual signatures help reassure users, the actual signature validity remains in the invisible cryptography.
How Digital Signatures Are Added
There are two main steps to signing a PDF:
- Create a signature dictionary and reserve a ByteRange with all signature bytes initially set to zero.
- Generate the signature value externally and inject it into the PDF by writing the hex string into the reserved ByteRange.
Here’s an example of how a signature might look in a PDF when viewed in a text editor:
<</Type /Sig
/Filter /Adobe.PPKLite
/SubFilter /ETSI.CAdES.detached
/Name (My Name)
/ContactInfo (info@eideasy.com)
/Location (At my desk)
/Reason (Signed in test app)
/M (D:20210105184421+00'00')
/Contents <30822C....CFE000....000000>
/ByteRange [0 3991 41881 794]
>>
The ByteRange means:
- Take bytes 0–3991
- Skip the signature section
- Then take bytes 41881–(41881+794)
During signature verification, the skipped section <30822C....CFE000....000000>
is removed, and the hash is calculated on the remaining parts to verify the signature.
Why ByteRange Must Be Large Enough
Since you don’t know the signature’s exact length in advance (due to variable signature types like RSA or Elliptic Curve, the latter also depending on specific curves like secp384r1
or prime256v1
), you have to reserve a buffer in the ByteRange. The presence of timestamps further increases signature size, which is why the reserved section ends with a block of zeros.
Implementation Requires PDF Libraries
Despite sounding simple, creating valid external PDF signatures requires complex PDF manipulation, often with specialized libraries. eID Easy has built an open source app and Docker microservice that offers a REST API for integration in PHP, Java, NodeJS, Go, Python, and other languages.
Resources to Get Started
- Source code: https://github.com/eideasy/eideasy-external-pades-digital-signatures
- Docker image: https://hub.docker.com/repository/docker/eideasy/pades-external-digital-signatures
- Live demo/test app: https://detached-pdf.eideasy.com
→ If you need help with qualified digital signatures using eID cards, Mobile-ID, Smart-ID, ZealiD, or similar tools, explore the eID Easy API set here:
https://documenter.getpostman.com/view/3869493/Szf6WoG1
→ If you're looking to ensure that your PDF signatures remain valid long into the future, even after certificates expire or responders go offline, check out our guide on implementing PAdES LTV (Long-Term Validation).
