Skip to content

Zero-Knowledge Proof Architecture

This document describes the zero-knowledge (ZK) proof architecture in the Lucid platform, enabling auditors to generate verifiable proofs of their computations without revealing sensitive data.

Overview

Zero-knowledge proofs allow auditors to prove that they performed a computation correctly without revealing the private inputs to that computation. This is particularly useful for:

  1. Privacy-Preserving Verification: Customers can receive AI Passports without raw data leaving their TEE
  2. Scalable Verification: ZK proofs are compact and fast to verify
  3. Cryptographic Guarantees: Mathematical proof that the computation was performed correctly

Architecture Diagram

flowchart TD
    subgraph Auditor["Auditor (TEE)"]
        A1["Private Data<br/>(not sent)"] --> A2["ZK Circuit<br/>(WASM+ZKEY)"]
        A2 --> A3["ZK Proof<br/>(sent to verifier)"]
    end

    A3 -->|"Evidence with ZK Proof"| V1

    subgraph Verifier["Verifier"]
        V1["Circuit Registry<br/>(Database)"] --> V2["Verification Key<br/>(from DB)"]
        V2 --> V3["Verify Proof"]
    end

Components

1. Schema Types (lucid-schemas)

The lucid-schemas package provides the core ZK-related types:

  • ZKProofSystem: Enum of supported proof systems (groth16, plonk, fflonk, stark)
  • ZKProofSchema: Schema for serializing ZK proofs
  • ZKCircuitMetadata: Schema for circuit registration metadata

The Evidence schema now includes an optional zk_proof field:

class Evidence(BaseModel):
    # ... existing fields ...
    zk_proof: Optional[ZKProofSchema] = Field(
        None,
        description="Optional ZK proof attesting to the evidence computation."
    )

2. SDK ZK Module (lucid-sdk)

The lucid-sdk package includes a ZK module with the following components:

  • ZKCircuit: Loads circuit artifacts and generates/verifies proofs
  • ZKProof: Wraps raw proof data with serialization methods
  • ZKEvidence: Helper for creating Evidence with ZK proofs

Installation (available to alpha participants):

pip install lucid-sdk[zk]

3. Verifier Integration

The Lucid Verifier service provides ZK proof verification capabilities:

  • Circuit Registry: Database of registered circuit verification keys
  • Circuit Management API: REST endpoints for circuit registration and lookup
  • ZK Verification Service: Validates proofs during evidence submission

See the Verifier API Reference for endpoint documentation.

Supported Proof Systems

System Setup Proof Size Verification Use Case
Groth16 Trusted ~200 bytes ~3ms Production, frequent proofs
PLONK Universal ~1KB ~10ms Flexibility, no trusted setup
fflonk Universal ~500 bytes ~5ms Balance of size and setup
STARK None ~50KB ~50ms Maximum transparency

Workflow

Circuit Registration

Before proofs can be verified, the circuit must be registered with the verifier:

POST /v1/zk/circuits
{
  "circuit_id": "pii-detector-v1",
  "circuit_name": "PII Detection Circuit",
  "version": "1.0.0",
  "proof_system": "groth16",
  "verification_key": "<base64-encoded>",
  "num_public_inputs": 3,
  "auditor_id": "pii-auditor@sha256:abc123"
}

Proof Generation (Auditor)

  1. Auditor loads circuit artifacts (WASM, proving key, verification key)
  2. Auditor computes claims using private inputs
  3. Auditor generates ZK proof attesting to the computation
  4. Auditor creates Evidence with zk_proof field populated
from lucid_sdk.zk import ZKCircuit, ZKEvidence
from lucid_schemas import MeasurementType

circuit = ZKCircuit.from_files(
    circuit_id="pii-detector-v1",
    proving_key_path="./pii.zkey",
    verification_key_path="./pii_vkey.json",
    wasm_path="./pii.wasm",
)

zk_evidence = ZKEvidence(
    name="pii_detection",
    measurement_type=MeasurementType.quantity,
    circuit=circuit,
    auditor_id="pii-auditor@sha256:abc123",
)

evidence = zk_evidence.create_evidence(
    value={"detected": False, "score": 0.0},
    private_inputs={"input_hash": hash_of_text},
    public_inputs={"threshold": 50},
)

Proof Verification (Verifier)

When evidence is submitted to /v1/evidence/verify:

  1. Verifier checks if Evidence has zk_proof field
  2. If present, verifier looks up circuit verification key from registry
  3. Verifier validates proof using the verification key
  4. If valid, evidence is accepted; if invalid, request is rejected
# In submit_evidence():
if ev.zk_proof is not None:
    zk_verifier = get_zk_verifier()
    result = await zk_verifier.verify_proof(ev.zk_proof, db)
    if not result.is_valid:
        raise HTTPException(401, detail=f"ZK proof failed: {result.error}")
else:
    # Fall back to Evidence signature verification
    ...

API Reference

Circuit Management

Endpoint Method Description
/v1/zk/circuits POST Register a new circuit
/v1/zk/circuits/{id} GET Get circuit metadata
/v1/zk/circuits GET List circuits (filter by auditor, proof system)
/v1/zk/circuits/{id} DELETE Deactivate a circuit

Evidence Submission

The /v1/evidence/verify endpoint automatically handles ZK proofs when present in Evidence bundles. No API changes required.

Security Considerations

Trusted Setup (Groth16)

Groth16 requires a trusted setup ceremony. The setup_hash field in ZKCircuitRecord tracks which setup was used. Organizations should:

  1. Use well-known trusted setups (e.g., Powers of Tau)
  2. Verify setup hash matches expected value
  3. Consider PLONK/fflonk for applications requiring transparent setup

Circuit Versioning

Circuits should be versioned to ensure compatibility:

  • circuit_id: Unique identifier (e.g., "pii-detector-v1")
  • version: Semantic version (e.g., "1.0.0")

When updating a circuit, register a new version rather than modifying existing.

Verification Key Storage

Verification keys are stored base64-encoded in the database. The verification_key_hash field provides a quick lookup mechanism and integrity check.

Database Schema

CREATE TABLE zk_circuit_record (
    id UUID PRIMARY KEY,
    circuit_id VARCHAR(255) UNIQUE NOT NULL,
    circuit_name VARCHAR(255) NOT NULL,
    description TEXT,
    version VARCHAR(50) NOT NULL,
    proof_system zkproofsystemenum NOT NULL,
    curve VARCHAR(50) DEFAULT 'bn254',
    verification_key TEXT NOT NULL,
    verification_key_hash VARCHAR(128) NOT NULL,
    num_public_inputs INTEGER NOT NULL,
    setup_hash VARCHAR(128),
    auditor_id VARCHAR(255),
    org_id UUID REFERENCES organization(id),
    is_active BOOLEAN DEFAULT TRUE,
    registered_at TIMESTAMP,
    expires_at TIMESTAMP
);

Backward Compatibility

The ZK proof feature is fully backward compatible:

  1. Evidence without zk_proof: Continue to use signature verification
  2. Evidence with zk_proof: Use ZK proof verification (takes precedence)
  3. SDK without ZK extras: ZK module raises ZKNotAvailableError if snarkjs not installed

Future Enhancements

  1. Recursive Proofs: Aggregate multiple auditor proofs into a single proof
  2. On-chain Verification: Publish proofs to blockchain for public verifiability
  3. Custom Circuits: SDK tooling for building auditor-specific circuits
  4. Hardware Acceleration: GPU-based proving for faster proof generation