Every election faces the same tension: voters want proof their ballot was counted, but the vote itself must remain secret. VoteAlly solves this with cryptographic receipt codes that verify inclusion in the final tally without ever revealing who voted for whom.
Published: March 2026
Ballot anonymity with voter receipts means that each voter receives a unique 12-character cryptographic code after submitting their ballot. This code can be checked against a published list of all receipt codes to confirm the ballot was counted. The receipt reveals nothing about the vote choice or the voter's identity. VoteAlly enforces anonymity structurally: the Ballot table has no voter ID column, vote choices are encrypted with AES-256-GCM, and timestamps are rounded to the nearest hour to prevent correlation.
Paper ballots handle anonymity well: you mark a ballot, fold it, and drop it in a box. No one can trace it back to you. But paper ballots are terrible at auditability. After the box is opened and votes are counted, you have no way to confirm that your specific ballot made it into the final tally. You have to trust the process.
Digital voting platforms have the same fundamental challenge. If you give every voter a way to look up their ballot, you risk creating a link between the voter and their choice. If you keep ballots completely anonymous, voters have no way to verify the count includes their vote.
VoteAlly addresses both sides of this problem. Anonymity is enforced at the database structure level, not just the application logic level. And auditability is provided through cryptographic receipt codes that prove a ballot exists without revealing anything about it.
VoteAlly's anonymity is not a policy or an access control rule. It is a structural property of the database. Four layers work together to make it impossible to trace a vote back to a voter, even with full database access.
The Ballot table has no voter ID column. There is no foreign key, no reference field, and no way to join a ballot back to a voter. Participation is tracked separately: the VoterParticipation table records that a voter voted on a question, but never what they voted for.
The actual vote selection is encrypted with AES-256-GCM before it reaches the database. The plaintext selection field is stored as NULL. Only the encrypted payload and HMAC tally hashes are kept. Even with full database access, the vote content is unreadable without the encryption key.
Ballot timestamps are rounded down to the top of the current hour. If you vote at 2:35 PM, your ballot is timestamped 2:00 PM. This prevents "time correlation attacks" where someone could match a voter participation timestamp to a ballot creation time.
Each ballot gets a 12-character receipt code generated using HMAC-SHA256 with a server-side secret. The code is shown to the voter immediately after submission. It proves the ballot exists without revealing the vote or the voter.
These protections apply to every ballot, regardless of session type. For more on the infrastructure behind these safeguards, see the security overview.
When a voter submits their ballot, VoteAlly generates a receipt code and returns it immediately. Here is what happens, step by step:
Every ballot gets a UUID (universally unique identifier) generated on the server before it is saved. This ID is internal and never shown to the voter directly.
The server computes HMAC-SHA256 using the ballot ID and a secret key (AUTH_SECRET), then takes the first 12 characters of the result in uppercase. This produces a short, unique, and unforgeable code like "A7F3B2C91D04".
The vote selection is encrypted using AES-256-GCM and stored alongside HMAC tally hashes. The plaintext selection is never saved. The receipt code is stored on the ballot record and enforced as unique by a database constraint.
The voter sees their receipt code on the confirmation screen. This is the only time the system connects the voter to this specific code. Once the voter leaves the page, the connection exists only in the voter's memory or notes.
After voting ends, the administrator can export or publish the full list of receipt codes. The voter checks that their code appears in the list. If it does, their ballot is confirmed as part of the final tally.
A common question is: if votes are encrypted, how does VoteAlly count them? The answer is HMAC-based tally hashes.
When a ballot is submitted, each selected candidate ID is hashed using a derived secret key. The database stores these hashes alongside the encrypted ballot. To tally votes, the system computes the same hash for each known candidate and then groups ballots by matching hashes in the database.
The database engine only ever sees opaque strings. It never processes candidate names or plaintext vote choices. This means tallying is fast (a standard SQL GROUP BY query) and secure (the database never has access to what the hashes represent without the application secret).
A 150-unit condo association in Florida runs its annual board election through VoteAlly. The results show Candidate A winning by 8 votes. A homeowner who supported Candidate B sends an email to the board president: "How do I know my vote was actually counted? I don't trust digital voting."
The board president exports the list of all receipt codes from VoteAlly's reports page and publishes it in the next board communication. The list contains 142 receipt codes (one per ballot cast), with no names or vote choices attached.
The concerned homeowner checks the list and finds their receipt code, "B9E4F1A72C03", which they saved after voting. Their ballot is confirmed in the count. They still cannot see anyone else's vote, and no one else can determine how they voted from the receipt list.
This is the kind of post-election trust that paper ballots simply cannot provide. The voter gets individual verification. The board gets institutional credibility. And anonymity is never compromised.
The Ballot table has no voter ID column. There is no foreign key, no reference, and no way to join a ballot record back to a voter record. Voter participation is tracked in a separate table that records who voted on which question, but never what they voted for. Ballot timestamps are also rounded to the nearest hour to prevent time-based correlation.
A 12-character uppercase string generated using HMAC-SHA256 from the ballot ID and a server-side secret. It is shown to you immediately after you submit your ballot. You can use it to verify your ballot appears in the final tally without revealing your identity or your vote choice.
No. Ballot choices are encrypted using AES-256-GCM before storage. The plaintext selection is never saved. The Ballot table contains no voter reference. Even with full database access, there is no way to link a specific ballot to a specific voter.
No. Receipt codes are generated using HMAC-SHA256 with a secret key that only exists on the server. Without this key, producing a valid code is computationally infeasible. Each code is also enforced as unique at the database level.
After a session ends, the administrator can publish or export the full list of receipt codes. Each voter checks that their personal receipt code appears in the list. If it does, their ballot is confirmed as part of the count. The code reveals nothing about the vote choice or the voter identity.
Receipt codes survive the PII purge process. When voter personal information is removed (by default, 90 days after a session ends), the anonymous ballots and their receipt codes remain intact. The audit trail stays verifiable indefinitely.
VoteAlly is free for up to 50 voters. Every ballot gets a cryptographic receipt, and every vote is anonymous by design. No credit card required.