Summary
page_index_flash() crashes with PyPDF2.errors.DependencyError: PyCryptodome is required for AES algorithm on any AES-encrypted PDF, including PDFs that only use encryption for permission flags (copy/print restrictions) with an empty user password — i.e. PDFs that open and read fine in any normal viewer. requirements.txt on this branch pins PyPDF2==3.0.1 but does not include pycryptodome, which PyPDF2 needs as an optional dependency to decrypt AES-protected content streams.
Environment
- Branch/commit:
feat/pageindex-flash @ c7243700c7aa37bad386a5878b1badc269fcc7a2
- Python: 3.12.13 (Windows)
PyPDF2==3.0.1, pypdfium2==4.30.0 (as pinned in requirements.txt)
- Invocation:
run_pageindex.py --pdf_path <file> --flash
Repro
Run Flash against any text-layer PDF that uses AES encryption for permissions only (a common pattern for publicly distributed standards/reference documents — no password prompt needed to open or read it in a normal PDF viewer):
python run_pageindex.py --pdf_path <aes-encrypted.pdf> --flash
Traceback
Traceback (most recent call last):
File "run_pageindex.py", line 60, in <module>
toc_with_page_number = page_index_flash(args.pdf_path)
File "pageindex/flash/api.py", line 73, in page_index_flash
return extract_toc(_validate_pdf(pdf))
File "pageindex/flash/main.py", line 131, in extract_toc
parsed, page_meta = parse_charlevel_meta(doc_handle)
File "pageindex/flash/parser_pdfium_charlevel/pipeline.py", line 117, in parse_charlevel_meta
if pdf_doc is not None and page_idx < pdf_doc.page_count:
File "pageindex/flash/parser_pdfium_charlevel/pdf_objects.py", line 125, in page_count
return len(self._reader.pages)
File ".venv/Lib/site-packages/PyPDF2/_page.py", line 2063, in __len__
return self.length_function()
File ".venv/Lib/site-packages/PyPDF2/_reader.py", line 445, in _get_num_pages
return self.trailer[TK.ROOT]["/Pages"]["/Count"]
File ".venv/Lib/site-packages/PyPDF2/generic/_data_structures.py", line 266, in __getitem__
return dict.__getitem__(self, key).get_object()
File ".venv/Lib/site-packages/PyPDF2/generic/_base.py", line 259, in get_object
obj = self.pdf.get_object(self)
File ".venv/Lib/site-packages/PyPDF2/_reader.py", line 1205, in get_object
retval = self._get_object_from_stream(indirect_reference)
File ".venv/Lib/site-packages/PyPDF2/_reader.py", line 1136, in _get_object_from_stream
obj_stm: EncodedStreamObject = IndirectObject(stmnum, 0, self).get_object()
File ".venv/Lib/site-packages/PyPDF2/generic/_base.py", line 259, in get_object
obj = self.pdf.get_object(self)
File ".venv/Lib/site-packages/PyPDF2/_reader.py", line 1269, in get_object
retval = self._encryption.decrypt_object(
File ".venv/Lib/site-packages/PyPDF2/_encryption.py", line 761, in decrypt_object
return cf.decrypt_object(obj)
File ".venv/Lib/site-packages/PyPDF2/_encryption.py", line 185, in decrypt_object
obj._data = self.stmCrypt.decrypt(obj._data)
File ".venv/Lib/site-packages/PyPDF2/_encryption.py", line 147, in decrypt
raise DependencyError("PyCryptodome is required for AES algorithm")
PyPDF2.errors.DependencyError: PyCryptodome is required for AES algorithm
Suggested fix
Either:
- Add
pycryptodome to requirements.txt so AES-encrypted PDFs decode correctly (installing it locally against this same pinned checkout resolves the crash), or
- Catch
PyPDF2.errors.DependencyError in the Flash path (parser_pdfium_charlevel/pdf_objects.py / pipeline.py) and surface it as a handled "unsupported PDF" result — same as the existing handling for scanned/encrypted PDFs mentioned in the README — instead of an unhandled exception.
Option 1 is preferable where possible: many permission-only-encrypted PDFs have no real password barrier and are otherwise perfectly parseable once the dependency is present.
Context
Found via a downstream integration (a pinned, local-only install of this Flash preview branch) hitting this reproducibly on a real corpus PDF. Happy to share more detail if useful.
Summary
page_index_flash()crashes withPyPDF2.errors.DependencyError: PyCryptodome is required for AES algorithmon any AES-encrypted PDF, including PDFs that only use encryption for permission flags (copy/print restrictions) with an empty user password — i.e. PDFs that open and read fine in any normal viewer.requirements.txton this branch pinsPyPDF2==3.0.1but does not includepycryptodome, whichPyPDF2needs as an optional dependency to decrypt AES-protected content streams.Environment
feat/pageindex-flash@c7243700c7aa37bad386a5878b1badc269fcc7a2PyPDF2==3.0.1,pypdfium2==4.30.0(as pinned inrequirements.txt)run_pageindex.py --pdf_path <file> --flashRepro
Run Flash against any text-layer PDF that uses AES encryption for permissions only (a common pattern for publicly distributed standards/reference documents — no password prompt needed to open or read it in a normal PDF viewer):
Traceback
Suggested fix
Either:
pycryptodometorequirements.txtso AES-encrypted PDFs decode correctly (installing it locally against this same pinned checkout resolves the crash), orPyPDF2.errors.DependencyErrorin the Flash path (parser_pdfium_charlevel/pdf_objects.py/pipeline.py) and surface it as a handled "unsupported PDF" result — same as the existing handling for scanned/encrypted PDFs mentioned in the README — instead of an unhandled exception.Option 1 is preferable where possible: many permission-only-encrypted PDFs have no real password barrier and are otherwise perfectly parseable once the dependency is present.
Context
Found via a downstream integration (a pinned, local-only install of this Flash preview branch) hitting this reproducibly on a real corpus PDF. Happy to share more detail if useful.