PDF Encryption Revision 6: How AES-256 Protection Actually Works
Put a password on a PDF and most people assume the job is done - especially if the software claims "AES-256 encryption", a phrase that sounds about as secure as it gets. But that label can be misleading: two PDFs can both claim AES-256 protection while one is dramatically easier to crack open than the other. The difference comes down to a lesser-known setting buried in the file, and understanding it is the easiest way to make sure a "protected" PDF is actually protected.
Every encrypted PDF carries a small integer, /R, buried in its /Encrypt dictionary, that tells a reader which version of the Standard Security Handler was used to lock the file. Revision 6 is the latest revision of the ISO-standardized Standard Security Handler, pairing AES-256 document encryption with a substantially strengthened password-verification algorithm. It is what a modern PDF writer produces by default when you ask for "AES-256" protection today.
Revision 6 is worth a dedicated look for a reason that isn't obvious from the outside: it isn't really about AES-256 at all. The cipher was already AES-256 one generation earlier, in Revision 5, and that revision turned out to have a significantly weaker password-verification design than intended - not because AES was weak, but because the password hashing algorithm performed only a single SHA-256 computation, making offline password guessing far too efficient. Revision 6 is best understood as the fix for that mistake.
If your workflow relies on password-protected or DRM-protected PDFs, understanding this distinction matters - because it determines whether the protection you're relying on is actually resistant to brute-force attack.
History: PDF encryption from 40-bit RC4 to a broken AES-256 to a fixed one
PDF encryption has gone through several distinct generations, each tied to a specific /R value in the /Encrypt dictionary:
- Revision 2 (PDF 1.1, 1994) - RC4 with a 40-bit key. Trivially breakable today; effectively no protection.
- Revision 3 (PDF 1.4, 2001) - RC4 extended up to 128-bit keys, with a 50-round MD5 hardening loop added to the key derivation. Still RC4, which has since been shown to have exploitable statistical biases (and was deprecated in TLS in 2015).
- Revision 4 (PDF 1.5/1.6, ~2005) - Introduced the crypt filter architecture (
/CF,/StmF,/StrF), which decoupled "how do we derive a key" from "what cipher do we actually use." This let Revision 4 files use either RC4-128 or, via theAESV2crypt filter method, AES-128 - while keeping the same password-verification algorithm as Revision 3 underneath. - Revision 5 (PDF 1.7 Extension Level 3, 2008) - The first appearance of AES-256. Adobe published this as a proprietary extension to ISO 32000-1 rather than through the standards body, and it shipped in Acrobat 9. This is where the story gets interesting.
- Revision 6 (formalized in ISO 32000-2:2020, 2020) - The corrected version of R5's password hashing, adopted into the actual ISO standard.
The gap between R5 and R6 is the whole point of this article. When Adobe introduced 256-bit AES in Extension Level 3, the password-check hash consisted of a single salted SHA-256 computation. While the use of random salts prevented precomputed rainbow-table attacks, the algorithm had essentially no work factor, making offline password guessing extremely efficient. That routine actually made password guessing faster than it had been against the older 128-bit scheme - the jump to a "stronger" cipher had, perversely, made brute-forcing easier, because a single SHA-256 call is extremely cheap to compute at scale (GPUs can do billions of them per second), whereas the older R3/R4 scheme at least forced 50 rounds of MD5. Security researchers quickly showed that the Revision 5 password hashing algorithm was highly efficient to brute-force using GPUs, making weak passwords substantially easier to recover than expected.
Adobe's fix arrived as Extension Level 8 in 2011, replacing the single hash with an iterated, self-adjusting one, revising the password handling to address the weakness that had been discovered in Extension Level 3. That corrected algorithm is what eventually became Revision 6 when the ISO committee folded it into the official standard. PDF 2.0 (ISO 32000-2) was published by the International Organization for Standardization in July 2017, bringing this fixed password handling into the formal standard, and the current published version, ISO 32000-2:2020, is where Revision 6 has its formal, non-Adobe-proprietary specification.
One practical consequence of this history: "AES-256" alone tells you almost nothing about a PDF's real security. A file can be R5 (Acrobat 9-compatible, weakly hashed) or R6 (PDF 2.0, properly hashed) and both will claim 256-bit AES. Tools that don't distinguish the two will happily "verify" that a file uses AES-256 while it remains crackable.
What changed in PDF encryption between Revision 5 and Revision 6
Structurally, R5 and R6 files look almost identical. Both store, in the /Encrypt dictionary:
| Key | Size | Purpose |
|---|---|---|
/U | 48 bytes | User password validation hash (32B) + validation salt (8B) + key salt (8B) |
/O | 48 bytes | Owner password validation hash (32B) + validation salt (8B) + key salt (8B) |
/UE | 32 bytes | User-password-encrypted copy of the file encryption key |
/OE | 32 bytes | Owner-password-encrypted copy of the file encryption key |
/Perms | 16 bytes | Encrypted copy of the permission flags, used to detect tampering |
The primary structural difference between R5 and R6 is the password hashing algorithm used to produce the values stored in /U, /O, /UE, and /OE. Most of Revision 6's security improvement comes from replacing Revision 5's inexpensive password hashing routine with a substantially more expensive one.
The R5 hash (Algorithm 2.B, deprecated form)
In R5, the hash used everywhere is simply:
hash = SHA-256(password || salt || [udata])udata is the 48-byte /U string, but only when computing the owner password's hash - it's empty for the user password. That's it: one call to SHA-256, run once. It's fast to compute for a legitimate user opening the file, but exactly as fast for an attacker trying millions of candidate passwords per second on a GPU. There's no work factor, no iteration count, nothing tunable - which is exactly what made the password-check routine boil down to a single, cheap hash that's actually faster to brute-force than the older 128-bit scheme's 50-round MD5.
The R6 hash (Algorithm 2.B, hardened form)
R6 keeps that same first step, but then runs a data-dependent hardening loop on top of it - a construction that resembles a lightweight, PDF-specific analogue of password-hashing schemes like bcrypt or PBKDF2. In pseudocode:
K = SHA-256(password || salt || udata) // same starting point as R5
round = 0
repeat:
// Build buffer: concatenate (password + K + udata) exactly 64 times
block = password || K || udata
K1 = repeat(block, 64)
// Key and IV are BOTH the first 16 bytes of K
E = AES-128-CBC-NoPadding(key = K[0:16], iv = K[0:16], data = K1)
// Data-dependent hash choice based on sum of first 16 bytes of E
sum = (sum of first 16 bytes of E) mod 3
if sum == 0:
K = SHA-256(E)
elif sum == 1:
K = SHA-384(E)
else:
K = SHA-512(E)
// Cast the last byte of E to an unsigned integer for the check
E_last = last_byte_of(E) as unsigned integer
round += 1
until round >= 64 AND E_last <= (round - 32)
result = first 32 bytes of KA few things are worth calling out about this construction:
- It's inherently sequential. Each round's output feeds the next round's input, so unlike a single SHA-256 call, you can't meaningfully parallelize a single password guess across GPU cores the way you could with R5 - though many candidate passwords can still be tried in parallel across cores, just each at the (comparatively) higher per-guess cost.
- The round count is variable, not fixed. The loop always runs at least 64 rounds, but the exact termination point depends on the data being hashed (via
last_byte(E) <= round - 32), which means the attacker can't precompute a fixed-cost table - the cost varies slightly per candidate password in a way that's determined only by actually running the algorithm. - It mixes three different hash functions. Dynamically selecting among SHA-256, SHA-384, and SHA-512 based on intermediate ciphertext bytes makes efficient GPU implementations more complicated than a fixed hash function, increasing the implementation cost for password-cracking tools.
- AES-128-CBC appears inside the password hashing, not just for content encryption. This is a detail that trips up naive implementations - the hardening loop uses AES as a keyed pseudorandom mixing step, entirely separate from the AES-256 that later encrypts the actual document content.
Deriving PDF encryption key from the password
The 32-byte hash above is only ever used to validate a candidate password (compare it against the stored digest in /U or /O) and to derive an intermediate key. The real, randomly-generated 32-byte AES-256 file encryption key - the one that actually encrypts every stream and string in the document - is never derived directly from the password at all. Instead:
- Run Algorithm 2.B again, but with the key salt (bytes 40–48 of
/Uor/O) instead of the validation salt, to get a 32-byte intermediate key. - Use that intermediate key as an AES-256 key (CBC mode, no padding, zero IV) to decrypt
/UE(or/OEfor the owner path). The 32-byte result is the actual file encryption key.
This indirection is what makes password changes cheap: changing a user's password only requires re-encrypting the 32-byte /UE value with a newly derived intermediate key - the file encryption key itself, and therefore every already-encrypted stream in the document, never has to change.
Validating PDF password without decrypting anything
Because /U (and /O) store the hash, not the password or key, a reader can confirm a candidate password is correct with nothing more than a hash comparison:
candidateHash = Algorithm2B(candidatePassword, validationSalt, udata)
isCorrect = (candidateHash == storedHash) // first 32 bytes of /U or /OOnly after that check passes does the reader bother deriving the intermediate key and decrypting /UE//OE to recover the real file key.
The owner/permissions password was never a real barrier
It's worth being explicit about something the spec itself implies but doesn't advertise: the "owner password," which is supposed to restrict actions like printing or copying without a corresponding open password, has never gated access to the file encryption key in any revision, including R6. Once a reader successfully authenticates - using either the user password or the owner password - it can recover the file encryption key. Because permission restrictions are enforced by compliant readers rather than cryptographically preventing access to the decrypted content, software that ignores those restrictions can remove them once the file has been legitimately decrypted. Any conformant reader must be able to decrypt and display the document to enforce the permission bits, which means the key material to do so has to be recoverable without the owner password. R6 changes none of this - permission enforcement has always been advisory, honored by well-behaved software rather than cryptographically required.
R6 does add one integrity check in this area: the 16-byte /Perms field. It's an encrypted copy of the permission bits and a fixed marker, produced by encrypting a small fixed-format block with the file encryption key using AES-256 in ECB mode. A conformant reader decrypts it and checks it against the plaintext /P value in the dictionary, mainly to detect a file that's been tampered with inconsistently - not to add any real access control.
This is the same reason browser-based DRM viewers take a different approach entirely: instead of relying on a password an attacker can eventually recover offline, permissions are enforced server-side on every request, and the underlying file is never handed to the reader's device at all.
PDF Password encoding
One more R5→R6-relevant detail: passwords are UTF-8 encoded (with SASLprep normalization where supported by the implementation) and truncated to at most 127 bytes before hashing - a departure from the single-byte PDFDocEncoding used by the older RC4/AES-128 revisions (R2–R4). This is what finally gave PDF passwords real Unicode support, letting non-Latin passwords behave consistently across implementations, as opposed to earlier revisions where non-ASCII passwords were encoding-fragile.
Where PDF encryption stand now
R6 fixed the specific flaw that made password-based protection weaker in practice than the previous AES-128 scheme, and it remains the current baseline for PDF encryption. It is not, however, the end of the story: ISO/TS 32003:2023 subsequently specified an extension adding AES-GCM support on top of the PDF 2.0 encryption framework, aimed at authenticated encryption rather than the CBC-mode cipher R6 uses. Content encrypted this way isn't yet universal, and R6/AES-256-CBC remains what the overwhelming majority of "AES-256 protected" PDFs use in practice as of this writing.
Summary
Revision 6 is less a new cryptographic primitive than a correction to a costly implementation mistake. AES-256 as the actual content cipher has been in place since Revision 5 in 2008; what R6 fixes is the password-hashing step that sat in front of it, replacing a single salted SHA-256 computation with a variable-length, data-dependent loop that mixes AES-128-CBC and three SHA variants across at least 64 rounds. That change restored resistance to offline password guessing that had been reduced in Revision 5 despite its use of a stronger AES-256 content cipher.
Two things are worth carrying forward: first, that the string "AES-256" on its own says nothing about whether a given PDF is R5 (broken hashing) or R6 (fixed) - the /R value in the /Encrypt dictionary is what actually matters; and second, that even in R6, the owner/permissions password remains, as it always has been, an honor-system restriction rather than a cryptographic one - real confidentiality in a PDF has only ever come from the user (open) password.
FAQs
Does PDF-DRM.com use Revision 6 PDF encryption?
Yes. When you password-protect a PDF through PDF-DRM.com, it's encrypted using Revision 6 /R 6. That means the password verification step uses the hardened, iterated hashing algorithm described above.
How do I tell if my PDF is Revision 5 or Revision 6?
Inspect the /Encrypt dictionary and check the /R value. A value of 5 weak hashing; a value of 6 means PDF 2.0-compliant hashing (fixed). Tools like qpdf --show-encryption option, or most PDF inspection utilities, will report this directly rather than just saying "AES-256."
Does a strong password make R5 safe to keep using?
A sufficiently long, high-entropy password is harder to brute-force under any hashing scheme, R5 included. But since R5's hash has no built-in work factor, the effective security margin against a well-resourced attacker is much thinner than the same password would provide under R6. There's no reason to keep producing R5 files when modern tooling defaults to R6.
Can I convert an existing R5 PDF to R6?
Yes. Decrypting the file with the correct password and re-encrypting it with a PDF 2.0-conformant tool (one that writes /R 6) produces a file with the hardened password hashing. The document content itself doesn't need to change - only the password-verification layer is being replaced.
If R6 fixes the password hashing, is a password-protected PDF now fully secure?
R6 closes the specific gap that made R5 weaker than it should have been, but password protection is still only as strong as the password itself, and the owner/permissions password has never been a real access control - any conformant reader can recover the file key once it authenticates. For scenarios that need server-enforced, revocable access control rather than a static password, a browser-based DRM viewer addresses limitations that no amount of password hardening can.
Go Beyond Password Protection
Even correctly hardened R6 passwords can be shared, forwarded, or forgotten. PDF-DRM.com lets you enforce access control, prevent copying and printing, add dynamic watermarks, and revoke access at any time - all without relying on a password recipients can pass along.