Skip to content

System Design Document: ZKP-Powered Portable Credit Union Identity

Author: Viswa Kondoju Date: February 22, 2026 Version: 1.1 Status: Implemented — All core features built and tested


Table of Contents

  1. System Overview
  2. Architecture Overview
  3. Deep Dive: ZKP Credential Engine
  4. Deep Dive: Member Identity Layer
  5. Deep Dive: QR Code Encoding & Transport
  6. Deep Dive: Lender Verification Portal
  7. Deep Dive: Credit Union Core Banking Integration
  8. Deep Dive: Credential Lifecycle & Revocation
  9. Security Model
  10. Regulatory Alignment
  11. Technology Stack Recommendations
  12. Deployment Architecture
  13. Risk Register

1. System Overview

1.1 Problem Statement

Credit union members applying for financial products — auto loans, mortgages, credit cards, personal loans — are forced to repeatedly submit the same personal and financial information to every lender they approach. Each lender independently verifies this information through data aggregators that transmit raw personal data, creating privacy exposure, verification delays, and redundant effort.

No solution exists today that allows a credit union member to carry a verified, privacy-preserving financial identity across lending institutions without exposing raw personal data.

1.2 Solution

A platform that enables credit union members to generate zero-knowledge proof credentials from their existing credit union financial data, encode those credentials into time-limited QR codes, and share them with any participating lender. Lenders can cryptographically verify financial claims (income ranges, credit score tiers, membership standing) and auto-fill loan applications — all without ever receiving the member's raw data.

1.3 Core Actors

Actor Role
Member Credit union member who generates and controls their portable credential
Credit Union (Issuer) Source of truth for member financial data; attests to credential accuracy
Lender (Verifier) External institution that scans QR codes, verifies claims, and auto-fills applications
Platform Orchestration layer that manages credential generation, encoding, verification APIs, and trust registry

1.4 Key Design Principles

  • Member-controlled sharing: No data leaves the system without an explicit member action.
  • Data minimization: Lenders receive only the boolean truth of a claim (e.g., "income > $50K"), never the underlying value.
  • Offline-capable verification: QR-based sharing works in physical environments without real-time connectivity requirements for the member.
  • Standards-aligned: Built on W3C Verifiable Credentials and Decentralized Identifiers.
  • Regulatory-forward: Designed to align with CFPB Section 1033 open banking mandates.

2. Architecture Overview

2.1 High-Level System Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                          MEMBER MOBILE APP                              │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                  │
│  │  Credential   │  │   QR Code    │  │   Wallet &   │                  │
│  │  Request UI   │  │  Generator   │  │  History UI  │                  │
│  └──────┬───────┘  └──────┬───────┘  └──────────────┘                  │
│         │                 │                                             │
│  ┌──────┴─────────────────┴──────────────────────────┐                 │
│  │              Local Credential Store                 │                 │
│  │         (Encrypted, Device-Bound Keys)              │                 │
│  └─────────────────────┬───────────────────────────────┘                │
└────────────────────────┼────────────────────────────────────────────────┘
                         │ HTTPS/mTLS
┌─────────────────────────────────────────────────────────────────────────┐
│                        PLATFORM SERVICES                                │
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                  │
│  │     ZKP       │  │   Credential │  │    Trust      │                 │
│  │  Credential   │  │   Status &   │  │   Registry    │                 │
│  │   Engine      │  │  Revocation  │  │   Service     │                 │
│  └──────┬───────┘  └──────────────┘  └──────┬───────┘                  │
│         │                                    │                          │
│  ┌──────┴───────┐  ┌──────────────┐  ┌──────┴───────┐                  │
│  │   DID         │  │    API       │  │   Lender     │                  │
│  │  Resolver     │  │   Gateway    │  │  Onboarding  │                  │
│  └──────────────┘  └──────┬───────┘  └──────────────┘                  │
└────────────────────────────┼────────────────────────────────────────────┘
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
┌──────────────────┐ ┌─────────────┐ ┌─────────────────┐
│  CREDIT UNION     │ │   LENDER    │ │   LENDER        │
│  CORE BANKING     │ │  PORTAL     │ │  API CLIENT     │
│  (Symitar, DNA,   │ │  (Web App)  │ │  (Programmatic) │
│   KeyStone)       │ │             │ │                 │
└──────────────────┘ └─────────────┘ └─────────────────┘

2.2 Data Flow Summary

CREDENTIAL GENERATION:
  CU Core Banking → Platform (ZKP Engine) → Member App (Credential Store)

CREDENTIAL SHARING:
  Member App (QR Generator) → Physical/Digital QR → Lender Scanner

CREDENTIAL VERIFICATION:
  Lender Scanner → Platform (Verification API) → Trust Registry + Status List → Result

3. Deep Dive: ZKP Credential Engine

3.1 ZKP Scheme Selection

