Passkeys (WebAuthn/FIDO2) are the first authentication mechanism that actually replaced passwords at scale. Zero-knowledge proofs (ZKPs) promise privacy-preserving authorization and identity. Naturally, engineers ask:
Can we combine real passkeys FaceID / TouchID / fingerprint-backed keys with zero-knowledge proofs to get passwordless and privacy-preserving authentication?
The answer is: yes, partially today; fully only with browser changes.
This article designs a realistic, implementable architecture, explains what browsers would need to expose, and ends with today's hard limitations.
No hype. Just constraints, primitives, and tradeoffs.
A passkey is not "biometrics + crypto" in the abstract sense. It is a hardware-backed asymmetric key with strict guarantees:
The private key lives in:
- Secure Enclave (Apple)
- TPM (Windows)
- StrongBox / TEE (Android)
The private key:
- Is non-extractable
- Is not directly addressable by applications
- Signing is allowed only via WebAuthn APIs
Every signature is:
- Origin-bound (domain + RP ID)
- Challenge-based
- User-verified (biometric / PIN)
This model is enforced by browsers and OS vendors like Google and Apple for phishing resistance and account isolation.
This matters because ZK systems want programmable access to secrets, while passkeys explicitly deny that.
Zero-knowledge proof systems assume:
- Deterministic computation
- Full access to private inputs
- Repeatable execution inside a prover
Passkeys provide:
- A black-box signing oracle
- No access to private key material
- No control over nonce generation
- No guarantee of deterministic signatures
This creates a fundamental constraint:
You cannot directly "put a passkey inside a ZK circuit."
Any architecture that claims otherwise is either:
- Ignoring Secure Enclave constraints, or
- Assuming browser changes that do not exist today
So the design goal becomes:
Use passkeys as a trust anchor, not as a ZK witness.
The only architecture that works today respects WebAuthn's boundaries.
- Passkeys authenticate who may receive a credential
- ZK proves what that credential allows
- Authentication and authorization are decoupled
- Passkeys never appear inside the ZK circuit
Client:
- Browser with WebAuthn
- ZK prover (WASM / native)
Server:
- WebAuthn verifier
- Credential issuer
- Public verification keys
ZK System:
- Circuits for attribute proofs
- Nullifier logic
- Verification logic (off-chain or on-chain)
- User registers a passkey with the website
- Server stores:
- WebAuthn public key
- Credential commitment root (Merkle root or hash)
- Server associates the passkey with a credential issuance policy
At this stage:
- No ZK proof exists
- No attributes are exposed
- The passkey is just an authentication primitive
- User authenticates using WebAuthn (biometric prompt)
- Server verifies:
- Signature
- Origin
- User verification flag
- Server issues a ZK credential, e.g.:
- Membership token
- Age bucket
- Subscription tier
- Eligibility flag
This credential is:
- Bound to a secret known only to the user
- Stored client-side
- Represented as commitments (not plaintext)
The passkey is now out of the picture.
Later, the user proves statements such as:
- "I am a valid member"
- "I am over 18"
- "I have not exceeded my quota"
- "I have not voted before"
Using ZK proofs that reveal:
- No identity
- No passkey
- No stable user identifier
Optionally:
- Nullifiers prevent double-use
- Proofs can be verified on-chain
This is the only scalable model today.
Let's be explicit.
- WebAuthn commonly uses ECDSA P-256
- ECDSA verification in ZK:
- Large circuits
- Slow proving
- High memory usage
- Even optimized circuits are unsuitable for UX-critical login flows
- Secure Enclaves choose nonces internally
- ZK circuits require deterministic computation
- You cannot replay or recompute the same signature inside the prover
WebAuthn signatures bind:
- RP ID
- Origin
- Client data hash
This is a feature, but it means:
- Proofs are not transferable
- Cross-site ZK proofs are impossible by design
To truly merge passkeys and ZK, browsers would need new primitives, not hacks.
Browsers would need to expose something like:
A verifiable attestation:
- "A valid WebAuthn authentication occurred"
- Without revealing RP ID or public key
Signed by:
- Platform root key
- Device attestation key
This is fundamentally different from today's WebAuthn assertions.
A controlled mechanism where:
The enclave signs:
- A fixed-format message
- With deterministic nonce derivation
Scope-limited:
- Only for ZK usage
- Only for specific relying parties
This is controversial because it touches side-channel risk.
Instead of exporting keys, browsers could expose:
- Commitment to the passkey public key
- Commitment to attestation metadata
- Zero-knowledge verifiable statements like:
- "This key was generated in a Secure Enclave"
- "User verification occurred"
No raw cryptography leaves the device.
The cleanest long-term solution:
- Browsers act as credential issuers
- Passkeys unlock issuance
- ZK proofs consume credentials
- Authentication events are never revealed
This aligns far better with the WebAuthn security model.
Browser vendors treat authentication APIs as critical infrastructure.
Any new surface:
- Risks fingerprinting
- Risks side channels
- Risks cross-site correlation
ZK systems are still evolving, which makes vendors cautious.
- ZK proof generation is still slow on mobile
- Battery and thermal budgets matter
- Login must feel instant
- Passkeys succeeded because they removed friction. ZK risks adding it back.
Privacy-preserving authentication:
- Reduces tracking
- Breaks analytics
- Weakens centralized identity graphs
This is not aligned with most platform business models.
- ❌ Prove a Google / Apple passkey login inside a ZK circuit
- ❌ Generate portable ZK proofs from WebAuthn assertions
- ❌ Use passkeys directly for on-chain authorization
- ❌ Extract enclave-backed secrets for ZK use
- ✅ Use passkeys as a secure gate to issue ZK credentials
- ✅ Build anonymous, unlinkable authorization systems
- ✅ Combine WebAuthn with ZK without violating security models
- ✅ Achieve passwordless + privacy-preserving authorization
Passkeys and ZK are complementary, not composable primitives - yet.
The winning architecture is not:
"ZK replaces passkeys"
It is:
"Passkeys securely bootstrap ZK credentials"
Anything deeper requires:
- New browser APIs
- New standards
- Years of security review