Skip to content

Support writing to encrypted documents and AES-256 R6 - #5

Open
nascuite wants to merge 1 commit into
digitorus:mainfrom
nascuite:feature/encryption-for-writers
Open

nascuite wants to merge 1 commit into
digitorus:mainfrom
nascuite:feature/encryption-for-writers

Conversation

@nascuite

Copy link
Copy Markdown

Writers that append objects to an encrypted document, such as a signature in an incremental update, must encrypt their strings and streams with the document’s key. The key and cipher parameters were only available internally, so such writers produced plain-text objects that readers decrypt into garbage.

  • Add Reader.IsEncrypted and Reader.Encrypt, which encrypts string or stream data for a given object (RC4, AES-128 V4, AES-256 V5) without exposing the key, and NewPtr to reference new objects.
  • Do not decrypt the Contents of signature and document timestamp dictionaries, which are never encrypted (ISO 32000-2, 7.6.2). Decrypting them broke verification of signed encrypted documents.
  • Support AES-256 revision 6 (ISO 32000-2, Algorithm 2.B), written by default by qpdf and Acrobat, and by pdfcpu for PDF 2.0 documents.
  • Fix authentication with the owner password for V5: the hash must include the 48 bytes of U.

@nascuite
nascuite marked this pull request as draft September 17, 2026 15:26
Writers that append objects to an encrypted document, such as a signature in an incremental update, must encrypt their strings and streams with the document’s key. The key and cipher parameters were only available internally, so such writers produced plain-text objects that readers decrypt into garbage.

- Add Reader.IsEncrypted and Reader.Encrypt, which encrypts string or stream data for a given object (RC4, AES-128 V4, AES-256 V5) without exposing the key, and NewPtr to reference new objects.
- Do not decrypt the Contents of signature and document timestamp dictionaries, which are never encrypted (ISO 32000-2, 7.6.2). Decrypting them broke verification of signed encrypted documents.
- Support AES-256 revision 6 (ISO 32000-2, Algorithm 2.B), written by default by qpdf and Acrobat, and by pdfcpu for PDF 2.0 documents.
- Fix authentication with the owner password for V5: the hash must include the 48 bytes of U.
- Support authentication with the owner password for V1, V2 and V4 (R2–R4, Algorithm 7). Only the user password was accepted.
- Reject key lengths over 128 bits for V1, V2 and V4 instead of panicking.
@nascuite
nascuite force-pushed the feature/encryption-for-writers branch from 384b99a to d60316b Compare September 17, 2026 19:17
@nascuite
nascuite marked this pull request as ready for review September 17, 2026 19:17
nascuite pushed a commit to nascuite/pdfsign that referenced this pull request Sep 18, 2026
Signing an encrypted document produced an internally inconsistent file: the signature dictionary, field, appearance and updated catalog and page were written in plain text, while readers decrypt every string and stream with the document key. Acrobat and pdfcpu found no signatures, and no error was reported.

* Encrypt all strings and streams of objects written by AddObject and UpdateObject when the document is encrypted. Strings are written as hexadecimal strings and stream Length values are updated. The encryption dictionary, the Contents of signature dictionaries and cross-reference streams are not encrypted, as required by ISO 32000.
* Add OpenWithPassword and OpenFileWithPassword. The password is also used when the document is re-opened for further signatures, verification and signature extraction.
* Add VerifyOptions.Password. The DocMDP incremental update scope check now opens encrypted documents too; previously it was silently skipped.
* Add encrypted test files, created from testfile17.pdf with password “pdfsign”: AES-128 R4 (qpdf), AES-256 R5 (pdfcpu, xref streams), AES-256 R6 (qpdf) and RC4 R3 (qpdf), the last one with its own owner password.

Requires github.com/digitorus/pdf with Reader.Encrypt and R6 support, which
is digitorus/pdf#5. Until that is released the replace in go.mod builds
against the commit the pull request was opened from.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant