Sign a PDF with a PAdES baseline signature (moved)
This recipe moved
Section titled “This recipe moved”The signing walkthrough that used to be on this page is now superseded. Use the canonical recipe instead:
Why this page changed (erratum)
Section titled “Why this page changed (erratum)”An earlier version of this page said the high-level Document::setSignature()
→ save() path was not wired and threw NotImplementedException.
That is no longer true. The high-level path now writes a real signature.
Document::setSignature($cert, SignatureLevel::PAdES_B_B)->save() (and the
equivalent output() / getPdfData()) writes a /Sig field with a /ByteRange
and a Distinguished Encoding Rules (DER)-encoded Cryptographic Message Syntax
(CMS) SignedData object in the signature dictionary Contents entry. That is
the structure ISO 32000-2 §12.8 specifies for the ETSI.CAdES.detached
SubFilter. The result is CMS-verifiable: a standard CMS/PKCS#7
(Public-Key Cryptography Standards #7) verifier parses and checks it.
- B-B — the Core level — is produced directly through this path.
- B-T adds one RFC 3161 signature-time-stamp when you pass a
TsaClienton the same call. - B-LT / B-LTA are reachable through the same high-level path
(
setSignature($cert, SignatureLevel::PAdES_B_LTA, $tsaClient)->save()) when the Pro and Enterprise packages are installed; without them, the call fails closed instead of writing a partial long-term revision. Encrypted documents also fail closed for B-LT/B-LTA.
The lower-level NextPDF\Security\Signature\DigitalSigner path is still
supported. The canonical recipe below walks through it end to end. The
high-level path is a thin convenience over the same signing engine. The
integration suite exercises both paths and produces a real, parseable CMS object.
U-1 caveat (scope of the claim). “CMS-verifiable” means the produced object is a well-formed CMS
SignedDataper RFC 5652 and ISO 32000-2 §12.8. It is not an assertion of ETSI EN 319 142-1 baseline-profile conformance or legal validity. The baseline-levels part of that standard is not in the verification corpus; the B-Tsignature-time-stamprequirement was checked against ETSI EN 319 122-1 §5.3 with RFC 3161, RFC 5652, RFC 5816, and ISO 32000-2 §12.8. B-LT/B-LTA produce the long-term-validation structure (a DSS dictionary plus a DocTimeStamp revision); they are not advertised as profile-conformance-tested. An independent validator determines conformance and legal validity.
What carried over unchanged
Section titled “What carried over unchanged”The structural facts the old page asserted about the on-disk artifact remain correct. The replacement recipe restates them with evidence:
- The signature value is stored in the signature dictionary
Contentsentry (ISO 32000-2 §12.8.1). - The digest is computed over the
ByteRangeand excludes the signature value itself (ISO 32000-2 §12.8.1).
This page does not assert that any resulting signature is legally valid. Legal validity depends on the certificate, its trust anchor, and the verifier’s policy. All of those live outside this library.