Verifiable credentials with selective disclosure let users prove specific claims without revealing full credentials. ZK proofs make this cryptographically secure. This guide covers practical implementation.
Credential Structure
A verifiable credential contains:
- Claims: Statements about the subject (name, age, address, etc.)
- Issuer signature: Cryptographic proof of issuance
- Metadata: Issuance date, expiration, schema
{
"subject": "did:example:user123",
"claims": {
"name": "Alice Smith",
"birthDate": "1990-05-15",
"citizenship": "US",
"employerVerified": true
},
"issuer": "did:example:government",
"signature": "..."
}
Selective Disclosure
With ZK, users control what to reveal:
Disclosure Options
Full disclosure: Reveal claim value
Predicate proof: Prove condition (age > 18)
Existence proof: Prove claim exists
Non-disclosure: Prove credential valid without revealing claim
ZK Credential Proof
// Generate selective disclosure proof
const proof = await zkCredentials.prove({
credential: myCredential,
disclose: ['citizenship'], // Reveal this
predicates: [
{ claim: 'birthDate', predicate: 'olderThan', value: 21 }
],
hide: ['name', 'employerVerified'] // Don't reveal
});
// Verifier learns:
// - citizenship is "US" (disclosed)
// - user is over 21 (predicate satisfied)
// - credential is valid (signature verified)
// Verifier does NOT learn: name, exact birth date, employer status
Credential Schemas
Define credential structure for interoperability:
{
"type": "IdentityCredential",
"version": "1.0",
"claims": {
"name": { "type": "string", "required": true },
"birthDate": { "type": "date", "required": true },
"citizenship": { "type": "string", "required": false }
},
"predicates": {
"birthDate": ["olderThan", "youngerThan", "between"]
}
}
Issuer Implementation
Credential issuers must:
- Verify subject identity before issuance
- Sign credentials with ZK-compatible signatures
- Publish public keys for verification
- Maintain revocation registry
Verifier Implementation
Verifiers specify requirements:
// Verifier requests proof
const request = {
required: [
{ claim: 'citizenship', disclose: true },
{ claim: 'birthDate', predicate: 'olderThan', value: 18 }
],
trustedIssuers: ['did:example:government'],
purpose: "Age verification for alcohol purchase"
};
// User generates proof matching request
const proof = await wallet.generateProof(request);
// Verifier validates
const valid = await verifier.check(proof, request);
Privacy Considerations
- Issuer unlinkability: Issuers shouldn't learn when credentials are used
- Verifier unlinkability: Different verifiers can't correlate proofs
- Minimal disclosure: Only prove what's asked
Revocation
Handle credential revocation privately:
- Accumulators allow ZK membership proof
- User proves credential not revoked without revealing which credential
- Update accumulator when revoking
ZK credentials are the foundation of privacy-respecting identity. Users control their data while verifiers get cryptographic assurance.
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 →