Inspect and Sign PDF Documents Safely with pdfsig
A signature on a PDF looks reassuring right up until somebody actually checks it, and pdfsig is the tool that does the checking properly. You will finish with a repeatable way to inspect a PDF's digital signatures and, once you have a suitable certificate, write a newly signed copy without touching the source document. The examples use pdfsig from Poppler 24.02.0, installed here as poppler-utils 24.02.0-1ubuntu9.9.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes for inspection. Signing takes longer if you need to track down an NSS certificate or a hardware token. You need a shell, a readable PDF and the poppler-utils package. Verification can make online OCSP checks, so use a network and trust store you actually trust for this document. The signing steps need an already configured certificate and private key: this guide does not create or import credentials.
1. Confirm the installed command
Start with checks that touch nothing:
$ command -v pdfsig
/usr/bin/pdfsig
$ pdfsig -v
pdfsig version 24.02.0
Copyright 2005-2024 The Poppler Developers - http://poppler.freedesktop.org
The option spelling and output belong to the version you have installed. If yours differs, read its local manual before copying a signing command into a script.
Checkpoint
Confirm the input is actually the document you mean to inspect, not a stale copy sitting in Downloads.
$ test -r /path/to/document.pdf && echo 'input is readable'
input is readable
$ file /path/to/document.pdf
/path/to/document.pdf: PDF document, version 1.7
Use a full path rather than trusting the current directory, especially for downloaded or shared files. Do not run sudo pdfsig as a routine step: root access does not make a certificate trustworthy, and it can expose credentials through a different home directory.
2. Inspect signatures without changing the PDF
Pass the PDF as the only positional argument:
$ pdfsig /path/to/document.pdf
The exact output depends on the file, but for each signature you will want to check:
- Signer identity and signing time. Who the certificate claims to be, and when it was applied.
- Digest and signature type. The hash algorithm and format used to seal it.
- Signed byte ranges. Whether the whole document is covered, or only part of it.
Treat the reported name and validation result as claims to investigate, not proof that the person or organisation is who you expect.
A PDF with no signatures may produce no signature records at all. A damaged, unreadable or unsupported file instead produces an error and a non-zero exit status. Capture the status immediately if a script needs to tell success apart from a message printed to the terminal:
$ pdfsig /path/to/document.pdf
$ status=$?
$ printf 'pdfsig exit status: %s\n' "$status"
pdfsig exit status: 0
Status 0 says pdfsig completed its operation. It does not conjure a trusted certificate, a known signer or a fully signed document where none exists.
3. Understand the certificate checks
By default, pdfsig pulls trusted certificates from its NSS search locations: an explicitly chosen directory, the default Firefox profile, or /etc/pki/nssdb. It also uses OCSP to check revocation unless you turn that off, which means inspection can quietly depend on network access and whatever certificate configuration happens to be sitting on the machine.
If you need a particular NSS database, point to it explicitly:
$ pdfsig -nssdir sql:/path/to/nssdb /path/to/document.pdf
The prefix is passed straight to the NSS database selection mechanism. Use the format your certutil setup already uses; do not guess a database directory from a certificate filename.
For an offline diagnostic, suppress OCSP while keeping local CRL checks:
$ pdfsig -no-ocsp /path/to/document.pdf
Warning
This is not a complete trust decision. Record the option in an audit trail and never use it to paper over a network or revocation failure. Similarly, -nocert disables certificate validation entirely. That is useful for isolating a parsing or signature problem, but it must never be reported as a trusted verification.
Some certificate chains are missing an intermediate certificate. The installed command can use Authority Information Access to fetch missing certificates:
$ pdfsig -aia /path/to/document.pdf
Fetching certificate material changes the external requests made during verification. Use it only where that network behaviour is acceptable, and prefer a controlled trust store for checks you plan to repeat.
4. Export the embedded signature material
Use -dump when you need the raw CMS or PKCS#7 bundle for separate analysis:
$ mkdir -p /tmp/pdfsig-dump
$ cd /tmp/pdfsig-dump
$ pdfsig -dump /path/to/document.pdf
$ find . -maxdepth 1 -type f -printf '%f\n'
The files land in the current directory and are typically unpadded or zero-padded CMS/PKCS#7 data. This writes files, but it leaves the PDF itself untouched. Keep the temporary directory access-controlled if the document contains sensitive signatures, and remove the dump once your analysis is finished. Do not mistake the exported bundle for a detached signature that can be applied to an arbitrary PDF.
5. List credentials before attempting a signature
Signing is security-sensitive: it creates a document other people may rely on, and the private-key password or token interaction needs to stay under your control. First list the available certificate nicknames in the intended NSS database:
$ pdfsig -nssdir sql:/path/to/nssdb -list-nicks
The output is host-specific. Copy the exact nickname, including spaces, and quote it in the signing command. You can also see which cryptographic backends this build has available:
$ pdfsig -list-backends
pdfsig backends:
NSS (active)
Security warning
Do not paste a private-key password into shell history, process listings or a support ticket. The manual exposes -nss-pwd and -kpw for exactly this, but a password supplied as an argument can be visible to other local users while the process runs. Prefer the least exposed method your environment supports, and clear any temporary shell history entry according to policy.
6. Add a signature to a new output file
Choose a fresh destination before you change anything. The command below creates signed-output.pdf from the source and selects an existing certificate:
$ pdfsig /path/to/input.pdf /path/to/signed-output.pdf \
-add-signature \
-nssdir sql:/path/to/nssdb \
-nick 'Example signing certificate' \
-reason 'Approved for release'
$ test -s /path/to/signed-output.pdf && echo 'signed output exists'
signed output exists
The default digest is SHA256. Only reach for -digest when a documented compatibility requirement calls for another algorithm. -etsi changes the signature type to ETSI.CAdES.detached; it is not a general-purpose quality switch.
This can prompt for access to the signing key, depending on the backend and key protection. It can also fail after creating an incomplete destination, so never point it at a valuable existing file. If it fails, remove only the failed output after checking its path, then retry with a fresh name. The input is your recovery copy and stays untouched throughout.
7. Sign an existing unsigned signature field
A form may already contain an unsigned signature field. In that case, use -sign with its field name or zero-based position:
$ pdfsig /path/to/input-with-field.pdf /path/to/field-signed.pdf \
-sign 0 \
-nssdir sql:/path/to/nssdb \
-nick 'Example signing certificate' \
-reason 'Approved for release'
The field must exist and be unsigned. Position 0 means the first signature field as pdfsig understands it, not a certificate index. If the document has multiple fields, prefer a field name when the producer gives you one, so a reordering cannot select the wrong target.
After either signing workflow, inspect the result as a separate step:
$ pdfsig /path/to/signed-output.pdf
$ printf 'verification command status: %s\n' "$?"
verification command status: 0
Check that the expected signer, reason and signed ranges appear. Keep the original and signed files apart until a recipient has confirmed the result opens and validates in their own software.
Done means
- Version confirmed. You checked the installed Poppler version and inspected the intended PDF.
- Trust chain understood. You know whether the verification used OCSP, local revocation data and which NSS database.
- Shortcuts flagged. You treated
-nocertand-no-ocspas diagnostic exceptions, never as proof of trust. - Certificate chosen carefully. You listed and selected the intended certificate without exposing a private-key password unnecessarily.
- Signed to a new path. You wrote the signed copy elsewhere, leaving the source PDF available for recovery.
- Result re-checked. You ran pdfsig on the output and confirmed the signer and signed ranges.