This repository contains tools for verifying PDF documents within zero-knowledge proof systems. Learn more in this blog post: https://pse.dev/blog/zkpdf-unlocking-verifiable-data
Sometimes you need to prove that:
- A PDF is signed by a trusted authority
- A specific text appears on a given page without revealing the entire document.
This repo enables such proving capability using SP1-based circuits.
- pdf-utils/ – Rust crates for:
- Validating PKCS#7 signatures (RSA-SHA256)
- Extracting Unicode text from PDF streams
- WebAssembly bindings for browser integration
- circuits/ – SP1-compatible zero-knowledge circuits for signature and text proofs
- app/ – Minimal React frontend to demo proof generation and verification
- PDF Utils - Core PDF processing libraries
- Circuits - Zero-knowledge proof circuits
- Circuit Library - Complete PDF verification library API
- Extractor - PDF text extraction
- Signature Validator - Digital signature verification
- Core Library - Combined PDF verification
- WASM Bindings - Browser-compatible API
Add the PDF verification library to your Rust project:
[dependencies]
zkpdf-lib = { git = "https://github.com/privacy-ethereum/zkpdf", branch = "main", subdir = "circuits/lib" }use zkpdf_lib::{verify_pdf_claim, PDFCircuitInput};
// Create input for PDF verification
let input = PDFCircuitInput {
pdf_bytes: pdf_data,
page_number: 0,
offset: 100,
substring: "Important Document".to_string(),
};
// Verify PDF
let result = verify_pdf_claim(input)?;- Parse the PDF using pure Rust (no OpenSSL or C deps)
- Generate a zk proof using SP1 circuits
- Verify the proof on-chain or off-chain
Follow these steps to run the prover API and the demo frontend.
git clone git@github.com:privacy-scaling-explorations/zkpdf
cd zkpdfStart the prover service from the circuits/script directory. If you have access to the Succinct Prover Network, export your API key and run:
cd circuits/script
SP1_PROVER=network \
NETWORK_PRIVATE_KEY=<PROVER_NETWORK_KEY> \
RUST_LOG=info \
cargo run --release --bin proverThis will start the prover API on port 3001.
Note: If you don’t have access to the Succinct Prover Network, you can omit the environment variables to run the prover locally. (This will take longer.)
For local proof generation, refer to
scripts/evm.rsor run:
RUST_LOG=info cargo run --release --bin evm -- --system groth16In a separate terminal, build the WASM module and start the Next.js app:
# Build WASM module (requires Rust + wasm-pack)
cd pdf-utils/wasm && ./generate_wasm.sh && cd ../../app
# Start the frontend
yarn install
yarn devVisit http://localhost:3000 to view the interface.
zkpdf-video.mp4
- Prove that a document is signed without showing its contents
- Selectively reveal fields from government-issued certificates
- Use verified document facts in smart contracts
This project is licensed under the MIT License - see the LICENSE file for details.