# System Architecture ## Overview Client/Server architecture with blockchain-based vote recording and cryptographic security. Built with Next.js 15 frontend and FastAPI backend. ## Components (Implemented) ### Frontend (Next.js 15 + TypeScript) - ✅ **Voting Interface** (`components/voting-interface.tsx`): Multi-step ballot selection and submission - ✅ **Crypto Client** (`lib/crypto-client.ts`): ElGamal encryption, ZKP generation, digital signatures - ✅ **Authentication**: JWT-based voter sessions - ⏳ **Blockchain Viewer**: Display blockchain and verify integrity (UI pending) - ⏳ **Results Display**: Show voting results with verification proofs (UI pending) ### Backend (FastAPI + Python 3.12) - ✅ **Auth Service** (`routes/auth.py`): JWT authentication and voter verification - ✅ **Voting API** (`routes/votes.py`): Vote submission, encryption, blockchain recording - ✅ **Blockchain Service** (`blockchain.py`): Block creation, chain validation, integrity verification - ✅ **Crypto Operations**: ElGamal encryption, digital signatures, SHA-256 hashing, ZKP - ✅ **Scrutator Service** (`scripts/scrutator.py`): Vote counting, verification, and audit reporting - ✅ **Election Service** (`routes/elections.py`): Election management ### Database (SQLAlchemy) - ✅ **Voter**: Voter registration and authentication - ✅ **Election**: Election configuration and cryptographic keys - ✅ **Candidate**: Election options - ✅ **Vote**: Encrypted votes with ballot hashes and ZK proofs - ✅ **AuditLog**: Security audit trail ## Data Flow (Implemented) ### Vote Submission ``` Frontend (Voter) ↓ GET /api/votes/public-keys Backend ↓ Return ElGamal public key ↓ Frontend: 1. ✅ Fetch public keys ↓ 2. ✅ Encrypt ballot (ElGamal) ↓ 3. ✅ Generate ZKP (Fiat-Shamir) ↓ 4. ✅ Sign ballot (RSA-PSS) ↓ 5. ✅ Submit POST /api/votes/submit ↓ Backend (API): ↓ 6. ✅ Authenticate voter (JWT) ↓ 7. ✅ Verify signature (RSA-PSS) ↓ 8. ✅ Verify ZKP ↓ 9. ✅ Check voter hasn't voted ↓ 10. ✅ Create blockchain block ↓ 11. ✅ Sign block (RSA-PSS) ↓ 12. ✅ Append to blockchain ↓ 13. ✅ Record in database ↓ 14. ✅ Return transaction_id ↓ Frontend: ↓ Display confirmation with TX ID ``` ### Vote Counting (Scrutator) ``` Command: poetry run python -m backend.scripts.scrutator --election-id 1 ↓ Scrutator Service: ↓ 1. ✅ Load election and blockchain ↓ 2. ✅ Fetch all votes from database ↓ 3. ✅ Verify blockchain integrity: - Check hash chain (each block refs previous) - Check block signatures - Detect any tampering ↓ 4. ✅ Count votes by candidate ↓ 5. ✅ Verify consistency (DB votes == blockchain votes) ↓ 6. ✅ Generate audit report: - Blockchain validity - Vote counts - Verification proofs - Timestamp ↓ 7. ✅ Export JSON report ``` ## Cryptographic Workflow (Implemented) ### Election Setup (Endpoint: POST /api/votes/setup) 1. ✅ Generate ElGamal keypair (p, g, h) where h = g^x mod p 2. ✅ Store public key p in election record 3. ✅ Create blockchain for election 4. ✅ Publish public key to voters **Post-Quantum Ready**: Kyber and Dilithium support via liboqs-python (optional) ### Voter Registration 1. ✅ Voter authenticates (JWT token) 2. ✅ Voter registration stored in database 3. ✅ System verifies voter hasn't voted in this election ### Ballot Submission (Endpoint: POST /api/votes/submit) ``` Voter: 1. ✅ Voter selects candidate: v ∈ {0, 1} Frontend (crypto-client.ts): 2. ✅ GET /api/votes/public-keys?election_id=1 3. ✅ E(v) = ElGamal.encrypt(v, pubkey) 4. ✅ π = ZKP.prove(E(v) is 0 or 1) [Fiat-Shamir protocol] 5. ✅ σ = sign(E(v) || π) [RSA-PSS] 6. ✅ POST /api/votes/submit {election_id, candidate_id, encrypted_vote, zkp_proof, signature} Backend (routes/votes.py): 7. ✅ Authenticate voter (verify JWT) 8. ✅ Validate encrypted vote format 9. ✅ Verify ZKP proof (check challenge-response) 10. ✅ Check voter hasn't voted (emission list check) 11. ✅ Create Block(index, prev_hash, timestamp, E(v), tx_id) 12. ✅ H = SHA256(Block contents) [hash chain] 13. ✅ σ_block = sign(H) [block signature] 14. ✅ blockchain.add_block(H, σ_block) [append to chain] 15. ✅ Record Vote in database 16. ✅ Return {transaction_id, block_index, confirmation} ``` ### Vote Counting (Command: poetry run python -m backend.scripts.scrutator --election-id 1) ``` Scrutator (scripts/scrutator.py): 1. ✅ Load blockchain for election 2. ✅ Fetch all votes from database 3. ✅ For each block b in blockchain: - ✅ Verify(b.signature) [block authenticity] - ✅ Verify(H = SHA256(block_content)) [block integrity] - ✅ Verify(b.prev_hash == previous_block.H) [chain linkage] 4. ✅ If any verification fails: BLOCKCHAIN INVALID 5. ✅ Count votes by candidate from database 6. ✅ Verify consistency: |database_votes| == |blockchain_blocks| 7. ✅ Generate audit report: - Blockchain validity status - Vote counts with percentages - Verification proofs - Timestamp and signatures 8. ✅ Export JSON report for transparency ``` ## Security Properties (Implemented) ### ✅ Vote Secrecy - Votes encrypted with ElGamal before leaving client (crypto-client.ts) - Server never sees plaintext votes (encrypted_vote stored as base64) - Vote linked to candidate in database only for counting (not in blockchain) - **Mechanism**: ElGamal(vote) = (g^r mod p, vote * h^r mod p) is semantically secure ### ✅ Vote Integrity - Blockchain structure prevents tampering (blockchain.py) - SHA-256 hash chain ensures immutability (each block refs previous) - RSA-PSS signatures verify block authenticity - Modification of any block breaks entire chain - **Verification**: Any block tampering detected by hash verification ### ✅ Voter Authentication - JWT tokens verify voter session (auth.py) - RSA-PSS signatures verify ballot authorship (crypto-client.ts) - Emission list prevents double voting (check before recording) - Voter must authenticate before voting ### ✅ Anonymity - Only transaction ID stored with vote in blockchain (not voter ID) - Voter verified once at authentication - Vote-to-voter link exists only in database (not blockchain) - Blockchain itself is voter-anonymous - **Mechanism**: Transaction ID = random 12-hex string, unlinked to voter ### ✅ Individual Verifiability - ZKP proves ballot validity (0 or 1) without revealing vote (zk_proofs.py) - Voter can search blockchain for their transaction ID - Voter can verify their encrypted ballot is recorded - **Mechanism**: Fiat-Shamir ZKP challenge-response protocol ### ✅ Universal Verifiability - Blockchain is public (GET /api/votes/blockchain) - Anyone can verify chain integrity (verify_chain_integrity()) - Anyone can run scrutator to verify vote counting - Hash chain verification ensures chain validity - **Mechanism**: SHA-256 chain links every block to previous; modify one block = hash mismatch ### ✅ Post-Quantum Ready - Kyber support in pqc_hybrid.py (requires liboqs-python) - Dilithium support in pqc_hybrid.py (requires liboqs-python) - Currently uses RSA (classical) - PQC available as drop-in replacement - Future-proof architecture ready for quantum-resistant migration ## File Structure (Implemented) ``` backend/ ├── blockchain.py # ✅ Block, Blockchain classes with integrity verification ├── crypto/ │ ├── encryption.py # ✅ ElGamal homomorphic encryption │ ├── signatures.py # ✅ RSA-PSS digital signatures │ ├── hashing.py # ✅ SHA-256 hashing and key derivation │ ├── zk_proofs.py # ✅ Fiat-Shamir zero-knowledge proofs │ └── pqc_hybrid.py # ✅ Post-quantum crypto (Kyber, Dilithium) ├── routes/ │ ├── votes.py # ✅ Complete voting API endpoints │ ├── elections.py # ✅ Election management │ └── auth.py # ✅ Authentication ├── models.py # ✅ Database models (Voter, Election, Vote, etc) ├── services.py # ✅ Business logic services ├── database.py # ✅ Database configuration ├── main.py # ✅ FastAPI app initialization ├── config.py # ✅ Configuration ├── auth.py # ✅ JWT token handling └── scripts/ └── scrutator.py # ✅ Vote counting, verification, audit reporting frontend/ ├── components/ │ └── voting-interface.tsx # ✅ Multi-step voting interface (select→confirm→submit→success) ├── lib/ │ ├── crypto-client.ts # ✅ Client-side encryption, ZKP, signatures │ ├── api.ts # ✅ API client with type-safe interfaces │ ├── auth-context.tsx # ✅ Authentication context │ └── validation.ts # ✅ Form validation ├── app/ │ ├── auth/ │ │ ├── login/page.tsx # ✅ Login page │ │ └── register/page.tsx # ✅ Registration page │ └── dashboard/ │ ├── page.tsx # ✅ Dashboard home │ ├── profile/page.tsx # ✅ Profile page │ └── votes/ │ ├── active/page.tsx # ✅ Active elections │ ├── upcoming/page.tsx # ✅ Upcoming elections │ ├── history/page.tsx # ✅ Vote history │ └── archives/page.tsx # ✅ Past elections └── public/ # ✅ Static assets Infrastructure: ├── docker-compose.yml # ✅ Docker configuration ├── Dockerfile # ✅ Backend Docker image ├── frontend/Dockerfile # ✅ Frontend Docker image ├── pyproject.toml # ✅ Python dependencies (Poetry) └── openspec/ # ✅ Specification and change tracking ├── specs/ │ ├── mvp.md # ✅ MVP implementation spec │ └── architecture.md # ✅ Architecture documentation └── changes/ └── add-pqc-voting-mvp/ ├── proposal.md ├── tasks.md └── design.md ```