Cryptographic Stack
| Component | Choice & Rationale |
|---|---|
| Proof System | PLONK — no per-circuit trusted setup, reuses Aztec Ignition ceremony. Circuit updates don’t require re-ceremony. |
| Elliptic Curve | BN254 — ~145,000 opcode budget on Algorand Virtual Machine (AVM) vs ~185,000 for BLS12-381. Cheaper, faster, sufficient security. |
| Verifier Type | LogicSig — max budget 320,000 opcodes vs 190,400 for smart contracts. Preserves smart contract budget for app logic. |
| Nullifier Hash | Poseidon — ZK-friendly, dramatically fewer circuit constraints than SHA-256. |
| Merkle Tree Hash | MiMC — ZK-optimized, ideal for tree operations inside circuits. |
| Merkle Tree Type | Sparse Merkle Tree — O(1) leaf updates enable efficient credential revocation without tree rebuild. |
Data Flow: Proof Generation
The core promise of Ciphera is that raw data never leaves the user’s browser.- Local Parsing: The user’s Aadhaar Offline XML is parsed purely in-memory in the browser.
- Local Proof Generation:
snarkjs(running in WASM) generates the PLONK proof locally. The proof takes ~2-8 seconds to generate and is mathematically impossible to reverse-engineer. - Nullifier Derivation: A unique, per-app identifier is derived (see Per-App Nullifier Design).
- Encryption (Conditional Anonymity): An encrypted identity blob is created using ECIES. Only the 3-of-5 Custodian Shamir threshold can decrypt this.
- Memory Wiped: The raw XML and PII are deleted from browser memory.
- On-Chain Anchor: Only the cryptographic proof (~200 bytes) and the encrypted box storage blob are sent to the Algorand blockchain.

On-Chain Components
Our smart contracts are written in Python (PuyaPy via AlgoKit) to take advantage of the AVM’s high throughput and low fees.- LogicSig Verifier: Auto-generated by AlgoPlonk from the gnark circuit. Validates the PLONK proof on the BN254 curve natively on-chain.
- Nullifier Registry: Smart contract mapping:
nullifier_hash → wallet_address. Prevents the same Aadhaar from creating multiple credentials for the same app. - Credential ASA: Non-transferable Algorand Standard Asset (ASA) issued to the verified wallet. Clawback enabled exclusively for revocation.
- Box Storage: Stores the ECIES-encrypted identity blob. The key is the nullifier.
- Sparse Merkle Root: Maintains the on-chain root of valid credentials for instant
revoke()capabilities.
The ZK Circuit Design

1. Aadhaar UIDAI Signature Verification
Every Aadhaar Offline XML downloaded from UIDAI is digitally signed by UIDAI’s RSA-2048 private key. Without verifying this inside the circuit, an attacker could craft a fake XML. The first circuit constraint verifies the RSA signature against the hardcoded, public UIDAI key.2. Mandatory Claims
If the signature is valid, the circuit checks the non-negotiable KYC laws:assert nationality == 'IN'assert age(dob, currentDate) >= 18assert kycStatus == VERIFIEDassert SMT.verify(nullifier, merkleRoot, merklePath)
3. Optional Constraints
If the relying app (the DeFi protocol) requires more context (like State or precise Age), the user can opt-in to reveal commitments to those fields, preserving absolute data minimization.Per-App Nullifier Design

Hash(Aadhaar)) creates a cross-app tracking identifier. An observer could see 0xABC on a DeFi app and 0xABC on an NFT marketplace, linking their activity and destroying privacy.
Ciphera guarantees unlinkability by including the app_id in the derivation:
Revocation: Sparse Merkle Trees

REVOKED propagates up the tree in O(log n) operations, requiring only 1 Algorand transaction to permanently exile a bad actor globally from the ecosystem.