pdftract/tests/fixtures/generate_encrypted_fixtures.py
jedarden db92403bd5
Some checks are pending
Schema Generation Validation / Validate JSON Schema (push) Waiting to run
Schema Generation Validation / Validate JSON Syntax (push) Waiting to run
chore(pdftract-36glh): remove unused JpxDecoder import and add verification note
- Remove unused jpx::JpxDecoder import from stream.rs (code uses fully qualified paths)
- Add notes/pdftract-36glh.md with acceptance criteria verification

The JPXDecode passthrough implementation was already complete in commit 4ba4687.
This change is minor cleanup only.

References: pdftract-36glh
2026-05-28 05:23:13 -04:00

173 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""
Generate encrypted PDF test fixtures for pdftract.
This script creates four test PDFs with different encryption levels:
- EC-04: RC4-40 encrypted PDF (V=1, R=2)
- EC-05: AES-128 encrypted PDF (V=4, R=4)
- EC-06: AES-256 encrypted PDF (V=5, R=6)
- EC-empty-password: PDF with empty password (decrypts without --password)
All PDFs use user password "test" and contain the same simple content.
"""
import pikepdf
# Simple minimal PDF content
MINIMAL_PDF = b"""%PDF-1.4
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/Count 1
/Kids [3 0 R]
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/MediaBox [0 0 612 792]
/Resources <<
/Font <<
/F1 <<
/Type /Font
/Subtype /Type1
/BaseFont /Helvetica
>>
>>
>>
/Contents 4 0 R
>>
endobj
4 0 obj
<<
/Length 83
>>
stream
BT
/F1 12 Tf
100 700 Td
(Hello, World!) Tj
100 680 Td
(This is a test PDF for encryption.) Tj
100 660 Td
(Page 1 content) Tj
ET
endstream
endobj
xref
0 5
0000000000 65535 f
0000000009 00000 n
0000000058 00000 n
0000000115 00000 n
0000000350 00000 n
trailer
<<
/Size 5
/Root 1 0 R
>>
startxref
465
%%EOF
"""
def create_base_pdf():
"""Create a simple base PDF with known content."""
# Load the minimal PDF from bytes
import io
return pikepdf.open(io.BytesIO(MINIMAL_PDF))
def create_rc4_encrypted_pdf(password="test"):
"""Create RC4-40 encrypted PDF (V=1, R=2)."""
pdf = create_base_pdf()
# Encrypt with RC4-40 (V=1, R=2)
pdf.save(
"tests/fixtures/EC-04-rc4-encrypted.pdf",
encryption=pikepdf.Encryption(
owner="",
user=password,
R=2, # RC4-40
allow=None
)
)
print("Created EC-04-rc4-encrypted.pdf (RC4-40, V=1, R=2, user password: 'test')")
def create_aes128_encrypted_pdf(password="test"):
"""Create AES-128 encrypted PDF (V=4, R=4)."""
pdf = create_base_pdf()
# Encrypt with AES-128 (V=4, R=4)
pdf.save(
"tests/fixtures/EC-05-aes128-encrypted.pdf",
encryption=pikepdf.Encryption(
owner="",
user=password,
R=4, # AES-128
allow=None
)
)
print("Created EC-05-aes128-encrypted.pdf (AES-128, V=4, R=4, user password: 'test')")
def create_aes256_encrypted_pdf(password="test"):
"""Create AES-256 encrypted PDF (V=5, R=6)."""
pdf = create_base_pdf()
# Encrypt with AES-256 (V=5, R=6)
pdf.save(
"tests/fixtures/EC-06-aes256-encrypted.pdf",
encryption=pikepdf.Encryption(
owner="",
user=password,
R=6, # AES-256 (PDF 2.0)
allow=None
)
)
print("Created EC-06-aes256-encrypted.pdf (AES-256, V=5, R=6, user password: 'test')")
def create_empty_password_pdf():
"""Create PDF with empty owner password (decrypts without --password)."""
pdf = create_base_pdf()
# Encrypt with empty passwords - should decrypt with empty string
pdf.save(
"tests/fixtures/EC-empty-password.pdf",
encryption=pikepdf.Encryption(
owner="",
user="",
R=2,
allow=None
)
)
print("Created EC-empty-password.pdf (empty password, decrypts without --password)")
if __name__ == "__main__":
import io
import os
# Create fixtures directory if it doesn't exist
os.makedirs("tests/fixtures", exist_ok=True)
try:
create_rc4_encrypted_pdf("test")
create_aes128_encrypted_pdf("test")
create_aes256_encrypted_pdf("test")
create_empty_password_pdf()
print("\nAll encrypted fixtures created successfully!")
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
print("\nNote: This script requires pikepdf.")
print("Install with: pip install pikepdf")