What exactly gets signed.
CMS, signed attributes and the byte range of a PDF: the anatomy of a signature inside a document.
A digital signature does not sign a document. It signs an exact sequence of bytes. Between those bytes and what a person sees on screen lie formats, structures and programs that interpret them, and that gap is where most practical attacks on document signatures over the past two decades took place. The cryptography held; what failed was the answer to a deceptively simple question: what, exactly, was signed?
CMS: the signature envelope
Almost all document signatures, in PDF and in many other formats, are packaged in a structure called CMS (Cryptographic Message Syntax), the successor to RSA Laboratories’ PKCS #7 standard and specified today in RFC 5652. Its signing variant is called SignedData, and its structure is worth looking at from the inside.
The crux lies in the signed attributes. When they are present, and in practice they always are, the signature is not computed over the document’s hash but over a small set of DER encoded attributes, one of which, messageDigest, holds that hash. It is a two level digest: the document is bound to the attribute, and the attribute to the signature. This makes it possible to sign, alongside the content, data about the signature itself.
- contentType prevents a signature over one type of content from being reinterpreted as a signature over another.
- signingCertificateV2, defined in RFC 5035, contains the hash of the signer’s certificate. Without it, someone could replace the attached certificate with another one carrying the same public key but a different holder or policy, and the signature would still verify. Advanced signature formats require it.
- signingTime is the time claimed by the signer’s machine. It is signed, but it only proves what the signer said, not when it happened. Proof of time comes from a third party timestamp, in the unsigned attributes.
The signature inside a PDF
A signed PDF carries the CMS structure inside the file itself. That raises a circular problem: the signature must cover the file, but the file contains the signature. The ISO 32000 standard solves it by leaving a gap. The signature dictionary reserves a fixed size slot, the /Contents entry, which is filled with the CMS structure in hexadecimal, and declares in /ByteRange which bytes of the file were hashed: everything except the gap.
The signature’s filter indicates the format of its contents. In European advanced signatures, the PAdES profile uses ETSI.CAdES.detached: a detached CMS signature, with the attributes required by the advanced signature standards, over the bytes in the range.
Incremental updates: the document that keeps changing
PDF allows a file to be modified without rewriting it: changes are appended at the end, as a new revision that redefines the altered objects. This is what lets several people sign the same document, one after another, without invalidating earlier signatures: each signature covers its own revision and all previous ones, and whatever comes afterward falls outside its range.
That same flexibility is the attack surface. If a later revision can change what is displayed, a document can show new content while the earlier signature still verifies, because the bytes it covers have not changed. The standards provide safeguards. A certification signature can declare, through DocMDP permissions, which changes are allowed afterward: none, filling in forms only, or annotations as well. And the validator must compare revisions and flag any disallowed change.
| Attack | Idea |
|---|---|
| Universal forgery | Tamper with the signature dictionary (null values, nonsensical ranges) so that the viewer shows the signature as valid without verifying anything. |
| Incremental saving | Append a revision that replaces the visible content, and disguise it so the viewer raises no warning. |
| Signature wrapping | Relocate the signed bytes within the file and redefine the range, so that what is verified and what is displayed are different things. |
| Shadow attacks | Prepare the document before it is signed with hidden content, which an update allowed by the permissions later makes visible. |
In 2019, a team from Ruhr University Bochum tested the first three techniques against 22 desktop viewers and 7 online validation services: 21 viewers and 5 services were vulnerable to at least one. In 2021 the same group presented shadow attacks, which break no rule of the format but abuse the changes it permits. Vendors fixed most of the cases, but the lesson endures: the security of a signature on a document depends as much on the validator as on the algorithm.
XML and other formats
XML signatures, the foundation of the XAdES profile, face the same problem in a different guise. Because the same XML document can be written in many equivalent ways, the signature is computed after canonicalization, and it covers references to parts of the document selected through transforms. If the verifier checks the signature over one element and the application processes another element with the same name elsewhere, the result is a signature wrapping attack, a family that plagued single sign on systems for years. The defensive principle is the same: the application must use exactly what the verifier verified.
In CMS, the signature covers signed attributes that contain the hash of the content and that of the signer’s certificate; the claimed time is not proof of time. In a PDF, the signature covers a byte range with a gap for itself, and later revisions fall outside it. Most real world attacks exploited the distance between what was verified and what was displayed, and they are countered by strict validators that report exactly what was signed.
Sources
- IETF, RFC 5652, Cryptographic Message Syntax (CMS), 2009
- IETF, RFC 5035, Enhanced Security Services Update: Adding CertID Algorithm Agility, 2007
- ISO 32000 2, Portable Document Format 2.0
- ETSI EN 319 142, PDF Advanced Electronic Signatures (PAdES)
- Mladenov, Mainka, Meyer zu Selhausen, Grothe and Schwenk, “1 Trillion Dollar Refund: How To Spoof PDF Signatures”, ACM CCS 2019
- Mainka, Mladenov and Rohlmann, “Shadow Attacks: Hiding and Replacing Content in Signed PDFs”, NDSS 2021