halo2-anon-auth
v0.2.0
Published
Halo 2 Anonymous Authentication - Standalone ZK proof library for web integration
Maintainers
Readme
Halo 2 Anonymous Authentication
A zero-knowledge proof system for anonymous authentication. Prove you are authorized without revealing your identity.
Security Notice
This is a security-critical cryptography project. Please review:
- Technical Documentation - Deep dive into cryptographic design
- Security Considerations - Deployment requirements
Overview
This package enables privacy-preserving authentication using Halo 2 zero-knowledge proofs. Users can prove they hold a valid credential from a trusted issuer without revealing:
- Their identity
- Which specific credential they hold
- Any other personal information
Privacy Properties
| What is Revealed | What is Hidden | |-----------------|----------------| | "Authorized" (yes/no) | Who the user is | | Nullifier (proves credential exists) | Which specific credential | | Issuer public key | User's identity | | Auth level (1, 2, etc) | Credential contents |
Installation
# Main package (includes WASM backend)
npm install halo2-anon-auth
# WASM backend only (standalone)
npm install halo2-anon-auth-wasmQuick Start
import { AnonAuth, createAnonAuth } from 'halo2-anon-auth';
// Initialize
const auth = createAnonAuth({ backend: 'wasm' });
await auth.init();
// Register a trusted issuer
auth.registerIssuer({
issuerId: 'did:example:authority1',
publicKey: { x: '0x...', y: '0x...' },
name: 'Example Authority',
maxAuthLevel: 2,
});
// Create anonymous proof (holder side)
const { proof, publicInputs } = await auth.createProof({
credential,
credentialSecret: holderSecret,
requestedLevel: 1,
nonce: crypto.getRandomValues(new Uint8Array(32)),
});
// Verify (verifier side)
const result = await auth.verify({
proof,
issuerId: 'did:example:authority1',
requiredLevel: 1,
});
if (result.valid) {
console.log('User is authorized!'); // We don't know who!
}Architecture
┌─────────────────────────────────────────────────────────────────┐
│ halo2-anon-auth Package │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ snarkjs │ │ halo2-wasm │ │ API.js │ │
│ │ backend │ │ backend │ │ (unified) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └───────────────────┴───────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ AnonAuth.js │ │
│ │ (main entry) │ │
│ └────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘WASM Backend
The WASM backend (halo2-wasm) uses DarkFi's zkvm - a battle-tested, production-ready zero-knowledge virtual machine. This provides:
- No Trusted Setup: Uses universal, updatable reference string (ULR)
- ZKAS Compiler: Human-readable circuit definitions compiled to binary
- Full Halo 2 Support: All standard arithmetic and cryptographic gadgets
- WASM Compilation: Runs natively in browsers
DarkFi Integration
The WASM backend directly imports from DarkFi:
# wasm/Cargo.toml
darkfi = { git = "https://codeberg.org/darkrenaissance/darkfi", features = ["zkas", "serde"] }
# Local vendor halo2 (zcash base with serialization ported from parazyd fork)
halo2_proofs = { path = "../../vendor/halo2/halo2_proofs", default-features = false, features = ["circuit-params"] }The local vendor/halo2/ contains zcash halo2 with:
circuit-paramsfeature (for darkfi::zk compatibility)- Serialization (
read/write/to_bytes/from_bytes) forProvingKeyandVerifyingKey - All fixes from parazyd's fork without the multicore bugs
See Technical Documentation for details on the zkvm architecture and the serialization port.
SnarkJS Backend
Pure JavaScript fallback for environments without WASM support.
ZK Circuit
The auth_v1 circuit proves:
1. Credential Possession: Prover knows the credential secret
2. Nullifier Derivation: nullifier = poseidon_hash(credential_secret, commitment)
3. Auth Level: Credential auth level is valid
4. Freshness: Proof uses a fresh nonce (no replay)Circuit defined in circuits/auth_v1.zk using ZKAS DSL:
k = 11;
field = "pallas";
constant "AuthV1" {
EcFixedPointBase NULLIFIER_K,
}
witness "AuthV1" {
Base nullifier,
Base issuer_pub_x,
Base issuer_pub_y,
Base requested_level,
}
witness "AuthV1" {
Base credential_secret,
Base commitment,
Base nonce,
}
circuit "AuthV1" {
computed_nullifier = poseidon_hash(credential_secret, commitment);
constrain_instance(computed_nullifier);
constrain_equal_base(computed_nullifier, nullifier);
range_check(64, nonce);
range_check(8, requested_level);
}API Reference
AnonAuth
Main class for anonymous authentication.
constructor(config?: AnonAuthConfig)
const auth = new AnonAuth({
backend: 'wasm', // 'snarkjs' | 'wasm' | 'auto'
wasmPath: '/path', // Optional WASM path
});async init(): Promise<void>
Initialize the backend.
registerIssuer(params: RegisterIssuerParams): void
Register a trusted issuer.
auth.registerIssuer({
issuerId: 'did:example:authority1',
publicKey: { x: '0x...', y: '0x...' },
name: 'Example Authority',
maxAuthLevel: 2,
});async createProof(params: CreateProofParams): Promise<{ proof: AuthProof, publicInputs: AuthPublicInputs }>
Create an anonymous authentication proof.
async verify(params: VerifyProofParams): Promise<VerifyResult>
Verify an anonymous authentication proof.
Building from Source
Prerequisites
- Node.js 18+
- Rust (latest stable)
- wasm-pack
# Clone
git clone https://github.com/your-org/halo2-anon-auth.git
cd halo2-anon-auth
# Install dependencies
npm install
# Build JavaScript
npm run build:js
# Build WASM backend
npm run build:wasmBuild WASM separately
cd wasm
wasm-pack build --target web --out-dir pkgSecurity Considerations
Critical Requirements
Credential Secrets: Must be kept secure on the holder's device. Never transmitted.
Nonce Generation: Must use cryptographically secure random. Never reuse a nonce.
Issuer Verification: Always verify issuer public key matches a registered trusted issuer.
Revocation Checking: Implementers should maintain and check against revocation lists.
Trusted Issuer Registration: Only register issuers you trust. A malicious issuer can create fake credentials.
Threat Model
See Technical Documentation for full details.
Theorem: A valid proof guarantees:
- The prover knows a credential secret corresponding to the nullifier
- The nullifier was correctly derived
- The credential has sufficient auth level
- The proof was generated after credential issuance
Use Cases
- Age Verification: Prove you're 18+ without revealing birthdate
- DAO Membership: Prove you're a member without revealing your identity
- KYC-Free Authentication: Authenticate without revealing personal data
- Access Control: Prove you have access rights without linking to identity
- Sybil Resistance: Prove uniqueness without deanonymization
Documentation
- Technical Documentation - Comprehensive technical documentation
- API Reference - Complete API documentation
Browser Support
- Chrome/Edge 90+
- Firefox 90+
- Safari 15+
References
License
MIT License
