security
Secure Voting System
Terminal-based e-voting prototype combining ECC key exchange, AES-GCM authenticated encryption, and Twilio SMS voter verification, so ballots are tallied without ever exposing a plaintext vote in storage.
Role
Developer — team project (3 students)
Problem
Explores how public-key cryptography can protect a vote's confidentiality: each ballot is encrypted with the voter's own key and only decrypted if that voter re-verifies to change their vote. The README is upfront about the limits: the SMS re-entry step isn't a true zero-knowledge proof, the election authority could still decrypt any ballot, and all state lives in memory.
Tech Stack
PythonECC (brainpoolP256r1, tinyec)AES-256-GCM (PyCryptodome)Twilio SMS
How It Works
- 01A voter registers with an ID and phone number, and the app generates an ECC keypair (brainpoolP256r1) for them.
- 02The private key doubles as the verification code: it's texted to the voter through Twilio, and the voter re-types it one character at a time. Enough matching characters marks them verified.
- 03The voter picks a voting center and a candidate. The choice is encrypted with ECIES (a one-time ECC key and the voter's public key produce a shared secret, which SHA-256 turns into an AES-256-GCM key) in DES.py, despite the filename.
- 04Running tallies are updated at vote time, so counting never needs to decrypt a stored ballot.
- 05Registering again with the same ID triggers re-verification. The old ballot is then decrypted, its count reversed, and the new choice encrypted in its place. example.py runs this crypto core without Twilio.
What I Learned
- –Implementing ECIES from its primitives (ECC key exchange + AES-GCM) instead of one high-level 'encrypt' call made the mechanics of hybrid encryption concrete instead of a black box.
- –Writing down the system's own limitations was as valuable as building the crypto: the SMS step isn't a real zero-knowledge proof, the authority can still decrypt ballots, and there's no persistence layer. Knowing what you didn't solve is part of understanding security.
- –Twilio credentials sat hardcoded in bot.py in the original commits. The later cleanup moved them to environment variables, but the README now warns they can still be recovered from git history and must be rotated: removing a secret from the code doesn't remove it from the repo.