A 52-file Go re-implementation of Swiss Post's e-voting protocol
The Swiss Post e-voting system is the rare bird of public-sector cryptography: actually used, by an actual electorate, for actual binding elections. The Swiss federal authorities decided about a decade ago to commit to a fully end-to-end verifiable internet voting protocol, with all four properties — individual verifiability, universal verifiability, cast-as-intended, recorded-as-cast — and to release the full source code under public scrutiny. They followed through. Anyone can read the reference implementation.
Reading it is a different matter. The production system is 14 Java repositories, 500,000+ lines of code, ~50 GB of RAM required to run an election dry-run. Most of it is operational concerns — message queues, audit logging, ballot box infrastructure, election lifecycle orchestration. The cryptographic core is in there, but you have to dig.
swisspost-evoting-go-poc is what came out of doing that dig and writing the cryptography down as a single Go binary. 52 Go files. 2 external dependencies. End-to-end election lifecycle.
The full pipeline:
- Setup. Four "Control Components" plus an Electoral Board collaboratively generate keys via a distributed key generation protocol. Voting cards are issued, each carrying secret codes the voter will use to verify their vote was correctly recorded.
- Vote. The voter encrypts their ballot client-side (ElGamal on a chosen-prime curve). The server validates a sheaf of zero-knowledge proofs proving the ballot is well-formed without learning its contents. Return codes get sent back to the voter, derived from the encrypted ballot in a way that confirms cast-as-intended without revealing the choice.
- Tally. Five sequential verifiable shuffles (Bayer-Groth) move the ciphertexts through Control Components. Each shuffle permutes, re-encrypts, and emits a zero-knowledge proof that the multiset was preserved. After the fifth shuffle, the ballots are decrypted in a way that no single party could have done.
Each of those building blocks is small and self-contained in the PoC. The ElGamal layer is one file. The verifiable-shuffle proof generation is another. The Bayer-Groth verifier is its own file. The end-to-end test reproduces a synthetic election and asserts that the universal-verifiability proof checks out.
The reason for writing this is the same reason most PoC implementations of major protocols get written: the production code base is too large to read. It's not too large to use — it's a perfectly engineered piece of software — but reading it as an exercise in understanding the protocol is hopeless without something thinner alongside. This is the thinner alongside.
What becomes possible: anyone who wants to understand how a real, deployed, end-to-end verifiable election runs can read 52 files instead of 14 repositories.