Skip to content

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:

  1. Blind Signing Protocol: A signer can issue a signature to a user without learning all the messages being signed or the complete signature.

  2. 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:

  1. Generate random 1536-bit primes p, q such that p' and q' are primes too
  2. Where p = 2p' + 1 and q = 2q' + 1 (Safe primes)
  3. Compute n = p · q
  4. Compute random values Rᵢ for each attribute
  5. Compute s (random quadratic residue) and z

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:

U = S^v' · R_link_secret^m_link_secret mod n

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:

tail[index] = g_dash * (gamma ^ index)


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

A = (Z / (S^v · R₁^m₁ · R₂^m₂ · ... · R_L^m_L))^(1/e) mod n

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:

A^e · S^v · ∏(Rᵢ^mᵢ) ≡ Z (mod n)

Attribute Encoding (SHA-256)

  1. Keep integers as-is
  2. Convert string integers to integers
  3. For other types:
  4. Convert to string (use "None" for null)
  5. Encode via UTF-8 to bytes
  6. Apply SHA-256
  7. Convert digest bytes (big-endian) to integer
  8. 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)

  1. Issuer → VDR: Publish Schema & CredDef
  2. Holder: Generate Link Secret
  3. Issuer → Holder: Credential Offer (nonce, key_correctness_proof)
  4. Holder: Verify offer, blind link_secret with factor v'
  5. Holder → Issuer: Credential Request (blinded_ms, correctness_proof)
  6. Issuer: Sign credential A = (Z / S^v · ∏Rᵢ^mᵢ)^(1/e) mod n
  7. Issuer → Holder: Credential (signature, values, witness)
  8. Holder: Unblind signature (v = v'' + v'), verify, store

Verification Flow (8 steps)

  1. Verifier → Holder: Presentation Request (attrs, predicates, nonce)
  2. Holder: Fetch CredDef, Schema, RevReg from VDR
  3. Holder: Randomize signature A' = A · S^r
  4. Holder: Generate ZKP (signature proof, predicates, NRP)
  5. Holder → Verifier: Verifiable Presentation
  6. Verifier: Fetch public keys from VDR
  7. Verifier: Verify all proofs
  8. Verifier: Accept or Reject

References


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.