How to check a signed PDF yourself: PAdES seals, timestamps and hashes
Someone sends you a contract "signed electronically". It is a PDF. How do you know nobody edited it after it was signed: changed the price, swapped a page, removed a clause? A screenshot of a signature proves nothing. W
Someone sends you a contract "signed electronically". It is a PDF. How do you know nobody edited it after it was signed: changed the price, swapped a page, removed a clause?
A screenshot of a signature proves nothing. What proves something is a digital seal inside the file. This post explains what is in a properly signed PDF and how to check each part yourself, with free tools.
What a signed PDF contains
A PDF signed the way the EU standard (PAdES, ETSI EN 319 142) expects has four pieces of evidence:
-
The seal (a CMS signature over the file). When the PDF is sealed, the signing software computes a hash of every byte of the file except the space reserved for the signature itself (the
/ByteRange), and signs that hash with a private key. Change one byte afterwards and the hash no longer matches. - A trusted timestamp (RFC 3161). An independent timestamp authority signs "this hash existed at this time". That proves when the file was sealed, and keeps the proof valid even after the sealing certificate expires.
- Who signed and how. Usually a certificate-of-completion page inside the sealed file: names, e-mail addresses, times, IP addresses, how each person was identified. Because it is inside the sealed bytes, it cannot be swapped.
- The file's fingerprint (SHA-256). A short code that identifies these exact bytes. Two files with the same SHA-256 are the same file.
Check it on the command line
Fingerprint. Compare it with the one the sender has on record:
shasum -a 256 contract-signed.pdf # macOS
sha256sum contract-signed.pdf # Linux
Seal and timestamp with poppler's pdfsig (comes with poppler-utils / brew install poppler):
pdfsig contract-signed.pdf
Look for Signature Validation: Signature is Valid. and, for the document as a whole, that the signature covers the whole file (Total document signed). If someone edited the file after sealing, you get Signature is Invalid or a note that the signature does not cover all of the document.
The same in Python with pyHanko:
pip install pyhanko-cli
pyhanko sign validate --pretty-print contract-signed.pdf
pyHanko reports the integrity of the file, the signing time, the timestamp token and whether the certificate chains to a root it trusts.
"Validity unknown" is not "changed"
PDF readers often show a yellow "signature validity is unknown". That message is about trust in the certificate issuer, not about the file: the reader checks whether the certificate comes from a list it trusts (for Adobe, the AATL or the EU Trusted Lists). A seal from a certificate outside that list can still prove perfectly well that the file was not modified. A red "document has been altered" is the one that matters.
So read the result in two parts:
| Question | Where to look |
|---|---|
| Was the file changed after sealing? | Integrity / "signature is valid" / covers the whole document |
| When was it sealed? | The timestamp token, not the computer's clock |
| Who sealed it, and do I trust them? | The certificate and its chain |
| Who signed and how were they identified? | The certificate-of-completion page inside the file |
Check it with one HTTP request
If the PDF was signed with PenlyDoc, there is a public endpoint that does all of the above without an account:
curl -F document=@contract-signed.pdf https://penlydoc.com/api/verify
The answer contains the SHA-256 of the file, whether every signature in it is cryptographically valid, whether it was sealed by the service, and the status of the matching document. The file is checked in memory and not stored. There is also a page where you can drop the file: penlydoc.com/verify.
A short checklist before you rely on a signed PDF
- The seal is valid and covers the whole document.
- There is a timestamp from an independent authority.
- The certificate-of-completion page lists the people you expect, with sensible times.
- The SHA-256 matches what the sender recorded.
- For documents where the law asks for a qualified electronic signature (some property, family or consumer-credit matters, depending on the country), a simple electronic signature is not enough, however good the seal is.
I build PenlyDoc, an e-signature service from the EU where every signed PDF can be checked this way. Questions about PAdES or timestamps are welcome in the comments.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.