A secure and scalable MySQL-based voting system that supports multiple election types, encrypted vote storage, and flexible vote counting methods. Perfect for organizations, universities, or any entity needing a robust electronic voting solution.
-
Popular Vote
- Counts all votes from all districts
- Ranks candidates by total vote count
- Suitable for direct elections
-
Electoral College
- Districts have weighted scores (electoral votes)
- District winner takes all electoral votes
- Models electoral systems like US presidential elections
- Single Choice: Traditional one-person-one-vote
- Multi Choice: Select multiple winners (e.g., board elections)
- Referendum: Yes/No voting with support for both counting methods
- AES encryption for stored votes
- Hashed user IDs in vote records
- Geographic validation of voter eligibility
main.sql— entry script that creates the database and sources the other scripts (schemas, indexes, inserts, tests, procedures).UserSchema.sql— geographic tables,Users, and address mapping (locates).ElectionSchema.sql— election-related tables:Elections,ElectionGroups,GroupDistricts,Candidates,VoteDetails,encrypted_candidates,ElectionResultsPerGroup,ElectionResults.ElectionResultsProcedures.sql— stored procedures that decrypt and aggregate votes per group and compute final results.get_procedures.sql— helper procedures to retrieve results and map users to groups.Indexing.sql— (expected) index creation to optimize queries (sourced bymain.sql).InsertingUsers.sql,InsertingCountries.sql— sample data loaders.Test*.sql— test scenarios for popular, electoral and referendum elections.test.sql— additional test script.
There is also a countries/egypt.csv file used by the insert scripts.
Tables (short descriptions and important columns):
-
Elections- id, election_name, start_date, end_date, description
- vote_count_method ENUM('ELECTORAL_COLLEGE','POPULAR_VOTE')
- type_name ENUM('ONE_CHOICE','MULTI_CHOICE','REFERENDUM')
- max_choices INT — controls how many winners may be selected
- created_by ->
Users(id)
-
ElectionGroups- id, election_id ->
Elections(id), group_name, score (number of seats) - groups partition the electorate for the electoral-college mode
- id, election_id ->
-
GroupDistricts- mapping of
group_idtodistrict_idwithin anelection_id(used to assign voters by district)
- mapping of
-
Candidates- id, user_id (nullable for referendum options), election_id
- is_referendum_option BOOLEAN, option_label (e.g. 'Yes'/'No')
-
VoteDetails- id, hashed_user_id, group_id, timestamp — tracks a cast vote's metadata
-
encrypted_candidates- id, vote_id ->
VoteDetails(id), encrypted_candidate (base64), iv - stores the (AES) encrypted candidate choice per vote for privacy
- id, vote_id ->
-
ElectionResultsPerGroup- per-group aggregate of
candidate_id,vote_count,percentage
- per-group aggregate of
-
ElectionResults- per-election aggregate of
candidate_id, totalvote_count,percentage,is_winner
- per-election aggregate of
-
Geographic and user tables (from
UserSchema.sql):Countries,States_Governorates,Cities,Districts,Users,locates.locatesconnectsUserstoDistrictsand storesnational_id.
-
p_EncryptData/p_DecryptData— small examples showing AES encrypt/decrypt (MySQL AES_ENCRYPT/AES_DECRYPT) using a passphrase-derived key. -
p_calculate_election_results_per_group(p_election_id, key_str)- Decrypts encrypted candidate values per vote using the provided key.
- Aggregates vote counts per
ElectionGroupsand populatesElectionResultsPerGroup(vote_count, percentage). - This procedure expects the encryption key (or passphrase) to decrypt stored
encrypted_candidatevalues.
-
p_calculate_final_election_results(p_election_id)- Reads
Elections.vote_count_methodandElections.max_choicesto decide how to compute final results. - If
POPULAR_VOTE: sums votes across groups for each candidate and writesElectionResults. - Else (Electoral College): for each group, the candidate with the highest votes in the group wins that group's
scoreseats; sums seats per candidate and writesElectionResults. - Uses a ranking and then marks
is_winnerfor the topmax_choicesentries.
- Reads
-
p_get_election_results(p_election_id)- Returns a readable list of candidates, counts, percentages and winner flags for the election. For referendums it shows option labels instead of user names.
-
p_get_user_group_id(u_id, elec_id, OUT group_id)- Maps a user to their group for a given election by joining
locates,DistrictsandGroupDistricts.
- Maps a user to their group for a given election by joining
Candidatesenforces either auser_id(normal candidate) oris_referendum_option = TRUEwithoption_label(referendum option).Electionscontains checks ensuringmax_choicesandtype_nameare consistent. For example, referendums and one-choice elections should havemax_choices = 1.VoteDetailsandencrypted_candidatesare used to store votes with encrypted candidate references. The procedures rely on a consistent encryption key to decrypt values.
Prerequisites:
- MySQL (5.7+ or 8.x recommended) installed and running.
- A MySQL user with privileges to create databases and objects.
-
Clone the repository:
git clone https://github.com/mohamed20o03/Voting_system.git cd Voting_system -
Create the database and tables:
mysql -u root -p < main.sql -
The script will:
- Create the
voting_systemdatabase - Set up all tables and procedures
- Import sample data
- Run test scenarios
- Create the
-
Set up the election:
INSERT INTO Elections ( election_name, start_date, end_date, vote_count_method, type_name, max_choices ) VALUES ( 'Presidential Election 2024', '2024-11-03 00:00:00', '2024-11-03 23:59:59', 'ELECTORAL_COLLEGE', 'ONE_CHOICE', 1 );
-
Calculate results:
-- Aggregate votes per district CALL p_calculate_election_results_per_group(@election_id, @encryption_key); -- Calculate final results CALL p_calculate_final_election_results(@election_id); -- View results CALL p_get_election_results(@election_id);
- Uses MySQL's AES_ENCRYPT/AES_DECRYPT
- Keys derived from passphrase using SHA2
- Initialization vectors (IV) stored per vote
- Candidate choices stored encrypted
- User IDs hashed in vote records
- Never commit encryption keys
- Store encryption keys securely
- Rotate keys periodically
- Monitor access logs
- Regular security audits
The repository includes test scenarios:
TestPopularOneChoice.sql: Single-winner popular voteTestPopularMultiChoise.sql: Multi-winner scenariosTestElectoral.sql: Electoral college simulationsTestReferendum.sql: Yes/No voting examples
docs/: Technical documentationschema/: Database diagramsexamples/: Sample queriestests/: Test scenarios
- Stored procedures
- Triggers
- Views
- Encryption functions
- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.