Two-party Private Set Intersection (PSI)
Problem: Two parties each have a list of identifiers (e.g., email addresses, customer IDs). They want to compute the intersection without revealing anything beyond it.
Solution
# Party A's set
cat > set_a.txt <<EOF
alice@example.com
bob@example.com
carol@example.com
EOF
# Party B's set
cat > set_b.txt <<EOF
bob@example.com
carol@example.com
dave@example.com
EOF
# Compute intersection (both parties see the result)
confium privacy psi \
--set-a set_a.txt \
--set-b set_b.txt \
--salt /dev/urandom
# bob@example.com
# carol@example.com
# Or just count:
confium privacy psi \
--set-a set_a.txt \
--set-b set_b.txt \
--salt /dev/urandom \
--cardinality-only
# 2
What’s happening
The current CLI implements hash-based PSI: each element is blinded via H(element || salt) and the intersection of blinded elements is computed. Both parties must use the same salt.
This is a semi-honest secure variant — it doesn’t defend against malicious parties that lie about their sets. For malicious-secure PSI (with ECDH blinding), use the confium-privacy crate’s psi::EcdhPsi API directly; the CLI variant is for demos and quick exploration.
Production caveats
- Salt handling: In production, the salt should be a session-specific random value agreed out-of-band. Using
/dev/urandomhere means the salt is fresh per invocation — both parties must coordinate. - Network transport: The CLI takes file inputs. Real deployments exchange blinded sets over a network (HTTP, gRPC, or WASM-over-WebSocket). The
confium-privacycrate exposes the primitive directly for that wiring. - Set size: Hash-based PSI works to ~10M elements; above that, switch to circuit-PSI or ECDH-PSI with bloom-filter optimization.