The system uses Groth16 zk-SNARKs as the primary proof system. This decision is driven by three constraints: QR code data capacity, verification speed in lending environments, and implementation maturity.

Property Groth16 PLONK zk-STARK Bulletproofs
Proof Size 260 bytes 868 bytes ~45 KB 576–674 bytes
Verification Time ~5 ms ~8 ms ~50 ms ~30 ms
Trusted Setup Per-circuit Universal None None
QR Feasibility Excellent Marginal Infeasible Good
Post-Quantum No No Yes No
Maturity Very High High Medium Medium

Why Groth16: At 260 bytes, a Groth16 proof fits comfortably within a QR code alongside metadata (issuer DID, credential schema, expiration timestamp). The proof + metadata total stays under 600 bytes after Base64 encoding, well within the 2,953-byte maximum of a Version 40 QR code. Verification takes approximately 5 milliseconds — fast enough for a real-time point-of-sale lending experience.

Trusted setup tradeoff: Groth16 requires a per-circuit trusted setup ceremony. For this system, "per-circuit" means one setup per claim type (income range, credit score tier, membership tenure, etc.). With a fixed and slowly-evolving set of claim types, the setup burden is manageable. The ceremony can be conducted as a multi-party computation (MPC) involving multiple credit unions to distribute trust.

Fallback consideration: If trusted setup concerns become a barrier to credit union adoption, Bulletproofs (576–674 bytes, no setup) are the fallback. They still fit within QR constraints, though with slightly slower verification.

3.2 Credential Predicate Design

The engine does not prove raw values. It proves predicates — boolean statements about a member's financial standing. This is the core privacy mechanism.

Predicate Category Example Predicates ZKP Circuit
Income annual_income > $50,000 Range proof against CU-attested income
annual_income ∈ [$75K, $100K] Range membership proof
Credit Score credit_tier ∈ {Excellent, Good} Set membership proof
credit_score >= 720 Threshold comparison proof
Account Standing membership_tenure > 24 months Duration comparison proof
account_status = Active Equality proof
Debt-to-Income DTI_ratio < 0.43 Ratio computation + comparison
Account Balance avg_balance_6mo > $10,000 Aggregation + comparison proof

3.3 Circuit Architecture

Each predicate type maps to a ZKP arithmetic circuit. The circuit takes private inputs (the member's actual financial data) and public inputs (the claim threshold and the credit union's attestation), and outputs a proof that the claim is true.

CIRCUIT: IncomeRangeProof

Private Inputs (witness — known only to member/CU):
  - actual_income: uint64
  - cu_attestation_signature: bytes

Public Inputs (known to verifier):
  - threshold: uint64  (e.g., 50000)
  - comparison_operator: enum  (GT, GTE, LT, LTE, EQ, RANGE)
  - cu_public_key: bytes
  - credential_expiry: timestamp
  - member_did: bytes

Constraints:
  1. Verify cu_attestation_signature over actual_income using cu_public_key
  2. Assert actual_income >= threshold  (for GTE operator)
  3. Assert credential_expiry > current_time

Output:
  - Groth16 proof (260 bytes)
  - Public input hash

3.4 Proof Generation Flow

Step 1: Member requests credential via mobile app
Step 2: Platform authenticates member (biometric + device key)
Step 3: Platform fetches current financial data from CU core banking API
Step 4: CU signs the data attestation (proving the data is real and current)
Step 5: ZKP Engine selects appropriate circuit for requested predicate
Step 6: Engine generates Groth16 proof with:
        - Private witness: actual financial values + CU signature
        - Public inputs: threshold, CU public key, expiry, member DID
Step 7: Engine packages proof into W3C Verifiable Credential format
Step 8: Credential returned to member's app and stored locally

3.5 Proof Generation Performance

Groth16 proof generation is computationally intensive and runs server-side on the platform. Expected benchmarks for the circuit types in this system:

Circuit Constraints Generation Time Proof Size
Income threshold ~10K ~1.5 seconds 260 bytes
Credit score tier ~8K ~1.2 seconds 260 bytes
Account tenure ~5K ~0.8 seconds 260 bytes
DTI ratio ~15K ~2.0 seconds 260 bytes
Composite (3 claims) ~30K ~3.5 seconds 260 bytes per claim

Generation runs on the platform's infrastructure, not the member's device. The member receives the completed proof within a few seconds of request.


4. Deep Dive: Member Identity Layer

4.1 Decentralized Identifier (DID) Architecture

Each member receives a Decentralized Identifier (DID) that serves as their portable cryptographic identity across the system. The DID is not tied to any single credit union — it belongs to the member.

DID Method Selection: did:key

The current implementation uses did:key as the DID method. This approach requires no external infrastructure — DIDs are self-resolving from the Ed25519 public key, making them ideal for MVP and offline-capable scenarios.

