Skip to content

ZK-Auth: Zero-Knowledge Identity Provider

Zero-knowledge cryptography changes what SSO delivers: instead of raw PII, relying parties receive cryptographic proofs. Verified answers without the underlying data, integrated via standard OAuth 2.1.

What changes when proofs replace PII

Standard SSO exchanges data for convenience. ZK-Auth exchanges proofs for the same convenience, without the liability.

Collection-based SSO

The data-for-convenience trade

  • Data liability: The relying party receives raw PII (emails, names, dates of birth) and inherits the obligation to secure, retain, and eventually delete it.
  • Correlation risk: The identity provider sees every service the user visits. The same identifier appears across all relying parties, enabling cross-service tracking.

Zentity ZK-Auth

Proof-based verification

  • No data liability: The relying party requests proof scopes (e.g., proof:age) and receives verified boolean flags. No passport stored, no PII retained.
  • No correlation: Pairwise pseudonyms per relying party. The identity provider cannot track which services the user visits. Cross-service linking is mathematically prevented.

What the protocol changes

Standard OAuth 2.1 and OIDC, but the default payload is fundamentally different: relying parties receive cryptographic proofs, not personal data.

Proofs first, data second

Collection-based identity flows deliver raw PII the moment a user logs in. Proof-based scopes (proof:age, proof:verification) answer the question without revealing the underlying data. A service learns "this person is over 21" without ever seeing a date of birth.

Encrypted computation

Compliance checks often require processing personal data (age thresholds, jurisdiction membership, and risk scoring). With fully homomorphic encryption (FHE), the server evaluates these policies directly on ciphertexts, returning an encrypted yes or no without ever decrypting the underlying attributes.

User-controlled vault

When a service legally needs actual personal data (e.g., a bank opening an account), the user unlocks their credential vault with their passkey, password, or wallet and approves exactly which fields to share. Zentity cannot release PII without the user actively participating in the consent and unlock flow.

Post-quantum delivery

When PII is shared, it is encrypted with ML-KEM-768 (NIST FIPS 203), a post-quantum key encapsulation standard. This protects against "harvest now, decrypt later" attacks where adversaries capture encrypted traffic today and break it with a future quantum computer. Compliance records often have multi-year retention requirements, so the encryption must outlast the retention period.

Integration at the protocol level, not the library level

The integration boundary is OAuth 2.1 and OpenID Connect, the same protocols your application already speaks. No SDK to install, no custom protocol to learn, no cryptography infrastructure to host. If you can add "Sign in with Google," you can add Zentity. This applies whether verification runs through Zentity directly or through your existing identity provider: the relying party receives the same privacy-preserving proofs via the same OIDC scopes.

No SDK to install

Any language, any framework, any OAuth library. Django, Rails, Spring, Express, Laravel, or a raw HTTP client. The protocol is the interface.

No cryptography code

Zero-knowledge proofs, FHE, and cryptographic commitments happen behind the protocol boundary. The relying party never touches a proof, a circuit, or a ciphertext.

No new infrastructure

No blockchain nodes, no relay servers, and no WebSocket connections. The relying party calls standard HTTPS endpoints and reads standard JWTs.

  • Standard OIDC flow

    Redirect to the authorization endpoint, receive an auth code, exchange it for a JWT. Dynamic Client Registration (RFC 7591) means the entire setup can be automated with a single POST request.

  • Scope-based proofs

    Scopes like proof:age or proof:verification return boolean verification flags. PII scopes like identity.name are requested only when regulation requires the actual data.

Open OAuth integration docs
example-integration.ts
// Step 1: Dynamic Client Registration (RFC 7591)
const reg = await fetch(
  "https://app.zentity.xyz/api/auth/oauth2/register",
  { method: "POST", body: JSON.stringify({
    client_name: "My App",
    redirect_uris: ["https://myapp.com/callback"],
    scope: "openid email proof:verification",
    grant_types: ["authorization_code"],
    token_endpoint_auth_method: "none",
  })})
);
const { client_id } = await reg.json();

// Step 2: Standard OIDC redirect with PKCE
// scope: openid email proof:verification
//   → returns boolean verification flags
// scope: identity.name identity.dob
//   → step-up: returns PII via id_token only

// Step 3: Userinfo returns proofs, not PII
{
  "sub": "usr_abc123",
  "email": "user@example.com",
  "verified": true,
  "verification_level": "full",
  "identity_bound": true
}