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:
- Privacy-Preserving Verification: Customers can receive AI Passports without raw data leaving their TEE
- Scalable Verification: ZK proofs are compact and fast to verify
- 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 proofsZKCircuitMetadata: 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 proofsZKProof: Wraps raw proof data with serialization methodsZKEvidence: 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)
- Auditor loads circuit artifacts (WASM, proving key, verification key)
- Auditor computes claims using private inputs
- Auditor generates ZK proof attesting to the computation
- Auditor creates
Evidencewithzk_prooffield 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:
- Verifier checks if Evidence has
zk_prooffield - If present, verifier looks up circuit verification key from registry
- Verifier validates proof using the verification key
- 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:
- Use well-known trusted setups (e.g., Powers of Tau)
- Verify setup hash matches expected value
- 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:
- Evidence without
zk_proof: Continue to use signature verification - Evidence with
zk_proof: Use ZK proof verification (takes precedence) - SDK without ZK extras: ZK module raises
ZKNotAvailableErrorif snarkjs not installed
Future Enhancements
- Recursive Proofs: Aggregate multiple auditor proofs into a single proof
- On-chain Verification: Publish proofs to blockchain for public verifiability
- Custom Circuits: SDK tooling for building auditor-specific circuits
- Hardware Acceleration: GPU-based proving for faster proof generation