- corpus-licensing.md: OQ-01 resolution - all fixtures are synthetic with no external licensing - font-fingerprinting.md: OQ-02 resolution - Level 3 fingerprint database methodology and curation pipeline - ocr-accuracy.md: PB-3 fallback plan - Tesseract WER targets (3% primary, 5% fallback) with methodology - pdf-2-coverage.md: PB-10/R10 analysis - PDF 2.0 feature compatibility matrix All four files are required phase sign-off artifacts referenced in the plan. Resolves OQ-01, OQ-02, PB-3, PB-10.
12 KiB
PDF 2.0 Feature Coverage
Risk R10: PDF 2.0 features (PAdES-LTV signatures, AES-256 enhancements, /Encryption V5) not covered
Proof Obligation PB-10: Support PDF 2.0 features incrementally; ship an explicit compatibility matrix in this document.
Overview
PDF 2.0 (ISO 32000-2:2017) introduces numerous changes and enhancements over PDF 1.7. This document tracks pdftract's support for PDF 2.0 features, what's implemented, what's deferred, and the compatibility matrix.
PDF Version Support Matrix
| PDF Version | ISO Specification | Read Support | Write Support | Notes |
|---|---|---|---|---|
| PDF 1.0 | (1993) | ✅ Full | ❌ None | Obsolete; rare in wild |
| PDF 1.1 | (1994) | ✅ Full | ❌ None | Obsolete; rare in wild |
| PDF 1.2 | (1996) | ✅ Full | ❌ None | Obsolete; rare in wild |
| PDF 1.3 | (1999) | ✅ Full | ❌ None | Common; JPEG 2000, EC-MA流 |
| PDF 1.4 | (2001) | ✅ Full | ❌ None | Target baseline; transparency, metadata |
| PDF 1.5 | (2003) | ✅ Full | ❌ None | Object streams, cross-reference streams |
| PDF 1.6 | (2004) | ✅ Full | ❌ None | Adobe Extension Level 3 |
| PDF 1.7 | (2008) | ✅ Full | ❌ None | Adobe Extension Level 8; PDF/A-2, PDF/UA-1 |
| PDF 2.0 | (2017) | ⚠️ Partial | ❌ None | See detailed breakdown below |
Key: ✅ Supported | ⚠️ Partial | ❌ Unsupported | 🔄 Deferred to v1.1+
PDF 2.0 Feature Coverage
✅ Fully Supported (v1.0.0)
Encryption: AES-256 (V=5, R=5)
Status: ✅ Implemented (Phase 1.4)
- Standard: PDF 2.0
/Encryption V=5, R=5 - Algorithm: AES-256 in CBC mode
- Key derivation: PDF 2.0 Revision 5 algorithm (32-byte encryption key)
- Test fixture:
EC-06-aes256-encrypted.pdf
Implementation:
// Phase 1.4 decryption handler
pub fn decrypt_pdf_2_encryption(
pdf_data: &[u8],
password: &str,
) -> Result<Vec<u8>, DecryptError> {
// PDF 2.0 V=5, R=5 uses AES-256-CBC
let key = derive_key_r5(password, &pdf_data.encrypt_key_metadata);
let decrypted = aes_256_cbc_decrypt(&pdf_data.encrypted_streams, &key);
Ok(decrypted)
}
Limitations:
- No cryptographic validation (signature verification, certificate chain checks)
- Password-only decryption (no certificate-based encryption)
- See "Crypto Validation" below for non-goal documentation
XMP Metadata: PDF 2.0 Schema
Status: ✅ Implemented (Phase 1.6)
- Standard: XMP specification 2014 + PDF 2.0 properties
- Properties:
pdf:Prefix,pdf:Keywords,pdf:Version - Test fixture: Tagged PDFs with PDF 2.0 XMP
Implementation:
// Phase 1.6 metadata extraction
pub fn extract_xmp_metadata(pdf: &PdfDocument) -> Result<XmpMetadata, MetadataError> {
let xmp_stream = pdf.get_xmp_stream()?;
let xml = std::str::from_utf8(&xmp_stream.data)?;
let pdf_version = extract_pdf_version_from_xmp(xml)?;
Ok(XmpMetadata { pdf_version, ... })
}
⚠️ Partially Supported (v1.0.0)
Linearization (Fast Web View)
Status: ⚠️ Basic support; fingerprint stability verified (Phase 1.7, KU-7)
- Standard: PDF 1.4+ feature for incremental download
- pdftract behavior: Reads linearized PDFs correctly; fingerprint computed from primary content stream (ignores hint tables)
- Test: Phase 1.7 critical test verifies fingerprint stability after
qpdf --linearize
Limitations:
- Does not use hint tables for optimized reading
- Reads entire file into memory (no progressive loading)
- Fingerprint includes hint stream data (but is stable across re-linearization)
Object Streams (Compressed Objects)
Status: ⚠️ Read-only; supports decompression but not compression
- Standard: PDF 1.5+; compresses indirect objects in a single stream
- pdftract behavior: Decompresses object streams during parsing (Phase 1.2)
- Implementation: Uses
flate2crate for decompression
Limitations:
- Cannot write object streams (no PDF generation support)
- Does not validate object stream integrity (assumes well-formed)
Cross-Reference Streams
Status: ⚠️ Read-only; supports hybrid xref tables
- Standard: PDF 1.5+; compressed xref tables
- pdftract behavior: Falls back to forward scan if xref stream is corrupt (Phase 1.3, EC-07)
Limitations:
- No write support for xref streams
- Hybrid xref (table + stream) may not be fully optimized
❌ Unsupported but Documented (v1.0.0)
PAdES-LTV Signatures
Status: ❌ Unsupported; non-goal per Phase 7.3
- Standard: PDF 2.0 Part 3 (PAdES-LTV — Long-Term Validation)
- Function: Document signatures with certificate validation and timestamp tokens
- pdftract behavior: Extracts signature dictionary as raw metadata; does not validate
Non-Goal Rationale:
- Crypto validation is out of scope for v1.0.0 (documented in Phase 7.3)
- Signature validation requires:
- X.509 certificate chain verification
- CRL/OCSP revocation checking
- Timestamp token validation (RFC 3161)
- Complex trust anchor management
Workaround:
- Use dedicated PDF validation tools (Adobe Acrobat Reader,
pdfsigfrom Poppler) - Extract signature metadata via pdftract's
/Vdictionary parsing
Future (v1.1+):
- May add
--validate-signaturesflag usingopensslorrustlscrates - Would require explicit trust store configuration
/Encryption V5 Cryptographic Enhancements
Status: ⚠️ Basic AES-256 decryption; no public-key encryption
-
Standard: PDF 2.0
/Encryption V5adds:- Public-key encryption (recipient list)
- Custom encryption methods
- Encrypt metadata independently
-
pdftract support:
- ✅ Password-based AES-256 (V=5, R=5)
- ❌ Public-key encryption (certificate-based)
- ❌ Custom encryption methods
- ❌ Separate metadata encryption
Limitations:
- Only password-based decryption is implemented
- Certificate-based encryption (recipient list) not supported
- Errors with clear diagnostic:
EncryptionError("Certificate-based encryption not supported; see docs/notes/pdf-2-coverage.md")
Adobe Extension Levels
Status: ❌ Not parsed; treats all PDF 1.7+ files uniformly
- Standard: Adobe Extension Levels (E1-E8) add features beyond ISO 32000-1:2008
- pdftract behavior: Ignores
/Extensionsdictionary; reads any PDF 1.7+ file
Impact:
- Extension-specific features (e.g., Adobe's private encryption variants) may fail
- Most common extensions (transparency, layers) are standard in PDF 2.0 anyway
🔄 Deferred to v1.1+
3D Artwork (PRC / U3D)
Status: 🔄 Deferred
- Standard: PDF 2.0
/3Dannotations with PRC or U3D embedded models - Use case: CAD documents, 3D product specifications
- Priority: Low (niche use case)
- Planned: v1.2+ with
--features 3dgate
Rich Media (Flash, Video, Audio)
Status: 🔄 Deferred
- Standard: PDF 2.0
/RichMediaannotations - Use case: Interactive presentations, multimedia documents
- Priority: Low (Flash is obsolete; HTML5 preferred)
- Planned: v1.2+ with
--features richmediagate
Web Capture (XFDF)
Status: 🔄 Deferred
- Standard: PDF 2.0
/XFDFforms for web form capture - Use case: AcroForm submission to web servers
- Priority: Medium (relevant to Phase 7.4 forms work)
- Planned: v1.1+ as part of forms enhancements
Compatibility Matrix by Feature
| PDF 2.0 Feature | ISO Reference | Read Support | Write Support | Notes |
|---|---|---|---|---|
| Encryption | ||||
| AES-256 password (V=5, R=5) | ISO 32000-2:2017 §7.6 | ✅ Phase 1.4 | ❌ | Phase 7.3 non-goal: no crypto validation |
| Public-key encryption | ISO 32000-2:2017 §7.6.4 | ❌ | ❌ | Deferred to v1.1+ |
| Custom encryption methods | ISO 32000-2:2017 §7.6.5 | ❌ | ❌ | Deferred to v1.2+ |
| Metadata | ||||
| XMP 2014 schema | ISO 32000-2:2017 §14.3 | ✅ Phase 1.6 | ❌ | Full XMP parsing |
| PDF 2.0 properties | ISO 32000-2:2017 §14.3.2 | ✅ Phase 1.6 | ❌ | pdf:Prefix, pdf:Keywords |
| Structure | ||||
| Tagged PDF (PDF/UA-1) | ISO 32000-2:2017 §14.8 | ✅ Phase 7.1 | ❌ | StructTree extraction |
| Reading order | ISO 32000-2:2017 §14.8.4 | ✅ Phase 4.5 | ❌ | XY-cut + reading order |
| Fonts | ||||
| OpenType fonts | ISO 32000-2:2017 §9.8 | ✅ Phase 2.2 | ❌ | Subset + ToUnicode |
| Variable fonts | ISO 32000-2:2017 §9.9 | ⚠️ Partial | ❌ | Reads as static fonts |
| CJK composite fonts | ISO 32000-2:2017 §9.10 | ✅ Phase 2.3 | ❌ | Type0 + CIDFonts |
| Graphics | ||||
| JPEG 2000 (JPX) | ISO 32000-2:2017 §8.9.5 | ⚠️ Phase 5.2 | ❌ | OCR support via full-render |
| Artifact marked content | ISO 32000-2:2017 §14.7 | ✅ Phase 7.1 | ❌ | Suppress from output |
| Optional content (OCG) | ISO 32000-2:2017 §8.11 | ✅ Phase 1.4 | ❌ | BaseState = OFF handling |
| Forms | ||||
| AcroForm 2.0 | ISO 32000-2:2017 §12.7 | ✅ Phase 7.4 | ❌ | Field extraction |
| XFA forms | ISO 32000-2:2017 §12.7.8 | ⚠️ Phase 7.4 | ❌ | Placeholder detection |
| Other | ||||
| Linearization | PDF 1.4+ | ⚠️ Phase 1.7 | ❌ | Read-only, stable fingerprint |
| Object streams | PDF 1.5+ | ✅ Phase 1.2 | ❌ | Decompression only |
| Xref streams | PDF 1.5+ | ✅ Phase 1.3 | ❌ | Hybrid table support |
| PAdES-LTV signatures | ISO 32000-2:2017 §12.8 | ❌ | ❌ | Non-goal; metadata only |
| 3D artwork | ISO 32000-2:2017 §13.6 | ❌ | ❌ | Deferred to v1.2+ |
| Rich media | ISO 32000-2:2017 §13.7 | ❌ | ❌ | Deferred to v1.2+ |
Non-Goals (Explicitly Out of Scope)
Per Phase 7.3 documentation, the following are non-goals for v1.0.0:
- Cryptographic validation: No signature verification, certificate chain checking, or revocation checking
- PDF generation: No write support for any PDF version (read-only tool)
- Rendering: No visual rendering of PDF pages (text extraction only)
- JavaScript execution: No
/JSaction evaluation or form field scripting - Embedded file extraction: No
/EmbeddedFilesextraction (attachments)
Version Detection
pdftract detects PDF 2.0 files via:
- Header check:
%PDF-2.0or%PDF-2.N(N = subversion) - Version key:
/Versionentry in/Catalogdictionary - XMP metadata:
pdf:Versionproperty in XMP packet
Implementation:
// Phase 1.1: PDF version detection
pub fn detect_pdf_version(pdf_data: &[u8]) -> PdfVersion {
// Check header
if let Some(version) = parse_header_version(pdf_data) {
return version;
}
// Check /Version key
if let Some(version) = parse_catalog_version(pdf_data) {
return version;
}
// Check XMP
if let Some(version) = parse_xmp_version(pdf_data) {
return version;
}
PdfVersion::V1_4 // Default baseline
}
Testing
PDF 2.0 Test Fixtures
EC-06-aes256-encrypted.pdf— AES-256 encryption (V=5, R=5)- Tagged PDFs with XMP — PDF 2.0 metadata extraction
- Linearized PDFs — Fingerprint stability test (KU-7)
Regression Tests
# Run PDF 2.0-specific tests
cargo nextest run pdf_2_encryption
cargo nextest run pdf_2_metadata
cargo nextest run linearization_fingerprint
# Verify PDF 2.0 extraction works
cargo run -- extract tests/fixtures/encrypted/EC-06-aes256-encrypted.pdf --password user256 --json out.json
Future Enhancements (v1.1+)
v1.1 Planned Additions
-
Certificate-based encryption (V=5, R=5 public-key):
- Parse
/Recipientslist - Use
rustlsoropensslfor decryption - Feature gate:
--features encryption-cert
- Parse
-
PAdES-LTV signature metadata extraction:
- Extract
/Vand/Sigdictionaries - Return certificate metadata (subject, issuer, validity)
- No validation (metadata only)
- Feature gate:
--features signatures
- Extract
-
PDF 2.0 properties in schema:
- Add
pdf_versionto metadata schema - Expose
pdf:Prefix,pdf:Keywordsin output JSON
- Add
v1.2+ Considerations
-
Variable font support (partial):
- Read
fvartable for named instances - Select default instance for glyph mapping
- Feature gate:
--features variable-fonts
- Read
-
3D artwork extraction:
- Parse PRC/U3D streams
- Return mesh data as JSON
- Feature gate:
--features 3d
References
- Plan Risk R10 (line ~564)
- Plan Proof Obligation PB-10 (line ~583)
- ISO 32000-2:2017 — PDF 2.0 specification
tests/fixtures/encrypted/EC-06-aes256-encrypted.pdf— PDF 2.0 encryption test fixture- Phase 1.4 implementation: PDF 2.0 AES-256 decryption
- Phase 1.6 implementation: XMP metadata extraction
- Phase 7.1 implementation: Tagged PDF / PDF/UA-1 structure tree