AnonCreds 1.0 Cryptographic Primitives
Overview
AnonCreds (Anonymous Credentials) is a Zero-Knowledge Proof (ZKP) based verifiable credential system built on CL Signatures (Camenisch-Lysyanskaya). This document covers the cryptographic primitives and sequence flows for credential issuance and verification.
Key Features: - Selective Disclosure - Predicates (prove conditions without revealing values) - Unlinkability (presentations cannot be correlated) - Efficient Revocation
Cryptographic Primitives Summary
| Primitive | Algorithm/Curve | Purpose |
|---|---|---|
| Digital Signatures | CL Signatures (RSA-2048) | Sign credential attributes |
| Key Generation | Sophie Germain / Safe Primes | Generate secure RSA modulus |
| Commitments | Pedersen-style | Blind link secret & attributes |
| Hash Function | SHA-256 | Encode attributes, Fiat-Shamir |
| Accumulator | CKS variant on BN254 | Revocation status |
| Pairing | Ate pairing on BN254 | Non-revocation proofs |
| ZK Proofs | Schnorr-style + Fiat-Shamir | Prove knowledge without revealing |
| Predicates | Four-squares decomposition | Range proofs (≥, ≤, etc.) |
1. CL Signatures (Camenisch-Lysyanskaya)
CL Signatures are a form of digital signature invented by Jan Camenisch and Anna Lysyanskaya (papers: 2001, 2003, 2004). They provide two key protocols:
-
Blind Signing Protocol: A signer can issue a signature to a user without learning all the messages being signed or the complete signature.
-
Proof of Knowledge Protocol: The signature owner can prove they have a signature on many messages without revealing the signature and only a (possibly empty) subset of the messages.
Historical Context
- 1983: David Chaum publishes blind signatures
- 2001: Camenisch & Lysyanskaya publish CL Signatures
- 2016: Hyperledger Indy created
- 2017: AnonCreds implementation begins
2. RSA Groups & Key Generation
Credential Definition Key Generation
The Credential Definition uses RSA-2048 with Sophie Germain and Safe primes:
- Generate random 1536-bit primes
p,qsuch thatp'andq'are primes too - Where
p = 2p' + 1andq = 2q' + 1(Safe primes) - Compute
n = p · q - Compute random values
Rᵢfor each attribute - Compute
s(random quadratic residue) andz
Public Key: (n, s, z, {Rᵢ})
Private Key: (p, q)
All integers in the Credential Definition are 2048-bit integers (617 decimal digits).
3. Blinded Secrets & Commitments
Blinded Secret
A cryptographic technique where a secret value is blinded before sharing, allowing later proof of knowledge without revealing the value.
Blinding Factor
A random BigNumber selected from integers up to the RSA group order n. Generated by the holder to blind their link secret during credential issuance.
Blinding Formula:
Where:
- v' = blinding factor
- m_link_secret = the holder's link secret
- S, R_link_secret = public keys from Credential Definition
4. Revocation: Cryptographic Accumulators
Accumulator Scheme
The revocation scheme uses a pairing-based dynamic accumulator (CKS variant) with Type 3 elliptic curve pairing on BN254 curve (254-bit prime).
Pairing Groups
- G1: Subgroup of E1 (more compact representation)
- G2: Subgroup of E2
- GT: Subgroup of multiplicative group of field extension
- e: G1 × G2 → GT (non-degenerate bilinear map)
Public Revocation Keys
| Key | Description |
|---|---|
g |
Generator for G1 |
g_dash |
Generator for G2 |
h, h0, h1, h2, htilde |
Random points in G1 |
h_cap, u, y |
Points in G2 |
pk |
Public key: g^sk |
Private Revocation Keys
| Key | Description |
|---|---|
x |
Integer modulo group order |
sk |
Integer modulo group order |
gamma |
Secret for accumulator construction |
Tails File
Array of G2 curve points, one per credential in the registry:
5. Link Secret (Master Secret)
A unique identifier known only to the holder used to:
- Bind credentials to the holder
- Demonstrate that all credentials in a presentation belong to the same holder
- Enable multi-credential presentations
During issuance and presentation, the link secret is blinded with a blinding factor and a correctness proof is provided.
6. Zero-Knowledge Proofs
Proof Types
| Proof Type | Purpose |
|---|---|
| Blinded Secrets Correctness Proof | Prove blinded secret was produced correctly |
| Signature Correctness Proof | Prove signature validity without revealing |
| Non-Revocation Proof | Prove credential not revoked without revealing index |
| Predicate Proof | Prove attribute satisfies condition |
ZKP Capabilities
- Prove knowledge of link secret
- Share data from multiple credentials without revealing correlatable identifiers
- Selective disclosure of necessary claims
- Predicates to minimize shared data
- Prove credentials not revoked without unique identifiers
7. Predicates
A zero-knowledge proof predicate is a boolean assertion (<=, <, >, >=) about an integer claim value without disclosing the value.
Example: Prove age >= 21 without revealing actual age.
Method: Four-squares decomposition to prove Δ = attribute - threshold >= 0
Sequence Diagrams
Full Lifecycle Overview
sequenceDiagram
autonumber
participant VDR as Verifiable Data<br/>Registry
participant I as Issuer
participant H as Holder
participant V as Verifier
Note over VDR, V: ══════════════ SETUP PHASE ══════════════
rect rgb(200, 230, 255)
I->>VDR: 1. Publish Schema
I->>I: Generate CL key pairs (RSA-2048)
I->>VDR: 2. Publish Credential Definition
opt Revocation Enabled
I->>I: Generate accumulator keys (BN254)
I->>VDR: 3. Publish RevReg + Tails File
end
H->>H: 4. Generate & store Link Secret
end
Note over VDR, V: ══════════════ ISSUANCE PHASE ══════════════
rect rgb(200, 255, 200)
I->>H: 5. Credential Offer<br/>(cred_def_id, key_correctness_proof, nonce)
H->>VDR: 6. Get Credential Definition
VDR-->>H: Public keys (n, s, z, {Rᵢ})
H->>H: 7. Blind link_secret with blinding factor
H->>I: 8. Credential Request<br/>(blinded_ms, correctness_proof, nonce)
I->>I: 9. Verify request & sign credential
Note right of I: A = (Z / S^v · ∏Rᵢ^mᵢ)^(1/e) mod n
I->>H: 10. Issue Credential<br/>(signature, values, witness)
H->>H: 11. Unblind & verify signature
H->>H: 12. Store credential
end
Note over VDR, V: ══════════════ PRESENTATION PHASE ══════════════
rect rgb(255, 230, 200)
V->>H: 13. Presentation Request<br/>(requested_attrs, predicates, nonce)
H->>VDR: 14. Fetch CredDef, Schema, RevReg
VDR-->>H: Public verification data
H->>H: 15. Generate ZK Proof
Note right of H: • Randomize signature<br/>• Blind unrevealed attrs<br/>• Predicate proofs (Δ ≥ 0)<br/>• Non-revocation proof<br/>• Link secret binding
H->>V: 16. Verifiable Presentation<br/>(revealed_attrs, proofs, identifiers)
end
Note over VDR, V: ══════════════ VERIFICATION PHASE ══════════════
rect rgb(255, 200, 200)
V->>VDR: 17. Fetch CredDef, Schema, RevReg
VDR-->>V: Public verification data
V->>V: 18. Verify ZK Proof
Note right of V: • Verify encoding<br/>• Verify signature proof<br/>• Verify predicates<br/>• Verify non-revocation<br/>• Verify link_secret binding
alt Valid
V->>V: ✓ Accept
else Invalid
V->>V: ✗ Reject
end
end
Note over VDR, V: ══════════════ REVOCATION (Optional) ══════════════
rect rgb(255, 255, 200)
opt Issuer Revokes Credential
I->>I: Update accumulator (remove index)
I->>VDR: 19. Publish new Revocation Status List
Note right of VDR: Holder can no longer<br/>generate valid NRP
end
end
Detailed Credential Issuance
sequenceDiagram
autonumber
participant VDR as Verifiable Data Registry
participant Issuer
participant Holder
Note over VDR, Holder: === SETUP PHASE ===
rect rgb(230, 245, 255)
Note over VDR, Issuer: Schema & Credential Definition Setup
Issuer->>VDR: Publish Schema (name, version, attributes)
VDR-->>Issuer: Schema ID
Note right of Issuer: Generate key pairs:<br/>- RSA primes p, q (1536-bit)<br/>- Compute n = p·q<br/>- Generate Rᵢ for each attribute<br/>- Compute s, z values
Issuer->>VDR: Publish Credential Definition<br/>(public keys: n, s, z, {Rᵢ})
VDR-->>Issuer: Credential Definition ID
opt If Revocation Enabled
Note right of Issuer: Generate revocation keys:<br/>- BN254 curve points<br/>- Accumulator keys (pk, y)<br/>- Private keys (x, sk, γ)
Issuer->>VDR: Publish Revocation Registry Definition
Issuer->>VDR: Publish Initial Revocation Status List
Note right of Issuer: Generate & publish Tails File<br/>(array of G2 curve points)
end
end
rect rgb(255, 245, 230)
Note over Holder: Holder Setup
Note right of Holder: Generate Link Secret<br/>(random unique identifier)<br/>Store securely
end
Note over VDR, Holder: === ISSUANCE PHASE ===
rect rgb(230, 255, 230)
Note over Issuer, Holder: Credential Offer
Note right of Issuer: Create Credential Offer:<br/>- schema_id<br/>- cred_def_id<br/>- nonce (random)<br/>- key_correctness_proof
Issuer->>Holder: Credential Offer
Note right of Holder: Verify key_correctness_proof<br/>using Credential Definition
end
rect rgb(255, 230, 255)
Note over Issuer, Holder: Credential Request
Holder->>VDR: Request Credential Definition
VDR-->>Holder: Credential Definition (public keys)
Note right of Holder: Blind the Link Secret:<br/>1. Generate blinding factor v'<br/>2. U = S^v' · R_ms^m_ms mod n<br/>3. Create correctness proof
Holder->>Issuer: Credential Request<br/>(entropy, cred_def_id, blinded_ms,<br/>correctness_proof, nonce)
Note right of Issuer: Verify blinded_ms_correctness_proof
end
rect rgb(255, 255, 220)
Note over Issuer, Holder: Credential Issuance
Note right of Issuer: Encode attributes (SHA-256)<br/>Generate signature:<br/>1. Random e (prime), v''<br/>2. Compute m₂ (credential context)<br/>3. A = (Z / S^v · ∏Rᵢ^mᵢ)^(1/e)<br/>4. signature_correctness_proof
opt If Revocable
Note right of Issuer: Update accumulator<br/>Generate witness<br/>Create r_credential
end
Issuer->>Holder: Credential<br/>(values, signature, proofs, witness)
end
rect rgb(220, 255, 255)
Note over Holder: Credential Processing
Note right of Holder: 1. Verify signature_correctness_proof<br/>2. Remove blinding: v = v'' + v'<br/>3. Verify final signature<br/>4. Store credential securely
end
Detailed Presentation & Verification
sequenceDiagram
autonumber
participant VDR as Verifiable Data Registry
participant Holder
participant Verifier
Note over VDR, Verifier: === PRESENTATION & VERIFICATION ===
rect rgb(255, 240, 230)
Note over Holder, Verifier: Presentation Request
Note right of Verifier: Create Request:<br/>- requested_attributes<br/>- requested_predicates<br/>- non_revoked interval<br/>- nonce
Verifier->>Holder: Presentation Request
end
rect rgb(230, 255, 240)
Note over VDR, Holder: Fetch Public Data
Holder->>VDR: Fetch CredDef, Schema
VDR-->>Holder: Public verification data
opt Non-Revocation Required
Holder->>VDR: Fetch RevReg + Status List
VDR-->>Holder: Accumulator data
Note right of Holder: Load Tails File
end
end
rect rgb(240, 230, 255)
Note over Holder: Generate Zero-Knowledge Proof
Note right of Holder: 1. RANDOMIZE SIGNATURE<br/> A' = A · S^r (unlinkable)
Note right of Holder: 2. PRIMARY PROOF<br/> - Knowledge of (A, e, v)<br/> - Knowledge of link_secret<br/> - Unrevealed attributes
Note right of Holder: 3. PREDICATE PROOFS<br/> Δ = attr - threshold<br/> Prove Δ ≥ 0 (four squares)
opt Non-Revocation
Note right of Holder: 4. NON-REVOCATION PROOF<br/> Pairing-based ZKP on BN254
end
Note right of Holder: 5. FIAT-SHAMIR<br/> c = H(nonce || commitments)<br/> responses = random - c·secrets
end
rect rgb(255, 255, 220)
Holder->>Verifier: Verifiable Presentation<br/>{revealed_attrs, proofs, identifiers}
end
rect rgb(230, 245, 255)
Note over VDR, Verifier: Fetch Verification Data
Verifier->>VDR: Fetch CredDef, Schema, RevReg
VDR-->>Verifier: Public keys + Accumulator
end
rect rgb(220, 255, 220)
Note over Verifier: Verify Proof
Note right of Verifier: 1. Verify structure<br/>2. Verify encoding (SHA-256)<br/>3. Verify primary proof<br/>4. Verify predicates<br/>5. Verify non-revocation<br/>6. Verify link_secret binding
alt All Valid
Note over Verifier: ✓ ACCEPT
else Any Invalid
Note over Verifier: ✗ REJECT
end
end
Key Algorithms
Credential Signature Generation
Where:
- Z, S, Rᵢ = public keys from Credential Definition
- v = random value
- mᵢ = encoded attribute values
- e = random prime
- n = RSA modulus
Signature Verification
Verify that:
Attribute Encoding (SHA-256)
- Keep integers as-is
- Convert string integers to integers
- For other types:
- Convert to string (use "None" for null)
- Encode via UTF-8 to bytes
- Apply SHA-256
- Convert digest bytes (big-endian) to integer
- Stringify as decimal
Data Structures
Schema
{
"issuerId": "did:example:issuer",
"name": "Example Schema",
"version": "1.0.0",
"attrNames": ["name", "age", "birthdate"]
}
Credential Definition
{
"issuerId": "did:example:issuer",
"schemaId": "did:example:schema/1.0.0",
"type": "CL",
"tag": "default",
"value": {
"primary": {
"n": "779...397",
"s": "750...893",
"z": "632...005",
"r": {
"name": "294...298",
"age": "533...284",
"link_secret": "521...922"
},
"rctxt": "774...977"
},
"revocation": {
"g": "1 154...813 1 11C...D0D 2 095..8A8",
"g_dash": "1 1F0...000",
"h": "1 131...8A8",
"pk": "1 0E7...8A8",
"y": "1 068...000"
}
}
}
Credential
{
"schema_id": "did:example:schema/1.0.0",
"cred_def_id": "did:example:creddef/1.0.0",
"values": {
"name": {
"raw": "Alice",
"encoded": "113...335"
},
"age": {
"raw": "25",
"encoded": "25"
}
},
"signature": {
"p_credential": {
"m_2": "992...312",
"a": "548...252",
"e": "259...199",
"v": "977...597"
}
},
"signature_correctness_proof": {
"se": "898...935",
"c": "935...598"
}
}
Quick Reference: Key Flows
Issuance Flow (10 steps)
- Issuer → VDR: Publish Schema & CredDef
- Holder: Generate Link Secret
- Issuer → Holder: Credential Offer (nonce, key_correctness_proof)
- Holder: Verify offer, blind link_secret with factor v'
- Holder → Issuer: Credential Request (blinded_ms, correctness_proof)
- Issuer: Sign credential
A = (Z / S^v · ∏Rᵢ^mᵢ)^(1/e) mod n - Issuer → Holder: Credential (signature, values, witness)
- Holder: Unblind signature (
v = v'' + v'), verify, store
Verification Flow (8 steps)
- Verifier → Holder: Presentation Request (attrs, predicates, nonce)
- Holder: Fetch CredDef, Schema, RevReg from VDR
- Holder: Randomize signature
A' = A · S^r - Holder: Generate ZKP (signature proof, predicates, NRP)
- Holder → Verifier: Verifiable Presentation
- Verifier: Fetch public keys from VDR
- Verifier: Verify all proofs
- Verifier: Accept or Reject
References
- Official Specification: https://hyperledger.github.io/anoncreds-spec/
- Rust Implementation: https://github.com/hyperledger/anoncreds-rs
- CL Signatures Library: https://github.com/hyperledger/anoncreds-clsignatures-rs
- Specification Repository: https://github.com/hyperledger/anoncreds-spec
- AnonCreds Whitepaper: Anonymous credentials with type-3 revocation
Original Papers
- Camenisch, J., & Lysyanskaya, A. (2001). Efficient non-transferable anonymous multi-show credential system with optional anonymity revocation. EUROCRYPT 2001.
- Camenisch, J., & Lysyanskaya, A. (2002). Dynamic accumulators and application to efficient revocation of anonymous credentials. CRYPTO 2002.
- Camenisch, J., & Lysyanskaya, A. (2003). A signature scheme with efficient protocols. SCN 2002.
- Camenisch, J., & Lysyanskaya, A. (2004). Signature schemes and anonymous credentials from bilinear maps. CRYPTO 2004.