Skip to content

proposal: give pypdf an AES backend so AES-encrypted PDFs can be read #209

Open

Description

@L4XB

Problem

pypdf decrypts AES only through an optional crypto backend: cryptography, or pycryptodome under the Crypto namespace. The API depends on pycryptodomex, whose namespace is Cryptodome, and pypdf does not look for that one. In the locked API environment pypdf therefore runs on its fallback, which handles RC4 only:

$ uv run --frozen --project services/api python -c "import pypdf._crypt_providers as c; print(c.crypt_provider)"
('local_crypt_fallback', '0.0.0')

Acrobat has offered AES for permission passwords since version 7 (AES-128) and X (AES-256), so a PDF restricted with a current tool is likely to be an AES file. #208 accepts PDFs that carry only an owner password (#115), but it can do that only for RC4 files. An AES file with an empty user password is still refused as encrypted, because its content cannot be decrypted here.

Measured with synthetic files from pypdf 6.19.0 (the locked version) and the code in #208:

file locked API environment same environment plus cryptography
RC4-40 / RC4-128, owner password only accepted, text parsed accepted, text parsed
AES-128, owner password only refused: encrypted accepted, text parsed
AES-256, owner password only refused: encrypted accepted, text parsed
any of these with a user password refused: encrypted refused: encrypted

Proposed behavior

Give pypdf a backend by depending on pypdf[crypto] in services/api, the extra pypdf documents for this, which pulls in cryptography. The validation from #208 needs no change for the right-hand column. A test can then generate AES-128 and AES-256 owner-only PDFs with PdfWriter.encrypt(user_password="", owner_password=..., algorithm=...), which also needs the backend, and assert that they upload with text while user-password files stay refused.

Alternatives considered

  1. Add pycryptodome next to pycryptodomex. pypdf would find it, but the API would then carry the same library under two namespaces.
  2. Keep refusing AES files and say so in the upload error and the self-hosting docs. This keeps the dependency set, and most restricted publisher PDFs stay refused.

Compatibility and research-method implications

No research-method change. More uploads are accepted: AES files with only an owner password. Every file that needs a password to open is still refused, and no password is ever accepted, stored or logged. The API image gains one compiled dependency.

Dependencies, network, and data terms

New runtime dependency cryptography (PyCA, Apache-2.0 OR BSD-3-Clause, wheels for the supported platforms), through pypdf[crypto]. No network calls and no data egress. This issue comes before any PR because CONTRIBUTING asks for one before a new dependency.

Submission checks

  • This proposal fits the community source tree and does not require production secrets, customer data, payment/subscription code, or hosted administration.
  • I searched existing issues and discussions for the same proposal.
  • I agree to follow the Code of Conduct.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions