evote.This manual provides step-by-step operational procedures for all participants in the Swiss Post e-voting election ceremony, as implemented in the Go proof-of-concept (PoC) system evote.
The Go PoC reimplements the cryptographic core of the production Swiss Post e-voting system in roughly ten thousand lines of Go, plus a small Rust crate for transport security. It uses the same algorithms (ElGamal encryption, Schnorr proofs, Bayer-Groth verifiable shuffle) and offers two modes: a single-machine demo command-line tool, and a multi-party netdemo where each role is a separate endpoint communicating over an Ed25519-signed, X25519-encrypted transport (no RSA).
The Go PoC preserves the same role structure as the production system. Each role's responsibilities, trust boundaries, and ceremony steps are faithfully reproduced; in netdemo mode the trust boundaries are enforced cryptographically, with every inter-party message signed and verified. This ensures operational familiarity and avoids disrupting the agreed-upon organizational framework with its legal underpinnings.
The e-voting system operates in three phases across three days:
| Phase | Day | Key Operations | Primary Roles |
|---|---|---|---|
| Configuration | Day 1 | Key generation, voting card creation, system setup | Cantonal Admin, CC Operators |
| Release & Voting | Day 2 + Voting Period | Electoral Board constitution, setup verification, voter portal activation, ballot casting | Electoral Board, Verifier, Voters |
| Tally | Day 3 | Mixing, decryption, tally verification, result publication | CC Operators, Electoral Board, Verifier |
The following organizational hierarchy applies:
evote subcommands. In production, these roles are performed by different people on different machines with strict access controls and the four-eyes principle.To operate the Go PoC system, you need:
evote binary (build with make build, or go build ./cmd/evote from the evote/ directory)netdemo transport-security library (only for building; the binary is self-contained)netdemo signed transport runs in-processIn the Go PoC, the Cantonal Administrator's role corresponds to initiating the election setup and configuring the system parameters.
Decide on the number of voters and ballot options. The system will generate a safe prime group, encode the candidates, and begin the key generation ceremony.
The demo command performs:
The system generates key pairs for all 4 Control Components and the Electoral Board. Each CC generates a Schnorr proof of knowledge for its secret key. The Cantonal Administrator verifies these proofs are present.
Expected output:
The 5 public keys (4 CCs + Electoral Board) are multiplied together to form the joint Election Public Key. This key locks the ballot box -- all 5 key holders must cooperate to decrypt.
The system generates a unique voting card for each registered voter containing:
The Cantonal Administrator coordinates the Electoral Board constitution (see Chapter 3) and triggers the setup verification (see Chapter 8). Once verification passes, the voter portal URL is configured and published.
The Cantonal Administrator initiates the mixing process, coordinates Electoral Board password entry for decryption (see Chapter 3), and triggers the tally verification (see Chapter 8). Upon successful verification, the results are exported.
On the Setup SDM (an air-gapped machine), each board member enters a strong password. The combined passwords are used to derive the Electoral Board's secret key via Argon2id (a memory-hard key derivation function).
In the Go PoC, the Electoral Board key is generated automatically during the demo command. The system simulates the password entry process.
After the 4 Control Components have completed their shuffles, the Electoral Board performs the final shuffle and decryption on an air-gapped Tally SDM. Each board member enters their password to reconstruct the EB secret key.
The system performs the 5th Bayer-Groth shuffle, generates its proof, and removes the last encryption layer. The decrypted votes appear in random order.
In the production system, Swiss Post operates:
| Component | Technology | Purpose |
|---|---|---|
| Access Layer | WAF, TLS termination | Protects the Voting Server from direct internet access |
| Voting Server | Spring Boot, Kubernetes | Processes vote submissions, relays to CCs |
| 3 Control Components | Bare metal, diverse OS | Distributed key generation, return codes, shuffle |
| Message Broker | Apache ActiveMQ Artemis | Asynchronous communication between Server and CCs |
| Databases | PostgreSQL | Stores encrypted ballots, configuration, audit logs |
In the Go PoC, all of Swiss Post's infrastructure is simulated within the evote binary. The Voting Server, message broker, and database are replaced by in-memory data structures. The cryptographic operations are identical.
During the voting period, Swiss Post enforces a "red phase":
demo command enters the voting phase, the system processes all ballots without interruption.In the production system, the 4 CCs are deployed on bare-metal servers:
| CC | Location | Hardware | OS | Operated By |
|---|---|---|---|---|
| CC0 | Canton premises | ProLiant BL460c | RHEL 9.6 | Canton |
| CC1 | Swiss Post DC | ProLiant BL460c | Debian 12.12 | Swiss Post Team A |
| CC2 | Swiss Post DC | ProLiant BL460c | Ubuntu 24.04 | Swiss Post Team B |
| CC3 | Swiss Post DC | ProLiant DL385 | Windows Server 2022 | Swiss Post Team C |
In the Go PoC, all 4 CCs are simulated within the same process. They are named CC0 (Bern), CC1 (Zurich), CC2 (Geneva), CC3 (Lugano) and behave identically to the production CCs cryptographically.
Each CC generates a secret key vector sk = (sk[0], sk[1]) by sampling uniformly at random from Z_q. The corresponding public key pk = (g^sk[0], g^sk[1]) is computed and published.
For each key component, the CC generates a non-interactive Schnorr proof (Fiat-Shamir heuristic) demonstrating knowledge of the secret key without revealing it. The proof consists of two values (e, z) that anyone can verify.
The public key and Schnorr proof are transmitted to the central system for combination with the other CCs' keys.
On Day 3, each CC performs the following operations in sequence (CC0 first, then CC1, CC2, CC3):
CC0 receives the original encrypted ballots from the ballot box. Subsequent CCs receive the output of the previous CC's shuffle.
Sample a uniformly random permutation π of {0, ..., N-1}. This permutation determines the new order of the ballots.
For each output slot k, re-encrypt the permuted input ciphertext with fresh randomness. The resulting ciphertexts encrypt the same votes but are computationally unlinkable to the inputs.
Generate a zero-knowledge proof that the output is a valid permutation + re-encryption of the input. The proof has sub-linear O(√N) size and consists of nested sub-arguments: ProductArgument, HadamardArgument, ZeroArgument, SingleValueProductArgument, and MultiExponentiationArgument.
Securely erase the permutation π and all re-encryption randomness. After this step, even the CC operator cannot determine the correspondence between input and output ciphertexts.
Remove this CC's encryption layer by computing γ^sk for each ciphertext and dividing from the phi components. This reduces the number of remaining encryption layers by one.
The Cantonal Administrator generates voting card data during the Configuration Phase. The Printing Office receives the data and produces physical cards.
Each voting card contains:
| Field | Purpose | Example |
|---|---|---|
| Start Voting Key (SVK) | Authentication credential | SVK-0000 |
| Ballot Casting Key (BCK) | Vote confirmation credential | BCK-0000 |
| Choice Return Codes | Verify correct recording (one per candidate) | CC00 (Alice), CC01 (Bob) |
| Vote Cast Code (VCC) | Confirm vote is sealed | VCC00 |
In the Go PoC, the demo command displays all voting cards on screen:
Navigate to the official URL provided on your voting card or the cantonal website. Verify the TLS certificate. Accept the legal terms.
Enter your Start Voting Key (SVK) and date of birth. The server verifies your identity using an Argon2id hash (the SVK is never stored in plaintext).
In the Go PoC, authentication is simulated automatically.
Select your candidate(s) on the ballot. Your browser encrypts the vote locally using ElGamal encryption under the Election Public Key. The plaintext vote never leaves your device.
The browser sends two large numbers (γ, φ) to the server -- pure noise to anyone without all 5 secret keys.
The server displays a Choice Return Code. Compare it to the code on your physical voting card for the candidate you selected.
Enter your Ballot Casting Key (BCK) to finalize your vote. This is the second factor that prevents the server from confirming a vote without your explicit action.
The server displays a Vote Cast Code (VCC). Compare it to your voting card. If it matches, your vote is sealed and confirmed.
The return code mechanism provides individual verifiability: each voter can personally verify that their vote was cast as intended and recorded as cast, without needing to trust any single system component.
The security guarantee: if the Choice Return Code matches the code on your physical card, then the ciphertext stored on the server encrypts the candidate you selected. This holds under the assumption that at least 1 of the 4 Control Components is honest (since all 4 contribute to computing the return code).
After the Configuration Phase, the Verifier checks that the setup was performed correctly:
In the Go PoC, setup verification is performed automatically as part of the demo command.
After tallying, the Verifier performs the most critical checks:
For each CC, recompute the Schnorr verification equation: gz · pk-e should reconstruct the commitment c, and H(p, q, g, pk, c) should equal e.
For each of the 5 shuffles (4 CCs + Electoral Board), verify all sub-arguments of the Bayer-Groth shuffle proof. This confirms each shuffle was a valid permutation + re-encryption.
Confirm that the number of ballots is preserved at every stage: input to the first shuffle = output of the last shuffle = number of decrypted votes.
If all checks pass, the Verifier provides mathematical certainty that:
The Federal Chancellery does not directly operate any component of the e-voting system. Its role is regulatory and supervisory.
The Federal Chancellery commissions independent examiners across 4 scopes:
| Scope | Subject | Examiner |
|---|---|---|
| Scope 1 | Cryptographic protocol | Academic cryptographers |
| Scope 2 | System software | Software security auditors |
| Scope 3 | Infrastructure & operations | Infrastructure security auditors |
| Scope 4 | Penetration testing | Penetration testers + bug bounty community |
Additionally, Swiss Post publishes all source code and documentation, and runs a permanent bug bounty programme through YesWeHack, allowing the public to scrutinize the system.
| Command | Description | Key Flags |
|---|---|---|
evote demo |
Run a full election ceremony: setup → vote → tally → verify | --voters=N (default 10)--options=N (default 2) |
evote present |
Interactive step-by-step presentation mode with role-play narration | (same as demo) |
evote serve |
Serve web presentations on local network (iPad-optimized) | --port=N (default 8080) |
evote --help |
Show available commands and flags | -- |
| Aspect | Production System | Go PoC |
|---|---|---|
| Language | Java 21 + TypeScript + C# | Go + Rust (transport security) |
| Prime size | 3072 bits (128-bit security) | 256 bits (demo only) |
| Infrastructure | Kubernetes cluster + 4 bare-metal CCs + SDM machines | Single binary; netdemo splits parties into separate in-process endpoints |
| Networking | HTTPS/TLS, RSocket/CBOR, ActiveMQ | In-process signed message bus (netdemo); no external network |
| Signatures / key exchange | RSASSA-PSS, RSA-based channels, RSA X.509 | Ed25519 + X25519, Ed25519 X.509 (Rust); no RSA |
| Persistence | PostgreSQL databases | In-memory (no persistence) |
| SDM | Electron desktop app, air-gapped Windows machines | CLI commands |
| Voter Portal | Angular SPA, 4 languages | Simulated in CLI |
| Verifier | Standalone Java application, 50 checks | Built into demo command |
| Electoral Board | Physical password entry on air-gapped machine | Simulated key derivation |
| Voting cards | Printed on paper, mailed by post | Displayed on screen |
| ElGamal encryption | Identical algorithm | Identical algorithm |
| Schnorr proofs | Identical algorithm | Identical algorithm |
| Bayer-Groth shuffle | Identical algorithm | Identical algorithm |
| Fiat-Shamir heuristic | SHA3-256 recursive hash | SHA3-256 recursive hash |
| Role structure | Distributed across organizations | Same roles; netdemo separates them over a signed transport |
| Four-eyes principle | Enforced physically | Organizational (not enforced by software) |
| Source code | ~500,000 lines across 14 repos | ~10.5K lines Go + small Rust crate, 1 module |
| Dependencies | BouncyCastle, Spring, Angular, Electron, ... | Cobra + x/crypto; ed25519-dalek + x25519-dalek (Rust) |
End of Manual
Swiss Post E-Voting Go PoC -- Operator Manual v1.0
February 2026