DID Method Infrastructure Required Resolution Suitability
did:key None Self-resolving Current implementation — zero infrastructure, Ed25519 native
did:web HTTPS endpoint DNS + HTTPS Future option — leverages existing web infrastructure, supports key rotation
did:ion Bitcoin blockchain Sidetree protocol Overkill for initial deployment
did:indy Hyperledger ledger Indy network Good fit if CUs already use Hyperledger

Example Member DID (current implementation):

did:key:z6MkewRxoJUAXJhRJtxq282dxU6KwBYYsuJf9mtheyco6Dbz

Implementation note: The MVP uses did:key with Ed25519 multicodec encoding. Migration to did:web is planned for production to support key rotation and institutional DID documents.

DID Document (resolved from https://identity.cuportable.com/members/m-7f3a9b2c/did.json):

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:web:identity.cuportable.com:members:m-7f3a9b2c",
  "verificationMethod": [{
    "id": "#key-1",
    "type": "JsonWebKey2020",
    "controller": "did:web:identity.cuportable.com:members:m-7f3a9b2c",
    "publicKeyJwk": { "kty": "EC", "crv": "BLS12-381-G2", ... }
  }],
  "authentication": ["#key-1"],
  "assertionMethod": ["#key-1"]
}

4.2 Key Management

Member keys are generated and stored on the member's device using hardware-backed secure enclaves (iOS Secure Enclave, Android StrongBox).

KEY HIERARCHY:

Device Root Key (hardware-backed, never exportable)
  └── Member DID Key Pair (BLS12-381)
       ├── Used for: credential binding, presentation signing
       └── Rotation: annual, or on device change

Backup & Recovery:
  - Encrypted key backup to member's credit union account
  - Recovery via CU identity verification + new device enrollment
  - Social recovery option: 2-of-3 trusted contacts (future)

4.3 Member Registration Flow

Step 1: Member downloads app and selects their credit union
Step 2: Member authenticates with their CU online banking credentials
        (OAuth2 flow — platform never sees the password)
Step 3: CU confirms member identity and returns member profile reference
Step 4: App generates DID key pair in device secure enclave
Step 5: Platform creates DID document and publishes to DID registry
Step 6: CU issues a "membership attestation" VC bound to the member's DID
Step 7: Member is now enrolled and can request financial credentials

5. Deep Dive: QR Code Encoding & Transport

5.1 QR Code Data Budget

A QR code's data capacity is the binding constraint on the credential transport format. The system targets QR Version 25–27 for optimal balance between data capacity and scanability.

QR Version Modules Byte Capacity (Level M) Scanability
25 117×117 1,853 bytes Good at arm's length
27 125×125 2,107 bytes Good at arm's length
33 149×149 2,701 bytes Requires closer scan
40 177×177 2,953 bytes Difficult to scan quickly

Error correction level M (15% recovery) is the target — it provides reasonable damage tolerance for printed or screen-displayed QR codes without sacrificing too much capacity.

5.2 Credential Payload Structure

The QR code encodes a Verifiable Presentation (VP) containing one or more Verifiable Credentials:

{
  "header": {
    "version": 1,
    "encoding": "base64url",
    "compression": "none",
    "created": 1740268800,
    "expires": 1740355200
  },
  "presentation": {
    "@context": ["https://www.w3.org/2018/credentials/v1"],
    "type": ["VerifiablePresentation"],
    "holder": "did:web:identity.cuportable.com:members:m-7f3a9b2c",
    "verifiableCredential": [{
      "issuer": "did:web:cu.firstfederal.org",
      "issuanceDate": "2026-02-22T00:00:00Z",
      "expirationDate": "2026-02-23T00:00:00Z",
      "credentialSubject": {
        "id": "did:web:identity.cuportable.com:members:m-7f3a9b2c",
        "claim": "annual_income_gte",
        "threshold": 75000,
        "currency": "USD"
      },
      "credentialStatus": {
        "type": "BitstringStatusListEntry",
        "statusListIndex": "4521",
        "statusListCredential": "https://status.cuportable.com/lists/firstfederal/1"
      },
      "proof": {
        "type": "Groth16Proof2026",
        "proofValue": "<base64url-encoded 260-byte Groth16 proof>",
        "verificationMethod": "did:web:cu.firstfederal.org#zkp-key-1"
      }
    }]
  },
  "presentationProof": "<base64url-encoded signature by holder DID>"
}

5.3 Size Budget Breakdown

Component Raw Size Base64url Size
Groth16 proof 260 bytes 347 bytes
Header + metadata ~120 bytes ~160 bytes
Credential subject (1 claim) ~150 bytes ~200 bytes
Issuer DID + status ~180 bytes ~240 bytes
Holder DID + presentation proof ~200 bytes ~267 bytes
Total (1 claim) ~910 bytes ~1,214 bytes
Total (3 claims) ~1,500 bytes ~2,000 bytes

A single-claim credential fits in QR Version 22 (Level M). A three-claim composite credential fits in QR Version 27 (Level M). Both are comfortably scannable.

5.4 QR Lifecycle

GENERATION (member app):
  1. Member selects which credentials to share
  2. App packages selected VCs into a Verifiable Presentation
  3. Member signs the presentation with their DID key
  4. App generates time-limited QR code (default: 24 hours)
  5. QR displayed on screen or saved for printing

SHARING:
  - In-person: Lender scans QR from member's phone screen
  - Digital: Member shares QR image via secure channel
  - Embedded: QR payload transmitted as deep link or API payload

EXPIRATION:
  - QR encodes an expiration timestamp
  - After expiration, verification always fails
  - Member generates a new QR for each sharing event (recommended)

6. Deep Dive: Lender Verification Portal

6.1 Verification Flow

When a lender scans a member's QR code, the verification process executes the following steps:

Step 1: DECODE
  - Parse QR payload
  - Validate header (version, encoding, expiration)
  - Extract Verifiable Presentation

Step 2: FRESHNESS CHECK
  - Verify credential has not expired (expirationDate > now)
  - Verify QR code has not expired (header.expires > now)
  - Reject if either timestamp has passed

Step 3: ISSUER AUTHENTICATION
  - Resolve issuer DID (e.g., did:web:cu.firstfederal.org)
  - Fetch issuer's DID Document
  - Verify issuer is in the Trust Registry (see 6.2)
  - Extract issuer's ZKP verification key

Step 4: ZKP PROOF VERIFICATION
  - Load the Groth16 verification key for the claim's circuit type
  - Extract public inputs (threshold, issuer key, expiry, member DID)
  - Run Groth16 verification algorithm
  - Result: VALID or INVALID (deterministic, no judgment)

Step 5: REVOCATION CHECK
  - Fetch the Bitstring Status List from the credential's statusListCredential URL
  - Check the bit at statusListIndex
  - If bit = 0: credential is active
  - If bit = 1: credential has been revoked

