A passport scan gets copied more often than it gets checked. A bank takes one, an exchange takes one, a landlord takes one, and each copy outlives the reason it was collected. Most of those checks are really asking one or two yes-or-no questions: old enough, resident here, is this you. A document answers all of them at once and then keeps answering them from someone else's database.
Zero-knowledge proofs change the shape of the exchange. You stop collecting documents and start accepting proofs that a specific statement about a document is true. The user keeps the passport. You learn "over 18" and nothing more. That sounds like a small change. It rewires what you store, what a breach can expose, and what your onboarding flow has to do.
Write down what you actually need to know. Not "verify identity," but the predicates: the user is over 18; the user holds a government-issued credential that has not been revoked; the user is resident in a permitted jurisdiction; this user has not already opened an account here.
Each of those is a boolean. A zero-knowledge proof lets the holder of a credential convince you that a boolean is true without showing you the underlying values. You learn the result. You do not learn the name, the birth date, the document number or the address.
The proof should answer your question, not enlarge your database.
That still leaves a design decision. What does the verifier learn, exactly? Usually the answer should be true or false, plus whatever the protocol unavoidably reveals: the issuer's identity, the credential type, the time of the proof. Anything beyond that needs a reason you can defend.
An issuer signs a credential: a government signs an attribute set, a bank signs an account-holder attestation, an employer signs an employment claim. The holder stores that credential somewhere they control. The verifier, which is you, checks a proof derived from it. You are no longer judging whether a paper document looks genuine. You are deciding which issuers you accept and whether a cryptographic signature chain is valid. That is a cleaner problem, but it means your integration depends on issuers existing for the attributes you need.
Most implementations combine a handful of pieces. The exact stack depends on your issuers and your latency budget.
Client-side proving. The proof is generated on the user's device and only the proof travels to your server, so private data never leaves the phone. This is the strongest privacy posture and the slowest, especially on older hardware.
Hosted proving. A service generates proofs on the user's behalf. The experience is smooth and the trust model is worse, because that service sees the witness. Reasonable for low-sensitivity predicates, poor for anything you would not want a vendor to hold.
Hybrid. The issuer issues into a wallet, the wallet proves, your backend verifies. Verification is cheap compared with proving, so a modest server handles a lot of traffic while the expensive step stays on the user's phone. Budget a few seconds and show progress rather than a frozen screen.
Reliable today: age thresholds, jurisdiction membership, credential validity and expiry, institutional affiliation, uniqueness within your service, and account or balance thresholds with careful design.
Needs extra machinery or caution:
Data minimisation helps, but it does not replace your obligations. Many jurisdictions require identity records to be retained for a set period, and a proof result may not satisfy that. Some rules expect you to be able to identify a customer again on request. Before you assume a proof is enough, get advice from qualified counsel in each jurisdiction you operate in.
Two engineering risks sit alongside the legal ones. Circuits can be wrong: a buggy predicate circuit can leak parts of the witness or accept a false statement, so use audited libraries and get custom circuits reviewed independently. And your verifier is now a security boundary. If it logs the raw credential or the witness, you have rebuilt the database you were trying to avoid.
Pick the highest-volume, lowest-sensitivity check you run. Age verification on a signup form is the classic starting point; jurisdiction eligibility is another. Run the proof path alongside your existing review, keep the fallback, and measure how many users finish it.
Expect friction in the first month. Proving takes seconds, users need to understand what they are proving, and support teams need an answer for "why can't I just upload my ID." The answer is a good one: the stored copy of that ID is the thing that hurts you when it leaks. Once a single predicate works, adding residency or uniqueness is mostly a matter of circuits and issuer relationships rather than new architecture.
Photo: SookyungAn / Pixabay