Skip to content

MusthabaSM/Decentralized-Voting-System

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Secure VoteChain

Hardware-Integrated Blockchain Voting System for department-level college elections.

  • Frontend: React (Vite) + Tailwind + Framer Motion + Lucide + Recharts
  • Backend: Node.js + Express + Mongoose + JWT + bcrypt + helmet
  • Database: MongoDB (six collections: Voters, Votes, Blockchain Blocks, Candidates, Elections, Admins)
  • Blockchain: Functional simulated chain — SHA-256 PoW, linked previous-hashes, smart-contract gates, masked candidate identities in blocks

Project layout

secure-votechain/
├── docker-compose.yml          # Local MongoDB
├── server/                     # Express API + blockchain engine
│   ├── data/students.csv       # Imported on boot
│   └── src/
│       ├── blockchain/         # Chain ops + smart contract
│       ├── models/             # 6 Mongoose collections
│       ├── routes/             # auth, voters, elections, candidates, votes, blockchain, admin
│       ├── utils/              # SHA-256 hashing, CSV importer
│       ├── seed.js             # Idempotent: admin + voters + genesis + demo election
│       └── index.js
└── client/                     # Vite + React + Tailwind
    └── src/
        ├── pages/              # 10 pages
        ├── components/
        └── context/            # Auth + Theme

First-time setup

1. Start MongoDB

cd ~/Downloads/secure-votechain
docker compose up -d

(Or install MongoDB locally and ensure it's running on mongodb://localhost:27017.)

2. Backend

cd server
npm install
npm run dev

On first boot the server will:

  1. Create the default admin (admin / admin123)
  2. Import every row of data/students.csv into the Voters collection
  3. Generate a SHA-256 blockchain hash ID for each voter
  4. Mine the genesis block
  5. Create a demo election + 3 sample candidates

Backend runs on http://localhost:5000.

3. Frontend

cd ../client
npm install
npm run dev

Frontend runs on http://localhost:5173 and proxies /api/* to the backend.

Default credentials

Role Username/Reg No. Password
Admin admin admin123
Student any register number from students.csv student123

All voter passwords are seeded to the same default. Rotate before any real use.

Pages

  1. Home — animated blockchain background, CTAs
  2. Student Login / Admin Login — separate, JWT-based
  3. Student Dashboard — live participation, eligibility, active elections
  4. Cast Vote — encrypted vote, block-mining receipt, QR transaction code
  5. Blockchain Explorer — every block, hash chain, integrity status (candidate identity is masked)
  6. Results — public turnout always; candidate-wise tallies sealed until end time, then auto-revealed; PDF export
  7. Admin Dashboard — create elections, add candidates, activate/release, voter search, CSV re-import, chain reset
  8. About, Security, Architecture — institutional documentation

API surface

Method Path Auth Purpose
POST /api/auth/student/login public Issue student JWT
POST /api/auth/admin/login public Issue admin JWT
GET /api/auth/me any token Current identity
GET /api/elections public All elections + stats
GET /api/elections/:id public One election + candidates
GET /api/elections/:id/results public Sealed before end; revealed after
POST /api/elections admin Create
PATCH /api/elections/:id admin Update / toggle active
POST /api/elections/:id/release admin Force-release results
GET /api/candidates?election=:id public List
POST /api/candidates admin Add candidate
POST /api/votes/cast student Cast vote (runs contract → mines block)
GET /api/votes/me/:electionId student My receipt
GET /api/blockchain/blocks public Explorer feed (masked candidate)
GET /api/blockchain/status public Chain integrity
GET /api/blockchain/tx/:hash public Look up a transaction
GET /api/admin/overview admin Dashboard widgets
GET /api/admin/voters?q= admin Search roster
POST /api/admin/import-csv admin Re-run CSV importer
POST /api/admin/reset-chain admin Dev only: wipe votes + blocks

How the "transparent but sealed" property works

  1. When a vote is cast, the candidate ID is hashed into a candidateMask = sha256(candidateId | electionId) before being written to the block. The block does not store the raw candidate ID.
  2. The actual (voterHashId → candidate) mapping lives only in the Vote collection, used for tallying.
  3. GET /api/elections/:id/results checks election.areResultsVisible(). Before end time, it returns turnout only. After end time (or after an admin presses Release), it returns the candidate-wise counts.
  4. Anyone hitting the Blockchain Explorer sees blocks, hashes, and transaction IDs but cannot infer the winner because the candidate is masked.

Blockchain engine notes

  • server/src/blockchain/chain.js — genesis, append, full-chain re-validation (validateChain() re-hashes every block and verifies the previous-hash link).
  • server/src/blockchain/smartContract.js — the gates that run before block creation: election liveness, voter not voted, candidate registered, no duplicate vote row, chain still valid.
  • server/src/utils/hash.js — SHA-256 helpers and a light proof-of-work miner (difficulty 2 = 00… prefix; tweak in chain.js if you want heavier PoW for demos).

Reset / re-seed

# wipe everything:
docker compose down -v && docker compose up -d
# or, from the admin dashboard:
"Reset Chain" → clears votes + blocks + voter flags
"Re-import CSV" → reads server/data/students.csv again

Production checklist (before real use)

  • Rotate JWT_SECRET and all default passwords
  • Issue per-voter unique passwords instead of the shared default
  • Move blockchain mining to a worker (current PoW is intentionally light)
  • Pair voter login with hardware terminal attestation
  • Add HTTPS termination + WAF

About

A secure, tamper-proof platform that uses a distributed ledger to guarantee anonymous casting and transparent, unalterable vote counting.

Topics

Resources

Stars

Watchers

Forks

Contributors