Step 6: HOLDER BINDING
  - Verify the presentation proof (holder's DID signature)
  - Confirms the person presenting the credential controls the DID

Step 7: RESULT
  - Return structured verification result to lender system
  - If all checks pass: release verified claim values for auto-fill

6.2 Trust Registry

The Trust Registry is the mechanism by which lenders know that an issuer (credit union) is legitimate. Without it, anyone could generate a fake credential from a fabricated "credit union."

TRUST REGISTRY ARCHITECTURE:

┌──────────────────────────────────────┐
│          TRUST REGISTRY              │
│                                      │
│  Maintained by: Platform operator    │
│  Updated: As CUs onboard/offboard   │
│                                      │
│  ┌────────────────────────────────┐  │
│  │  Registered Issuers:           │  │
│  │                                │  │
│  │  did:web:cu.firstfederal.org   │  │
│  │    → Name: First Federal CU    │  │
│  │    → NCUA Charter: #12345      │  │
│  │    → ZKP Verify Keys: [...]    │  │
│  │    → Status: Active            │  │
│  │                                │  │
│  │  did:web:cu.navyfcu.org        │  │
│  │    → Name: Navy Federal CU     │  │
│  │    → NCUA Charter: #67890      │  │
│  │    → ZKP Verify Keys: [...]    │  │
│  │    → Status: Active            │  │
│  └────────────────────────────────┘  │
└──────────────────────────────────────┘

The registry maps each issuer DID to a verified credit union identity (NCUA charter number) and their current ZKP verification keys. Lenders query this registry during Step 3 of verification.

6.3 Lender Integration Modes

Mode Integration Effort Use Case
Web Portal None — lender uses hosted portal Small lenders, occasional use
JavaScript SDK Low — embed widget in existing LOS Mid-size lenders with web-based loan origination
REST API Medium — integrate into backend systems Large lenders with custom workflows
Webhook Medium — receive verification events Lenders wanting async/batch processing

6.4 Auto-Fill Mapping

After successful verification, the lender's loan origination system receives a structured result that maps directly to application fields:

{
  "verificationId": "vrf-8a3b2c1d",
  "status": "VERIFIED",
  "timestamp": "2026-02-22T14:30:00Z",
  "holder": "did:web:identity.cuportable.com:members:m-7f3a9b2c",
  "issuer": {
    "did": "did:web:cu.firstfederal.org",
    "name": "First Federal Credit Union",
    "ncuaCharter": "12345"
  },
  "verifiedClaims": [
    {
      "claimType": "annual_income_gte",
      "threshold": 75000,
      "currency": "USD",
      "result": true,
      "autoFillMapping": {
        "field": "applicant.annual_income_range",
        "value": "$75,000+"
      }
    },
    {
      "claimType": "credit_score_tier",
      "tier": "Excellent",
      "result": true,
      "autoFillMapping": {
        "field": "applicant.credit_tier",
        "value": "Excellent (750+)"
      }
    }
  ],
  "credentialExpiry": "2026-02-23T00:00:00Z"
}

7. Deep Dive: Credit Union Core Banking Integration

7.1 Core Banking Landscape

The system must integrate with the major core banking platforms used by U.S. credit unions:

Platform Vendor Market Share API Type Integration Path
Symitar Jack Henry ~15.7% (699 CUs) SOAP (SymXchange) Vendor Integration Program (VIP)
DNA Fiserv ~25.9% (1,155 CUs) REST / Proprietary Fiserv Developer Portal
KeyStone Corelation ~2.9% (145 CUs) REST (KeyBridge) Corelation Certification
Spectrum Jack Henry ~12.0% (535 CUs) SOAP Jack Henry VIP

7.2 Data Elements Required

The ZKP Credential Engine needs access to specific member data elements from the core banking system to generate proofs. Critically, the platform processes these values only ephemerally — they are used as private inputs to the ZKP circuit and are never stored by the platform.

Data Element Source Field (Symitar) Used For
Annual Income Member record / payroll data Income range predicates
Credit Score Credit report pull / cached score Credit tier predicates
Account Open Date Account creation date Membership tenure predicates
Account Status Share/Loan status codes Account standing predicates
Monthly Debt Payments Loan payment summaries DTI ratio predicates
Average Balance (6mo) Transaction history aggregation Balance threshold predicates

7.3 Integration Architecture

┌──────────────────┐         ┌──────────────────┐         ┌──────────────────┐
│   CREDIT UNION   │         │    PLATFORM      │         │   MEMBER APP     │
│   CORE BANKING   │         │   ADAPTER LAYER  │         │                  │
│                  │         │                  │         │                  │
│  ┌────────────┐  │  SOAP/  │  ┌────────────┐  │  HTTPS  │                  │
│  │  Symitar   │──┼──REST──▶│  │  Symitar    │  │◀───────▶│  Credential      │
│  │  SymXchange│  │         │  │  Adapter    │  │         │  Request UI      │
│  └────────────┘  │         │  └─────┬──────┘  │         │                  │
│                  │         │        │         │         │                  │
│  ┌────────────┐  │  REST   │  ┌─────┴──────┐  │         │                  │
│  │  KeyStone  │──┼────────▶│  │  Normalized │  │         │                  │
│  │  KeyBridge │  │         │  │  Data Model │──┼────────▶│  ZKP Engine      │
│  └────────────┘  │         │  └─────┬──────┘  │         │                  │
│                  │         │        │         │         │                  │
│  ┌────────────┐  │  REST/  │  ┌─────┴──────┐  │         │                  │
│  │  DNA       │──┼──Prop──▶│  │  DNA        │  │         │                  │
│  │  (Fiserv)  │  │         │  │  Adapter    │  │         │                  │
│  └────────────┘  │         │  └────────────┘  │         │                  │
└──────────────────┘         └──────────────────┘         └──────────────────┘

The Adapter Layer normalizes data from different core banking APIs into a unified data model that the ZKP Engine consumes. Each adapter handles the protocol differences (SOAP vs REST), authentication mechanisms, and data field mappings specific to that core platform.

7.4 Data Flow Security

Member financial data is handled with strict ephemerality:

  1. Fetch: Adapter retrieves member data from core banking API (encrypted in transit via mTLS).
  2. Normalize: Data mapped to internal schema in memory.
  3. Attest: Credit union's HSM-hosted key signs the data attestation.
  4. Prove: ZKP Engine uses the data as private witness input to the circuit.
  5. Purge: Raw financial data is wiped from platform memory immediately after proof generation. The data is never written to disk, logged, or cached.

The platform can verifiably demonstrate this property through architecture audits and can adopt trusted execution environments (Intel SGX, AWS Nitro Enclaves) to provide hardware-enforced guarantees.


8. Deep Dive: Credential Lifecycle & Revocation

8.1 Credential States

  ┌──────────┐     generate     ┌──────────┐     expire     ┌──────────┐
  │          │ ──────────────▶  │          │ ─────────────▶  │          │
  │  NONE    │                  │  ACTIVE  │                 │ EXPIRED  │
  │          │                  │          │                 │          │
  └──────────┘                  └────┬─────┘                 └──────────┘
                                     │ revoke
                                ┌──────────┐
                                │          │
                                │ REVOKED  │
                                │          │
                                └──────────┘

8.2 Revocation Mechanism: W3C Bitstring Status List

The system uses Bitstring Status List v1.0 (W3C standard) for credential revocation.

How it works:

Each credit union (issuer) maintains a bitstring — a long binary array where each bit position corresponds to one issued credential. Bit value 0 means the credential is active; bit value 1 means it has been revoked.

BITSTRING STATUS LIST:

Credit Union: First Federal (did:web:cu.firstfederal.org)
Status List ID: https://status.cuportable.com/lists/firstfederal/1

Bit positions:
  [0] = 0 (active)     ← Credential for Member A (income claim)
  [1] = 0 (active)     ← Credential for Member B (credit tier claim)
  [2] = 1 (REVOKED)    ← Credential for Member C (account closed)
  [3] = 0 (active)     ← Credential for Member D (income claim)
  ...
  [131071] = 0          ← Minimum list size: 131,072 bits (16 KB)

Privacy property: The minimum list size of 131,072 entries ensures that a verifier checking one credential cannot determine how many total credentials the issuer has issued or which specific member is at a given index — the member is hidden within a large anonymity set.

8.3 Revocation Triggers

Trigger Source Action
Account closure CU core banking webhook Revoke all active credentials for member
Fraud flag CU fraud system Immediate revocation of all credentials
Data staleness Platform TTL policy Credential expires (not revoked, just expired)
Member request Member app Member can self-revoke any credential
Material change CU-defined rules Revoke if income drops below attested threshold

8.4 Revocation Propagation

REVOCATION FLOW:

Step 1: CU detects revocation event (e.g., account closure)
Step 2: CU sends revocation request to Platform via API
Step 3: Platform updates the bitstring at the credential's index
Step 4: Updated status list published to HTTPS endpoint
Step 5: Next lender verification fetches fresh status list
Step 6: Lender sees bit = 1 → verification fails

Propagation time: < 60 seconds (near real-time)
Caching policy: Lenders cache status lists for max 5 minutes

9. Security Model

9.1 Threat Model

Threat Attack Vector Mitigation
Credential forgery Attacker generates fake proof Groth16 soundness — computationally infeasible without valid witness
Replay attack Attacker reuses a captured QR code Time-limited expiration + holder binding (DID signature)
Issuer impersonation Attacker fakes a credit union Trust Registry verification; only registered CU DIDs are accepted
Data exfiltration from platform Attacker compromises platform servers Ephemeral data handling; raw data never stored. TEE enforcement optional.
Collusion (lender + platform) Lender and platform conspire to extract raw data ZKP mathematical guarantee: proof reveals nothing beyond the boolean claim
Quantum computing Future quantum computers break elliptic curve cryptography Groth16 is not post-quantum. Migration path: transition to zk-STARKs when QR capacity or alternative transport allows
Revocation delay Revoked credential used before status list update 5-minute max cache TTL. High-value transactions require real-time status check.
Device compromise Attacker gains access to member's phone Device-bound keys in secure enclave; biometric authentication for credential access

9.2 Cryptographic Assumptions

The system's security relies on the following assumptions:

  • Groth16 soundness: Based on the Knowledge of Exponent assumption in bilinear groups (BN254 or BLS12-381 curves).
  • BLS12-381 discrete log hardness: The curve used for DID keys and BBS+ signatures.
  • SHA-256 collision resistance: Used in credential hashing and status list integrity.
  • TLS 1.3 channel security: All platform-to-CU and platform-to-lender communications.

9.3 Compliance & Audit

  • SOC 2 Type II: Platform infrastructure will target SOC 2 certification.
  • PCI DSS: Not required — platform never handles payment card data.
  • GLBA Safeguards Rule: Applicable as a service provider to financial institutions.
  • NCUA Vendor Due Diligence: CUs will require standard vendor risk assessment; system design supports this.

10. Regulatory Alignment

10.1 CFPB Section 1033 (Open Banking)

Section 1033 of the Dodd-Frank Act mandates that financial institutions make consumer data available to consumers and their authorized third parties. The rule was finalized in October 2024, with implementation dates staggered by institution size:

  • Largest institutions ($850M+ assets): April 1, 2026
  • Mid-tier: April 1, 2028
  • Smaller institutions: April 1, 2030

As of 2025, the CFPB has reopened rulemaking for reconsideration of certain provisions (definition of "representative," fee assessment, data security requirements). The rule's core mandate — consumer-controlled data portability — remains intact.

Alignment: This system is a privacy-enhanced implementation of Section 1033's vision. Rather than sharing raw financial data (the Plaid/Finicity model), it shares cryptographically verified claims. This satisfies the consumer's right to port their financial standing while exceeding the rule's data security expectations.

10.2 ECOA / Reg B (Fair Lending)

The Equal Credit Opportunity Act prohibits discrimination in lending. ZKP credentials naturally support fair lending by design — a lender verifying "income > $75K" never sees the applicant's name, age, race, or any other protected characteristic unless the applicant explicitly includes it.

10.3 FCRA (Fair Credit Reporting)

The system must be carefully positioned relative to the Fair Credit Reporting Act. If the platform is deemed a "consumer reporting agency," it would face significant compliance obligations. The mitigation: the platform does not collect, store, or report consumer credit information. It generates mathematical proofs from data held by the credit union (the regulated entity) and passes only the proof to the lender. The credit union remains the data custodian.

10.4 State Privacy Laws

Emerging state privacy laws (California CCPA/CPRA, Virginia VCDPA, Colorado CPA) generally strengthen the case for this system. ZKP-based verification is inherently aligned with data minimization principles required by these laws.


11. Technology Stack Recommendations

11.1 ZKP Layer

Component Technology Rationale
Circuit language Circom 2.0 Mature, large community, Groth16-native
Proving system snarkjs / rapidsnark JavaScript + native Rust prover for performance
Curve BN254 or BLS12-381 Well-supported in snarkjs; BLS12-381 for BBS+ compatibility
Trusted setup snarkjs MPC Multi-party ceremony tooling built-in

11.2 Identity Layer

Component Technology Rationale
DID resolution Universal Resolver (DIF) Standard resolution for multiple DID methods
VC format W3C VC Data Model 2.0 Industry standard
Selective disclosure BBS+ (Data Integrity BBS Cryptosuites) W3C standardization path, unlinkable proofs
Key storage (mobile) iOS Secure Enclave / Android StrongBox Hardware-backed key protection

11.3 Platform Services

Component Technology Rationale
API Gateway Kong or AWS API Gateway Rate limiting, auth, lender key management
Backend services Rust (proving engine) + Node.js (API/orchestration) Rust for performance-critical ZKP generation; Node.js for rapid API development
Database PostgreSQL (metadata) + Redis (session/cache) Relational for audit trails; Redis for status list caching
Message queue Apache Kafka Async credential generation, revocation event propagation
Secrets management HashiCorp Vault or AWS KMS HSM-backed key storage for CU attestation keys

11.4 Mobile App

Component Technology Rationale
Framework React Native or Flutter Cross-platform; single codebase for iOS + Android
QR generation react-native-qrcode-svg or equivalent Client-side QR rendering
Local storage Encrypted SQLite (SQLCipher) Credential storage on device
Biometric auth Native biometric APIs Gate access to credential operations

12. Deployment Architecture

12.1 Cloud Infrastructure

┌─────────────────────────────────────────────────────────────────┐
│                     AWS / GCP / Azure                            │
│                                                                  │
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐           │
│  │   API        │   │   ZKP        │   │   Status    │           │
│  │   Gateway    │   │   Proving    │   │   List      │           │
│  │   (Kong)     │   │   Workers    │   │   CDN       │           │
│  │             │   │   (Rust)     │   │   (CloudFront)│          │
│  └──────┬──────┘   └──────┬──────┘   └──────┬──────┘           │
│         │                 │                  │                   │
│  ┌──────┴─────────────────┴──────────────────┴──────┐           │
│  │              Kubernetes Cluster                    │           │
│  │                                                   │           │
│  │  ┌───────────┐  ┌───────────┐  ┌───────────┐    │           │
│  │  │ Credential │  │   DID     │  │   Trust   │    │           │
│  │  │ Service    │  │  Resolver │  │  Registry │    │           │
│  │  └───────────┘  └───────────┘  └───────────┘    │           │
│  │                                                   │           │
│  │  ┌───────────┐  ┌───────────┐  ┌───────────┐    │           │
│  │  │ CU Adapter│  │  Kafka    │  │  Postgres │    │           │
│  │  │ Services  │  │  Cluster  │  │  + Redis  │    │           │
│  │  └───────────┘  └───────────┘  └───────────┘    │           │
│  └───────────────────────────────────────────────────┘           │
│                                                                  │
│  ┌─────────────────────────────────┐                             │
│  │   HSM / KMS                      │                            │
│  │   (CU attestation keys,          │                            │
│  │    platform signing keys)         │                            │
│  └─────────────────────────────────┘                             │
└─────────────────────────────────────────────────────────────────┘

12.2 Scaling Considerations

Component Scaling Strategy Target
ZKP Proving Workers Horizontal auto-scaling (CPU-bound) < 5 sec proof generation at P99
API Gateway Load-balanced replicas 10,000 verifications/minute
Status List CDN Edge-cached, 5-min TTL Global < 50ms latency
CU Adapters Per-CU dedicated worker pools Isolation between CU integrations

13. Risk Register

# Risk Likelihood Impact Mitigation
1 Credit unions slow to adopt due to integration complexity High High Start with CUs already on modern platforms (KeyStone). Offer managed adapter deployment.
2 Lenders don't trust ZKP verification as equivalent to raw data Medium High Pilot with progressive lenders. Publish audit results. Seek regulatory endorsement.
3 Patent rejection on obviousness grounds Medium Medium File provisional early. Collect pilot data showing unexpected technical results.
4 Groth16 trusted setup ceremony deters CU participation Low Medium Conduct multi-party ceremony with 5+ CUs. Publish ceremony artifacts. Offer Bulletproofs fallback.
5 Quantum computing threatens Groth16 security within 10 years Low High Monitor NIST post-quantum standards. Design migration path to zk-STARKs or lattice-based proofs.
6 Section 1033 rulemaking changes reduce regulatory tailwind Medium Low System value proposition stands independent of regulatory mandate. Privacy is a feature, not just compliance.
7 Competitor (Plaid, Mastercard) builds similar system Medium High Network effects from CU partnerships. Patent protection. First-mover advantage in credit union vertical.
8 Member adoption friction (app download, enrollment) Medium Medium Integrate with existing CU mobile banking apps via SDK. Reduce enrollment to 2 taps.


14. Implementation Status

14.1 What's Been Built (v1.1 — February 2026)

The following features from this design document have been fully implemented and tested:

Component Design Section Status Notes
Groth16 ZK-SNARKs 3.1 Implemented 5 Circom circuits (membership, employment, income, credit, account age)
W3C Verifiable Credentials 3.4 Implemented Real Ed25519 issuer signatures, JSON-LD format
DID:key Identity 4.1 Implemented Ed25519 multicodec, self-resolving DIDs
Holder Binding 6.1 Step 6 Implemented Member signs QR presentation with private key
7-Step Verification 6.1 Implemented All 7 steps: decode, freshness, issuer auth, ZKP, revocation, binding, result
Trust Registry 6.2 Implemented Public API, NCUA charter verification, issuer DID lookup
Auto-Fill Mapping 6.4 Implemented Maps verified claims to loan application fields
Bitstring Status List 8.2 Implemented W3C standard, 16KB (131,072 slots), instant revocation
Credential Lifecycle 8.1 Implemented Three-state: ACTIVE / EXPIRED / REVOKED
Lender API Key Auth 6.3 Implemented JWT Bearer + X-API-Key header (REST API mode)
AES-256-GCM Encryption 7.4 Implemented PII + private keys encrypted at rest
Poseidon Hash 3.3 Implemented Identity commitments via circomlibjs

14.2 Current Technology Stack (Implemented)

Component Design Recommendation (11.x) Actual Implementation
Circuit language Circom 2.0 Circom 2
Proving system snarkjs / rapidsnark snarkjs (Node.js subprocess)
Curve BN254 or BLS12-381 BN128 (alt_bn128)
DID method did:web did:key (Ed25519) — did:web planned for production
VC format W3C VC Data Model 2.0 W3C VC with Ed25519 proof + BitstringStatusListEntry
Backend Rust + Node.js Python FastAPI + Node.js (snarkjs subprocess)
Database PostgreSQL + Redis PostgreSQL 16 + Redis 7 (Docker Compose)
Frontend React Native / Flutter Next.js 15 (TypeScript, Tailwind CSS)
Key storage iOS Secure Enclave / Android StrongBox AES-256-GCM encrypted in database (web MVP)

14.3 Not Yet Implemented (Future Work)

Component Design Section Priority Notes
did:web migration 4.1 High Needed for key rotation and institutional DIDs
Mobile app (React Native) 11.4 High Current web app to be wrapped or rebuilt native
Core banking adapters (Symitar, DNA, KeyStone) 7.3 High Currently using direct database seeding
DTI ratio circuit 3.2 Medium Requires additional circuit design
Account balance circuit 3.2 Medium Requires transaction aggregation
BBS+ selective disclosure 11.2 Low Future enhancement for unlinkable proofs
Kubernetes deployment 12.1 Medium Currently Docker Compose for dev
Hardware-backed key storage 4.2 Medium Planned for mobile app release
Multi-party trusted setup ceremony 3.1 Medium Currently single-party dev setup
Webhook integration for lenders 6.3 Low REST API and web portal available

14.4 Database Schema (Implemented)

Seven tables in PostgreSQL:

  1. members — UUID, DID, encrypted PII, Ed25519 keys, encrypted private key, identity commitment
  2. credentials — Member FK, claim type, W3C VC JSON, Groth16 proof, credential_status (ACTIVE/EXPIRED/REVOKED), status_list_index
  3. qr_tokens — Member FK, cryptographic token, credential IDs, single_use, TTL, holder_signature, binding_payload
  4. lenders — UUID, name, email, password hash, api_key
  5. verification_logs — Lender FK, member DID, claims_verified, all_verified, issuer_info JSONB, failed_step
  6. trust_registry — DID, name, NCUA charter, public key hex, status
  7. status_lists — Issuer DID, list_index, 16KB bitstring, next_available_index, version

This document is a living technical specification. It should be updated as architectural decisions are finalized, pilot data is collected, and the regulatory landscape evolves.