PyMuPDF is_encrypted=False for AES PDFs with empty-user-password
PyMuPDF reports is_encrypted=False for empty-user-password AES PDFs. In a document-harvesting pipeline I used Document.is_encrypted to decide whether to explicitly decrypt a PDF and record its original encryption status. Two known encrypted inputs were readable and returned false, so the inventory incorrectly recorded them as unencrypted. Document.needs_pass was also false, while document.metadata['encryption'] still described AES encryption. I needed to distinguish a readable encrypted file from an actually unencrypted file without relying on password prompts.
Do not use PyMuPDF's is_encrypted or needs_pass as the original-file encryption inventory flag for this case. With an empty user password, PyMuPDF can read the document and both properties are false even though the PDF still has an encryption dictionary. pikepdf.Pdf.is_encrypted remains true after opening that same encrypted payload with password=''. Use that property to record input encryption, then save a decrypted temporary PDF explicitly.
Reproduction, entirely in memory:
import io
import pikepdf
import pymupdf
source = pymupdf.open()
source.new_page().insert_text((72, 72), 'Example document')
payload = source.tobytes(
encryption=pymupdf.PDF_ENCRYPT_AES_256,
owner_pw='0123456789',
user_pw='',
)
with pymupdf.open(stream=payload, filetype='pdf') as pdf:
print(pdf.is_encrypted, pdf.needs_pass)
print(pdf.metadata['encryption'])
print(pdf[0].get_text().strip())
with pikepdf.open(io.BytesIO(payload), password='') as pdf:
print(pdf.is_encrypted)
decrypted = io.BytesIO()
pdf.save(decrypted)
with pikepdf.open(io.BytesIO(decrypted.getvalue())) as pdf:
print(pdf.is_encrypted)Observed with PyMuPDF 1.28.2 and pikepdf 10.13.0.post1: False 0; Standard V5 R6 256-bit AES; readable text; then pikepdf True for the original and False for the saved output. The empty-password path is not a way around unknown passwords: genuinely password-protected inputs still need their password or an explicit failure disposition.