BenchmarksStack Ranking
APIsPricingDocsWhite PaperTokenBlogAboutSecurity Demo
Log InGet API Key
Zero-Knowledge · 5 min read

ZK Age Verification:
Proving You're Over 18 Without Sharing Your Birthday

Implementing privacy-preserving age verification using zero-knowledge proofs.

67ns
Proof Verify
SHA3-256
Hash
PQ
Secure
Zero
Knowledge Leaked

Age verification is required for many services — alcohol, gambling, adult content, financial products, healthcare patient portals, and increasingly, social media platforms. Traditional methods expose birthdates unnecessarily, creating a growing honeypot of personally identifiable information. Zero-knowledge proofs enable proving "I am over X" without revealing when you were born, and they do it with cryptographic certainty rather than trust.

The Problem with Current Age Verification

Today's age verification landscape is fundamentally broken. Every service that gates content by age forces users to hand over far more information than is mathematically necessary. The result is a cascading privacy failure:

The Fundamental Question

Age verification is a yes/no question. Is this person 18 or older? The answer is one bit of information. Yet current systems collect hundreds of bytes of personal data to produce that single bit. ZK proofs close the gap — the verifier learns the answer and nothing else.

We need to verify age without collecting age. Zero-knowledge cryptography makes this possible.

ZK Age Verification Design

The circuit proves a simple predicate. A user holds a digitally signed credential — issued by a trusted authority like a government ID office or a bank — that contains their date of birth. The ZK proof demonstrates that the credential is valid and that the embedded birthdate satisfies the age requirement, without revealing the birthdate itself.

The Proof Statement

"I possess a valid credential containing a birthdate, and today's date minus that birthdate is greater than or equal to the required age."

The circuit operates on private inputs (the user's birthdate and credential signature) and public inputs (the current date and the minimum age threshold). The verifier never sees the private inputs — they only see the proof and the public parameters.

// Simplified age verification circuit
template AgeVerification() {
  signal private input birthYear;
  signal private input birthMonth;
  signal private input birthDay;
  signal private input credentialSignature;

  signal input currentYear;
  signal input currentMonth;
  signal input currentDay;
  signal input minimumAge;

  signal output isOldEnough;

  // Verify credential signature (not shown)
  // Calculate age from dates
  // Compare to minimum
  // Output 1 if old enough, 0 otherwise
}

Circuit Internals: Date Arithmetic in Constraints

Date arithmetic inside an arithmetic circuit is less straightforward than in conventional code. ZK circuits operate over finite fields, so calendar logic — leap years, variable month lengths, carry propagation from months to years — must be expressed as rank-1 constraint systems (R1CS) or PLONKish gates. The key insight is that for age verification, we only need a conservative comparison: it is acceptable to round down (a 17-year-364-day-old user may be told to try again tomorrow) but never acceptable to round up.

In practice, the circuit computes age = currentYear - birthYear, then adjusts downward by one if the birthday has not yet occurred in the current calendar year. This adjustment is a single constraint comparing (currentMonth, currentDay) against (birthMonth, birthDay) using lexicographic ordering.

Implementation Architecture

The end-to-end flow involves four distinct phases, each with clear trust boundaries:

  1. Credential Setup: User obtains a signed credential with their birthdate from a trusted issuer (government, bank, or certified identity provider). The credential is bound to the user's device key to prevent sharing.
  2. Proof Request: Service requests an age proof, providing the minimum age and a fresh nonce to prevent replay attacks.
  3. Proof Generation: User generates a ZK proof on-device. The private inputs never leave the user's hardware.
  4. Verification: Service verifies the proof and learns only pass/fail. No birthdate, no name, no ID number.
Post-Quantum Consideration

Classical ZK-SNARKs rely on elliptic curve pairings vulnerable to quantum attack. H33's ZKP pipeline uses SHA3-256 hash commitments — a symmetric primitive unaffected by Shor's algorithm — combined with Dilithium signatures for attestation. This makes the entire age verification flow post-quantum secure from day one.

Security Considerations

Credential Security

Proof Freshness

Selective Disclosure

Performance

ZK age verification is fast enough for real-time, inline verification — no loading spinners, no redirect flows:

Operation Latency Where
Proof generation 100-500 ms Client device (mobile/desktop)
Proof verification 10-50 ms Server-side
ZKP cache lookup (DashMap) 0.085 µs H33 in-process cache
Full H33 auth pipeline ~42 µs Per-auth (BFV FHE + ZKP + Dilithium)
Proof size 200-500 B Over the wire

At scale, H33's production pipeline sustains 2,172,518 authentications per second on a single Graviton4 instance, with ZKP verification handled by an in-process DashMap cache at 0.085 microseconds per lookup. Age proofs slot directly into this pipeline — the ZK verification step adds negligible overhead to the existing ~42 microsecond per-auth budget.

Integration Example

The H33 SDK abstracts the circuit compilation, witness generation, and proof serialization behind two function calls. The credential is stored client-side (typically in a secure enclave or keychain), and the proof is generated entirely on the user's device before being sent to your server.

// Client-side proof generation
const proof = await h33.zk.proveAge({
  credential: storedCredential,
  minimumAge: 21,
  verifierNonce: serviceProvidedNonce
});

// Server-side verification
const valid = await h33.zk.verifyAge(proof, {
  minimumAge: 21,
  nonce: serviceProvidedNonce
});

if (valid) {
  // Grant access - age confirmed, birthdate unknown
}

The verifierNonce is critical: it binds the proof to a specific session and prevents an attacker from capturing a valid proof and replaying it later. The nonce should be cryptographically random and expire within a short window.

Regulatory Landscape

Regulations are evolving toward privacy-preserving verification, and ZK proofs are increasingly recognized as a compliant mechanism:

"The best compliance strategy for age verification is to never collect the data you don't need. Zero-knowledge proofs make this architecturally enforceable, not just a policy promise."

ZK age verification protects user privacy while meeting regulatory requirements across jurisdictions. It eliminates the data liability that traditional age-gating creates, reduces breach surface area to zero personal data, and delivers verification results in milliseconds. As credential ecosystems like the EU Digital Identity Wallet mature, ZK-based attribute proofs will become the default — not the exception — for every age-gated service on the internet.

Ready to Go Quantum-Secure?

Start protecting your users with post-quantum authentication today. 1,000 free auths, no credit card required.

Get Free API Key →

Build With Post-Quantum Security

Enterprise-grade FHE, ZKP, and post-quantum cryptography. One API call. Sub-millisecond latency.

Get Free API Key → Read the Docs
Free tier · 10,000 API calls/month · No credit card required
Verify It Yourself