This project is a blockchain-based voting system with anonymous voting via RSA blind signatures.
It includes:
- an admin server for election setup and control,
- a voter client for secure voting,
- receipt-based vote verification and blockchain integrity checks.
- Python
3.9+(recommended3.10+) - python-rsa >= 4.9
server/admin_server.py- election administration panel + background socket serverserver/server.py- request handler logicserver/CANDIDATES.json- candidates list loaded at startupclient/client.py- voter-side interactive CLIserver/tests.py- load/integration test suite (optional)
Generated during usage:
client/receipts/- voter receipts (receipt_*.json)client/exports/- exported blockchain snapshotslogs/- server logsvoting_results_*.zip- final packaged results produced by admin panel
Run from repository root:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtIf you use Windows PowerShell:
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txtFrom repository root:
python3 server/admin_server.py 5000 0.0.0.0 server/CANDIDATES.jsonParameters:
5000- port to listen on0.0.0.0- host binding (default:0.0.0.0for all interfaces; use127.0.0.1for localhost only, or your local IP like192.168.1.100for network access)server/CANDIDATES.json- candidate file path (optional, defaults toserver/CANDIDATES.json)
To connect from another machine on the local network, replace 0.0.0.0 with your server's local IP:
python3 server/admin_server.py 5000 192.168.1.100 server/CANDIDATES.jsonInside the admin panel:
- Use option 1 to generate voting tokens and distribute them to voters.
- Use option 3 to monitor live results.
- Use option 2 to stop voting and create final artifacts (
results.json,blockchain.json,winner.txtin a.zipfile).
In another terminal (same machine or remote machine that can reach server):
cd client
python3 client.pyThen follow the menu:
- Connect to server (
host,port) - Submit Vote (Blind Signature)
- Provide your one-time token
- Select candidate
- Client completes blind-signature flow automatically
- Receive and save digital receipt
The receipt is saved as JSON in client/receipts/.
In client menu, choose Verify Receipt:
- Recommended: load your saved receipt JSON file
- Alternative: paste
receipt_hashmanually
The client asks server to confirm that the receipt exists in blockchain and returns block metadata if valid.
From client:
- See Blockchain (and export) - view latest blocks and optionally export full chain to
client/exports/ - View Results - current vote counts
- Validate Blockchain - integrity check (hash links + duplicate-vote detection)
From admin panel:
- Generate tokens in batches before/while voting
- Stop and archive election outputs at the end
For security, test token issuance (request_test_tokens) is disabled by default.
To run automated tests, start the plain voting server with --test-mode:
python3 server/server.py 5000 0.0.0.0 server/CANDIDATES.json --test-modeParameters:
5000- port0.0.0.0- host binding (uselocalhostor127.0.0.1for local-only)server/CANDIDATES.json- candidate file path (optional)--test-mode- enables test token generation API
Then run tests from repository root:
python3 server/tests.py localhost 5000 150Arguments:
- host (default
localhost) - port (default
5000) - number of votes to simulate (default
150)
Important:
- Do not use
--test-modein normal voting sessions. admin_server.pydoes not enable test token API by default, which is intentional for safer operation.
Connection refusedon client:- Ensure admin server is running and listening on selected port.
Invalid token/Token already used:- Tokens are one-time only; request a new unused token from admin.
Invalid signature:- Retry vote flow from start; ensure stable connection and correct server target.
- No candidates shown:
- Verify
server/CANDIDATES.jsonexists and contains valid JSON array.
- Verify
RSA Blind Signatures (Chaum Protocol)
The system implements Chaum's blind signature scheme using the python-rsa library for consistent RSA operations across client and server:
- Key Generation: Server generates 2048-bit RSA keypair (modulus N, public exponent e=65537, private exponent d)
- Client Blinding: Client blinds vote m with random factor r:
m' = m · r^e mod N - Server Signing: Server signs blinded message without seeing vote:
σ' = (m')^d mod N - Client Unblinding: Client recovers valid signature:
σ = σ' · r^-1 mod N - Verification: Anyone can verify:
σ^e ≡ m (mod N)using public key
Key Properties:
- ✓ Server blindness: Server never sees the actual vote during signing
- ✓ Non-repudiation: Signature proves server signed it
- ✓ Unlinkability: Server cannot link signature to blinding factor
- ✓ One-vote enforcement: Tokens + nonce hashing prevent double voting
Both client and server now use the python-rsa library for key management and cryptographic operations, ensuring consistency and security.
- Vote Anonymity: Achieved through blind signatures - server signs blinded payloads without seeing actual votes.
- One-Person-One-Vote: Enforced by one-time token consumption and nonce-based deduplication in blockchain.
- Network Security: For production use with local network access, consider adding TLS/HTTPS encryption. Current implementation uses plain JSON over TCP.
- Blockchain: Single-node, in-memory (academic prototype). Data persistence provided through export/result packages rather than continuous database storage.
- Requirements: Install
python-rsavia:python3 -m pip install rsa