| Crates.io | zk-psi-verifier |
| lib.rs | zk-psi-verifier |
| version | 0.1.0 |
| created_at | 2025-10-19 17:19:21.269851+00 |
| updated_at | 2025-10-19 17:19:21.269851+00 |
| description | Zero-knowledge Private Set Intersection verifier using Halo2 for zkVerify |
| homepage | |
| repository | https://github.com/kunalsinghdadhwal/zk-psi-verifier |
| max_upload_size | |
| id | 1890666 |
| size | 79,486 |
A high-performance, production-ready Rust library for zero-knowledge Private Set Intersection (PSI) using Halo2 Plonk proofs. Built for zkVerify and decentralized ZK verification networks.
zk-psi-verifier enables two parties to prove the size of their set intersection without revealing the sets themselves. Using cutting-edge zero-knowledge cryptography (Halo2 with KZG polynomial commitments), this library provides:
Private Set Intersection has critical applications in:
Traditional PSI requires interaction or reveals partial information. Our ZK-PSI generates non-interactive, publicly verifiable proofs suitable for blockchain and decentralized systems like zkVerify.
git clone https://github.com/kunalsinghdadhwal/zk-psi-verifier.git
cd zk-psi-verifier
cargo build --release
cargo run --release --bin setup -- --k 12 --output-dir ./keys
This generates:
cargo run --release --bin cli -- prove \
--set-a "1,2,3,4,5" \
--set-b "3,4,5,6,7" \
--output proof.bin \
--pk ./keys/proving_key.bin \
--params ./keys/params.bin \
--public-inputs-file public_inputs.bin
cargo run --release --bin cli -- verify \
--proof proof.bin \
--public-inputs public_inputs.bin \
--vk ./keys/verifying_key.bin \
--params ./keys/params.bin
The CLI automatically hashes non-numeric inputs:
cargo run --release --bin cli -- prove \
--set-a "alice,bob,charlie" \
--set-b "bob,charlie,david" \
--output proof.bin \
--pk ./keys/proving_key.bin \
--params ./keys/params.bin
use pasta_curves::Fp;
use zk_psi_verifier::{hash_to_field, PsiCircuit, setup, generate_proof, verify_proof};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Hash input sets to field elements
let set_a: Vec<Fp> = vec![1, 2, 3].iter().map(|&x| hash_to_field(x)).collect();
let set_b: Vec<Fp> = vec![2, 3, 4].iter().map(|&x| hash_to_field(x)).collect();
// Compute intersection size (for witness)
let circuit = PsiCircuit::new(set_a.clone(), set_b.clone(), 0);
let intersection_size = circuit.compute_intersection_size();
// Trusted setup
let k = 10;
let (params, pk, vk) = setup(k)?;
// Generate proof
let circuit = PsiCircuit::new(set_a, set_b, intersection_size);
let public_inputs = vec![Fp::from(intersection_size)];
let proof = generate_proof(¶ms, &pk, circuit, &public_inputs)
.map_err(|e| format!("Proof failed: {:?}", e))?;
// Verify proof
verify_proof(¶ms, &vk, &proof, &public_inputs)
.map_err(|e| format!("Verification failed: {:?}", e))?;
println!("Proved intersection size: {}", intersection_size);
Ok(())
}
See examples/ for more usage patterns.
The PSI circuit uses a comparison matrix approach:
| Set Size (n×n) | Proof Gen | Verification | Proof Size |
|---|---|---|---|
| 4×4 | ~800ms | ~120ms | ~3KB |
| 8×8 | ~1.5s | ~140ms | ~3KB |
| 16×16 | ~3.2s | ~180ms | ~3KB |
| 32×32 (max) | ~12s | ~250ms | ~3KB |
Run the full test suite:
cargo test
Tests include:
Generate performance reports:
cargo bench
Criterion outputs HTML reports to target/criterion/
Problem: Proving multiple PSI instances (e.g., 10 pairs of sets) requires 10 separate proofs.
Solution: Use proof recursion to aggregate multiple PSI proofs into one:
Benefits:
Implementation:
Built with: