Skip to content

PDF encryption: Reserved permission bits might have wrong state #2401

Open
@stefan6419846

Description

@stefan6419846
Collaborator

When encrypting PDF files, there is no verification whether the reserved permission bits are passed correctly. This seems to allow for PDF files which do not completely follow the PDF 1.7 specification (table 3.20). (This is some follow-up to #2391.)

Environment

Which environment were you using when you encountered the problem?

$ python -m platform
Linux-6.5.0-10013-tuxedo-x86_64-with-glibc2.35

$ python -c "import pypdf;print(pypdf._debug_versions)"
pypdf==3.17.4, crypt_provider=('cryptography', '3.4.8'), PIL=9.0.1

Code + PDF

This is a minimal, complete example that shows the issue:

from tempfile import NamedTemporaryFile

from pypdf import PdfReader, PdfWriter
from pypdf.constants import UserAccessPermissions


with NamedTemporaryFile() as fp:
    name = fp.name
    writer = PdfWriter(clone_from='resources/crazyones.pdf')
    writer.encrypt(
        user_password='',
        owner_password='abc',
        permissions_flag=UserAccessPermissions.PRINT | UserAccessPermissions.PRINT_TO_REPRESENTATION | UserAccessPermissions.FILL_FORM_FIELDS | UserAccessPermissions.R1,
        algorithm='AES-128'
    )
    writer.write(name)
    reader = PdfReader(name)
    print(reader._encryption.V)
    print(UserAccessPermissions(reader._encryption.P))

The PDF file is from our own resources directory.

Output

This will print:

4
UserAccessPermissions.PRINT_TO_REPRESENTATION|FILL_FORM_FIELDS|PRINT|R1

Problem

  • R1 and R2 are meant to be 0, but can be declared as 1.
  • R7 and R8 as well as R13-R32 are meant to always be 1, but can be declared as 0 by omitting them.

Activity

MartinThoma

MartinThoma commented on Jan 28, 2024

@MartinThoma
Member

This seems to allow for PDF files which do not completely follow the PDF 1.7 specification (table 3.20)

I think I might have a different version of the specs as I don't have that table.

In PDF 32000-1:2008, First Edition, 2008-7-1, Document management — Portable document format — Part 1: PDF 1.7 there is Table 22 – User access permissions.

I do see a note, though:

PDF integer objects can be interpreted as binary values in a signed twos-complement form. Since all the
reserved high-order flag bits
in the encryption dictionary’s P value are required to be 1, the integer value P
shall be specified as a negative integer. For example, assuming revision 2 of the security handler, the value -
44 permits printing and copying but disallows modifying the contents and annotations.

This means that R13 -R32 are required to be 1.

However, I don't see evidence for any other values.

stefan6419846

stefan6419846 commented on Jan 28, 2024

@stefan6419846
CollaboratorAuthor

There are indeed at least two versions of the spec. In

"""TABLE 3.20 User access permissions."""
we reference https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/pdfreference1.7old.pdf with the aforementioned table 3.20, while table 22 of https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf is indeed shorter and does not list the reserved bits, but tells us:

Conforming readers shall ignore all flags other than those at bit positions 3, 4, 5, 6, 9, 10, 11, and 12.

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

    workflow-encryptionFrom a users perspective, encryption is the affected feature/workflow

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @MartinThoma@stefan6419846

      Issue actions

        PDF encryption: Reserved permission bits might have wrong state · Issue #2401 · py-pdf/pypdf