Skip to content

Loading pdf file ends with cipher mode unsupported #3398

@Wojciech-Rebisz

Description

@Wojciech-Rebisz

Hi,
We are trying to load PDF file, it doesn't use any password and the whole process ends with cipher RC4 unsupported.

Environment

Which environment were you using when you encountered the problem?

$ python -m platform
# macOS-14.6.1-x86_64-i386-64bit

$ python -c "import pypdf;print(pypdf._debug_versions)"
# pypdf==5.8.0, crypt_provider=('cryptography', '44.0.1'), PIL=none

Code + PDF

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

from pypdf import PdfReader

reader = PdfReader('APPLE_2023Q3_10Qde.pdf')
full_text = [page.extract_text() for page in reader.pages]
full_text

Share here the PDF file(s) that cause the issue. The smaller they are, the
better. Let us know if we may add them to our tests!

APPLE_2023Q3_10Qde.pdf

Traceback

This is the complete traceback I see:

Click to see
---------------------------------------------------------------------------
UnsupportedAlgorithm                      Traceback (most recent call last)
Cell In[3], line 3
      1 from pypdf import PdfReader
----> 3 reader = PdfReader('APPLE_2023Q3_10Qde.pdf')
      4 full_text = [page.extract_text() for page in reader.pages]
      5 full_text

File ~/miniforge3/envs/temp_libs/lib/python3.11/site-packages/pypdf/_reader.py:142, in PdfReader.__init__(self, stream, strict, password)
    140 self._encryption: Optional[Encryption] = None
    141 if self.is_encrypted:
--> 142     self._handle_encryption(password)
    143 elif password is not None:
    144     raise PdfReadError("Not an encrypted file")

File ~/miniforge3/envs/temp_libs/lib/python3.11/site-packages/pypdf/_reader.py:174, in PdfReader._handle_encryption(self, password)
    171 # try empty password if no password provided
    172 pwd = password if password is not None else b""
    173 if (
--> 174     self._encryption.verify(pwd) == PasswordType.NOT_DECRYPTED
    175     and password is not None
    176 ):
    177     # raise if password provided
    178     raise WrongPasswordError("Wrong password")
    179 self._override_encryption = False

File ~/miniforge3/envs/temp_libs/lib/python3.11/site-packages/pypdf/_encryption.py:963, in Encryption.verify(self, password)
    961 def verify(self, password: Union[bytes, str]) -> PasswordType:
    962     pwd = self._encode_password(password)
--> 963     key, rc = self.verify_v4(pwd) if self.V <= 4 else self.verify_v5(pwd)
    964     if rc != PasswordType.NOT_DECRYPTED:
    965         self._password_type = rc

File ~/miniforge3/envs/temp_libs/lib/python3.11/site-packages/pypdf/_encryption.py:971, in Encryption.verify_v4(self, password)
    969 def verify_v4(self, password: bytes) -> Tuple[bytes, PasswordType]:
    970     # verify owner password first
--> 971     key = AlgV4.verify_owner_password(
    972         password,
    973         self.R,
    974         self.Length,
    975         self.values.O,
    976         self.values.U,
    977         self.P,
    978         self.id1_entry,
    979         self.EncryptMetadata,
    980     )
    981     if key:
    982         return key, PasswordType.OWNER_PASSWORD

File ~/miniforge3/envs/temp_libs/lib/python3.11/site-packages/pypdf/_encryption.py:459, in AlgV4.verify_owner_password(owner_password, rev, key_size, o_entry, u_entry, P, id1_entry, metadata_encrypted)
    457     for i in range(19, -1, -1):
    458         key = bytes(x ^ i for x in rc4_key)
--> 459         user_password = rc4_decrypt(key, user_password)
    460 return AlgV4.verify_user_password(
    461     user_password,
    462     rev,
   (...)    468     metadata_encrypted,
    469 )

File ~/miniforge3/envs/temp_libs/lib/python3.11/site-packages/pypdf/_crypt_providers/_cryptography.py:97, in rc4_decrypt(key, data)
     96 def rc4_decrypt(key: bytes, data: bytes) -> bytes:
---> 97     decryptor = Cipher(ARC4(key), mode=None).decryptor()
     98     return decryptor.update(data) + decryptor.finalize()

File ~/miniforge3/envs/temp_libs/lib/python3.11/site-packages/cryptography/hazmat/primitives/ciphers/base.py:128, in Cipher.decryptor(self)
    127 def decryptor(self):
--> 128     return rust_openssl.ciphers.create_decryption_ctx(
    129         self.algorithm, self.mode
    130     )

UnsupportedAlgorithm: cipher RC4 in None mode is not supported 

Is there any recommended workaround for the issue? Can we somehow set the mode?

Metadata

Metadata

Assignees

No one assigned

    Labels

    cannot-reproduceReported issues that might exist, but are impossible to solve as we cannot reproduce them

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions