Built on the Midnight Network
Zero-knowledge TOTP authenticator for the Midnight blockchain.
Prove you have the right code without showing it.
Midnight Authenticator enables users to prove they possess a valid authentication code without revealing the underlying secret or the code itself. Unlike traditional 2FA where codes are transmitted in plaintext, this authenticator replaces codes with zero-knowledge proofs - privacy-preserving 2FA that doesn't leak secrets to verifiers.
Contract deployed on Preprod: 02b325...1d66
| Extension | Demo dApp |
|---|---|
![]() |
![]() |
This authenticator uses Midnight's persistentHash for code generation, making it a ZK-native protocol. It is NOT RFC 6238 (TOTP) compatible.
| Aspect | Standard TOTP | Midnight Authenticator |
|---|---|---|
| Hash function | HMAC-SHA1 | persistentHash (ZK-friendly) |
| Interoperability | Works with Google Auth, etc. | Standalone ZK system |
| Privacy | Codes transmitted in plaintext | Codes never transmitted (ZK proof instead) |
| Verification | Server compares codes | Server verifies ZK proof |
Codes displayed in this app will NOT match standard authenticators like Google Authenticator.
Phase 4: ZK Integration - Mainnet Ready
| Component | Status | Notes |
|---|---|---|
| Compact Contract | ✅ Deployed | totp-verifier.compact on preprod |
| TypeScript Bindings | ✅ Generated | Full type-safe API |
| Chrome Extension | ✅ MVP Complete | Encrypted vault, ZK code generation (mock proofs in dev, see below) |
| Proof Provider | ✅ Architecture Ready | Lace wallet integration for mainnet |
| Security Reviews | ✅ 9 Reviews | All issues addressed |
| Test Coverage | ✅ 129 Tests | Vault, backup, accounts, crypto |
| Component | Proof Type | Notes |
|---|---|---|
| Deploy CLI (Node.js) | Real ZK proofs | Uses Docker proof server |
| Browser Extension | Mock proofs | SDK browser limitation (same as all Midnight extensions) |
| Mainnet | Real ZK proofs | Via Lace wallet integration |
For developers testing real ZK proofs:
# Start proof server
docker run -d --name proof-server -p 6300:6300 \
midnightntwrk/proof-server:8.0.3 midnight-proof-server -v
# Deploy contract with real ZK proofs
cd packages/deploy-cli
MIDNIGHT_SEED="your64hexseed" pnpm deployThe browser extension uses mock proofs during development because the Midnight SDK doesn't yet support browser-based proof generation. This is a known limitation shared by all Midnight browser extensions. At mainnet, users with Lace wallet will automatically use real proofs via Midnight's hosted infrastructure.
Security note: Mock proofs are for development/testing only. They do NOT provide ZK privacy or cryptographic integrity guarantees. Never use mock proofs with real credentials or in production scenarios.
- Zero-knowledge authentication using Midnight's ZK proof system
- ZK-native code generation (
persistentHash) - Encrypted local vault (Argon2id + AES-256-GCM)
- Encrypted backup/restore with password protection
- Chrome extension (Manifest V3)
- Real-time countdown timer (30-second windows)
- Click-to-copy codes
- Auto-lock security timer (5 minutes)
- Dark theme UI
- Service stores shared secrets (can be leaked)
- Codes transmitted in plaintext (can be intercepted)
- Service knows exact authentication times
- User proves: "I know secret S that produces a valid auth code"
- Service only learns: "user authenticated successfully"
- Secret never leaves the user's device
- Code never transmitted - replaced by ZK proof
- Registration: User commits
persistentCommit(secret, blinder)on-chain - Authentication: User generates ZK proof showing knowledge of secret
- Verification: Contract verifies proof without learning secret or code
packages/
contracts/ Compact smart contracts (ZK circuits)
core/ Core SDK and proof generation
extension/ Chrome extension (wallet + authenticator)
- Node.js 18+
- pnpm 9+
- Docker (for proof server)
- WSL (Windows only, for Compact CLI)
git clone https://github.com/subc0der/midnight-authenticator.git
cd midnight-authenticator
pnpm installdocker run -d --name proof-server -p 6300:6300 \
midnightntwrk/proof-server:8.0.3 midnight-proof-server -v
# Verify it's running
curl http://localhost:6300/version# Build all packages
pnpm build
# Build contracts only (requires WSL on Windows)
pnpm build:contracts
# Build extension
pnpm --filter @midnight-authenticator/extension build- Open Chrome and navigate to
chrome://extensions - Enable "Developer mode"
- Click "Load unpacked"
- Select
packages/extension/dist
After loading the extension:
- Click the extension icon
- Create a vault password
- Add an account:
- Issuer:
TestService - Name:
user@example.com - Secret:
JBSWY3DPEHPK3PXP(any Base32 string)
- Issuer:
- Click the account to reveal the ZK auth code
- The code refreshes every 30 seconds
Note: These codes are ZK-native and will NOT match Google Authenticator.
Your accounts are stored in an encrypted vault. To prevent data loss:
- Click the Export Backup button
- Enter a strong password (8+ characters, 2+ character types)
- Save the encrypted
.jsonfile securely
To restore from backup:
- Click Import Backup
- Select your backup file
- Enter the backup password
- Choose Merge (add to existing) or Replace (overwrite all)
Security notes:
- Backup files are encrypted with PBKDF2 (600k iterations) + AES-256-GCM
- The extension shows a warning if you haven't backed up recently
- Backups contain secrets - store them securely (password manager, encrypted drive)
The totp-verifier.compact contract provides:
| Circuit | Purpose |
|---|---|
registerAccount |
Register commitment on-chain |
authenticate |
Prove knowledge of secret for time window |
isRegistered |
Check if account exists |
computeAuthCode |
Pure circuit for client-side code generation |
- Commitment:
persistentCommit(secret, blinder)stored on-chain - Auth Proof:
persistentHash(authCode, blinder, nonce)for unlinkability - Time Window: Public input from verifier (30-second intervals)
- Replay Protection: Monotonic nonce per account
| Data | Visibility | Notes |
|---|---|---|
| accountId | Public | Identifies the account |
| nonce | Public | Replay protection |
| expectedTimeWindow | Public | Verifier-provided |
| secret | Private | Never revealed |
| blinder | Private | Commitment scheme |
| authCode | Private | Computed but never transmitted |
| Layer | Technology |
|---|---|
| Smart Contracts | Compact (Midnight ZK language) |
| Extension | React + Vite, Chrome MV3 |
| Encryption | Argon2id + AES-256-GCM |
| ZK Proofs | Midnight proof server (via Lace or Docker) |
| Code Generation | persistentHash (ZK-friendly) |
| Network | Midnight Preprod → Mainnet |
| Package | Version |
|---|---|
@midnight-ntwrk/compact-runtime |
0.15.0 |
@midnight-ntwrk/midnight-js-contracts |
4.0.2 |
@midnight-ntwrk/ledger |
4.0.0 |
| Proof Server | 8.0.3 |
| Compact CLI | 0.5.0 |
midnight-authenticator/
packages/
contracts/ Compact contracts
src/
totp-verifier.compact ZK authentication circuit
managed/ Compiled output (zkir, keys, TS bindings)
core/ Core SDK
src/
index.ts Exports and utilities
extension/ Chrome extension
src/
popup/ React UI
background/ Service worker (auth code, vault)
content/ Page integration
cd packages/contracts
pnpm compilecd packages/extension
pnpm devpnpm test # Run all tests
pnpm test --coverage # With coverage reportTest coverage includes:
- Vault encryption/decryption (22 tests)
- Base32 encoding (24 tests)
- Password validation (15 tests)
- Backup/restore (14 tests)
- Account CRUD (54 tests)
-
Phase 1: Research & Foundation
- ZK-compatible approach using
persistentHash - Circuit architecture design
- Monorepo setup
- ZK-compatible approach using
-
Phase 2: Core Circuits
totp-verifier.compactwith 9 security reviews- Compact CLI compilation (3 circuits)
- TypeScript bindings generated
-
Phase 3: Extension MVP
- Encrypted vault (Argon2id + AES-256-GCM)
- ZK auth code generation via pure circuits
- Account management UI with auto-lock
-
Phase 4: ZK Integration
- Contract deployed to preprod
- Proof provider architecture (Lace, Docker, Mock)
- Vault-locked authentication flow
- Demo verifier dApp
- Phase 5: Production
- Mainnet deployment (pending mainnet launch)
- Chrome Web Store submission
- End-to-end testing with real ZK proofs
A demo verifier application is included to test the authentication flow:
cd apps/demo
pnpm dev- Open the demo at
http://localhost:5173 - Add an account in the extension
- Copy the Account ID from the extension (click the ID below the code)
- Paste into the demo and click "Request Authentication"
- Approve in the extension popup
- See the ZK proof result
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Demo dApp │────▶│ Extension │────▶│ Proof Server │
│ (Verifier) │ │ (Prover/User) │ │ (Lace/Docker) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ AUTH_REQUEST │ Generate ZK Proof │
│◀──────────────────────│◀──────────────────────│
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Midnight Network (Preprod) │
│ Contract: 02b3255950655d5c3f2695692e8135... │
└─────────────────────────────────────────────────────────────────┘
Contributions welcome! Please read the security notes in .claude/context/security-learnings.md before contributing security-sensitive code.
This project has undergone 9 security-focused code reviews. Key patterns:
- All auth requests require explicit user approval (no silent proof generation)
- Secrets zeroed after use (
secret.fill(0)) - Origin validation via
sender.origin, not message payload - Keyboard accessibility for all interactive elements
Apache 2.0 - See LICENSE for details.

