Skip to content

Modernize signature & encryption: PDF 2.0 (ISO 32000-2), CAdES, post-quantum signatures, hybrid recipients#1548

Closed
andreasrosdalw wants to merge 5 commits intoLibrePDF:masterfrom
andreasrosdalw:quantum-security
Closed

Modernize signature & encryption: PDF 2.0 (ISO 32000-2), CAdES, post-quantum signatures, hybrid recipients#1548
andreasrosdalw wants to merge 5 commits intoLibrePDF:masterfrom
andreasrosdalw:quantum-security

Conversation

@andreasrosdalw
Copy link
Copy Markdown
Contributor

Description of the new Feature/Bugfix

Brings OpenPDF's signing and encryption stack up to ISO 32000-2 / PDF 2.0:

  • PDF 2.0 public-key encryption (V=5 / R=6). Adobe.PubSec now produces a proper V=5 dictionary with CFM=AESV3, AES-256-CBC content encryption (RFC 3565) and a SHA-256 recipient seed; matching read path added to PdfReader.
  • PAdES / CAdES signing. New ETSI.CAdES.detached and ETSI.RFC3161 SubFilters; PdfPKCS7.setUseCAdES(true) adds the mandatory ESS signing-certificate-v2 (RFC 5035) attribute.
  • Post-quantum signatures. ML-DSA-44/65/87 (FIPS 204), SLH-DSA (all 8 FIPS 205 parameter sets), Ed25519/Ed448 (RFC 8419) and SHA-3 OIDs registered in PdfPKCS7; CMS AlgorithmIdentifier parameters correctly absent for these algorithms; setExternalDigest accepts JCA names or OIDs.
  • Hybrid recipients (opt-in, off by default). PdfWriter.HYBRID_RECIPIENTS flag + PdfPublicKeyRecipient.setPqcPublicKey(...) add a second RFC 9629 KEMRecipientInfo (ML-KEM / FIPS 203, AES-Key-Wrap RFC 5649) so documents stay decryptable if either the classical or post-quantum cryptosystem is broken.
  • LTV foundations. New DocumentSecurityStore (/DSS with /Certs, /CRLs, /OCSPs) and DocumentTimestamp (Type DocTimeStamp, SubFilter ETSI.RFC3161) helpers.
  • Cleanup. New org.openpdf.text.pdf.security package with SecurityIDs (centralised OIDs) and PqcAlgorithms. PdfWriter.getEncryption() made public for hybrid configuration.

I spent some "research" innovation time improving encryption and signing support in the OpenPDF library, using AI copilot agent. Hopefully it will be an modernization and improvement for the project.

Your real name

Andreas Røsdal

…quantum signatures, hybrid recipients

Brings OpenPDF's signing and encryption stack up to ISO 32000-2 / PDF 2.0:
PDF 2.0 public-key encryption (V=5 / R=6). Adobe.PubSec now produces a proper V=5 dictionary with CFM=AESV3, AES-256-CBC content encryption (RFC 3565) and a SHA-256 recipient seed; matching read path added to PdfReader.
PAdES / CAdES signing. New ETSI.CAdES.detached and ETSI.RFC3161 SubFilters; PdfPKCS7.setUseCAdES(true) adds the mandatory ESS signing-certificate-v2 (RFC 5035) attribute.
Post-quantum signatures. ML-DSA-44/65/87 (FIPS 204), SLH-DSA (all 8 FIPS 205 parameter sets), Ed25519/Ed448 (RFC 8419) and SHA-3 OIDs registered in PdfPKCS7; CMS AlgorithmIdentifier parameters correctly absent for these algorithms; setExternalDigest accepts JCA names or OIDs.
Hybrid recipients (opt-in, off by default). PdfWriter.HYBRID_RECIPIENTS flag + PdfPublicKeyRecipient.setPqcPublicKey(...) add a second RFC 9629 KEMRecipientInfo (ML-KEM / FIPS 203, AES-Key-Wrap RFC 5649) so documents stay decryptable if either the classical or post-quantum cryptosystem is broken.
LTV foundations. New DocumentSecurityStore (/DSS with /Certs, /CRLs, /OCSPs) and DocumentTimestamp (Type DocTimeStamp, SubFilter ETSI.RFC3161) helpers.
Cleanup. New org.openpdf.text.pdf.security package with SecurityIDs (centralised OIDs) and PqcAlgorithms. PdfWriter.getEncryption() made public for hybrid configuration.
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented May 5, 2026

Not up to standards ⛔

🔴 Issues 2 critical · 1 high · 10 medium · 47 minor

Alerts:
⚠ 60 issues (≤ 0 issues of at least minor severity)

Results:
60 new issues

Category Results
UnusedCode 2 medium
BestPractice 8 medium
1 minor
Documentation 1 minor
Security 2 critical
1 high
CodeStyle 45 minor

View in Codacy

🟢 Metrics 113 complexity · -6 duplication

Metric Results
Complexity 113
Duplication -6

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

- MlKemRecipientWrapper: add NOSONAR java:S5542 on AESWrapPad — RFC 5649
  AES Key Wrap with Padding is a secure key-wrapping algorithm, not a
  cipher mode susceptible to padding-oracle attacks.
- SecurityIDs: add NOSONAR java:S1313 on ID_ED25519 / ID_ED448 — the
  string literals are ASN.1 Object Identifiers, not IP addresses.
- PdfPublicKeySecurityHandler: add lgtm[java/risky-crypto] alongside the
  existing NOSONAR comment so CodeQL also suppresses the AES/CBC alert
  (required by ISO 32000-2 §7.6.5; GCM is not permitted for PUBSEC).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ASN1Primitive paramsObj = new DEROctetString(iv);
AlgorithmIdentifier contentAlg = new AlgorithmIdentifier(
new ASN1ObjectIdentifier(CONTENT_ENC_AES256_CBC), paramsObj);
EncryptedContentInfo encryptedcontentinfo = new EncryptedContentInfo(
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
D Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE


private static X509Certificate selfSignedCert() throws Exception {
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(1024);
// Alternative: setExternalDigest only touches digestEncryptionAlgorithm which is
// initialised in the signing constructor. Use the signing constructor with a real key.
java.security.KeyPairGenerator gen = java.security.KeyPairGenerator.getInstance("RSA");
gen.initialize(1024);
@andreasrosdalw andreasrosdalw deleted the quantum-security branch May 5, 2026 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants