<p>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 <code>evote</code>.</p>
<p>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 <code>demo</code> command-line tool, and a multi-party <code>netdemo</code> where each role is a separate endpoint communicating over an Ed25519-signed, X25519-encrypted transport (no RSA).</p>
<p>The Go PoC preserves the <strong>same role structure</strong> as the production system. Each role's responsibilities, trust boundaries, and ceremony steps are faithfully reproduced; in <code>netdemo</code> 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.</p>
<divclass="legal-box">The role structure follows the Ordinance on Electronic Voting (OEV/VEleS) issued by the Federal Chancellery (Bundeskanzlei). All operational roles, trust boundaries, and separation-of-duties requirements are mandated by law. Deviating from the agreed role structure may have legal implications for the authorization of e-voting channels.</div>
<p>The following organizational hierarchy applies:</p>
+-- Operates 3 of 4 Control Components (separate teams)</div>
<divclass="note-box">In the Go PoC, all roles are exercised by the same person on the same machine via different <code>evote</code> subcommands. In production, these roles are performed by <strong>different people on different machines</strong> with strict access controls and the four-eyes principle.</div>
<li>The <code>evote</code> binary (build with <code>make build</code>, or <code>go build ./cmd/evote</code> from the <code>evote/</code> directory)</li>
<li>Go 1.25 or later, plus a Rust toolchain for the <code>netdemo</code> transport-security library (only for building; the binary is self-contained)</li>
<divclass="role-desc">Operates the Secure Data Manager (SDM) and coordinates the election ceremony. Responsible for processing electoral data, managing the key generation ceremony, generating voting cards, and coordinating between all other roles.</div>
</div>
<divclass="legal-box">The Cantonal Administrator operates the SDM under cantonal authority, <strong>not</strong> under Swiss Post. All personal data (electoral registers) remains exclusively at the canton. The four-eyes principle applies to all SDM operations.</div>
<p>In the Go PoC, the Cantonal Administrator's role corresponds to initiating the election setup and configuring the system parameters.</p>
<h3>2.2 Day 1 -- Configuration Phase</h3>
<divclass="step">
<spanclass="step-num">1</span>
<divclass="step-title">Initialize the election and generate cryptographic parameters</div>
<pstyle="margin-top:8px;">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.</p>
<divclass="code-block"># Full automated ceremony (all roles in one command):
./evote demo --voters=6 --options=2</div>
<p>The <code>demo</code> command performs:</p>
<ul>
<li>Safe prime group generation (p = 2q + 1, both prime, 256-bit)</li>
<li>Generator selection (g = 4, verified as quadratic residue)</li>
<divclass="step-title">Coordinate Control Component key generation</div>
<pstyle="margin-top:8px;">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.</p>
<divclass="step-title">Combine public keys into Election Public Key</div>
<pstyle="margin-top:8px;">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.</p>
<pstyle="margin-top:8px;">The system generates a unique voting card for each registered voter containing:</p>
<ul>
<li><strong>Start Voting Key (SVK)</strong> -- used for authentication</li>
<li><strong>Ballot Casting Key (BCK)</strong> -- used to confirm the vote</li>
<li><strong>Choice Return Codes</strong> -- one per candidate, used for individual verifiability</li>
<li><strong>Vote Cast Code (VCC)</strong> -- confirms the vote is sealed</li>
</ul>
</div>
<divclass="warning">In the Go PoC, voting cards are displayed on screen. In production, these are printed on physical paper and mailed to voters. The codes must <strong>never</strong> be transmitted electronically.</div>
<h3>2.3 Day 2 -- Release Phase</h3>
<p>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.</p>
<h3>2.4 Day 3 -- Tally Phase</h3>
<p>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.</p>
<divclass="code-block"># In the Go PoC, the demo command runs all three days automatically:
<divclass="role-desc">A group of at least 2 board members who collectively hold the 5th encryption key. Each member sets a password during setup; all members must enter their passwords to authorize decryption on election night. The Electoral Board is the final safeguard against unauthorized decryption.</div>
</div>
<divclass="legal-box">The Ordinance requires a minimum of 2 Electoral Board members. Each member's password must meet complexity requirements (minimum 24 characters in production). The board operates on air-gapped machines under the four-eyes principle.</div>
<h3>3.2 Constituting the Board (Day 2)</h3>
<divclass="step">
<spanclass="step-num">1</span>
<divclass="step-title">Each board member sets a password</div>
<pstyle="margin-top:8px;">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).</p>
<divclass="code-block"> EB member 1: enters password --> |
EB member 2: enters password --> |-- Argon2id --> sk_EB
EB member 3: enters password --> |
pk_EB = g^sk_EB mod p (published as part of the Election Public Key)</div>
</div>
<divclass="warning">If any board member forgets their password, the ballot box <strong>cannot be decrypted</strong>. There is no recovery mechanism. This is by design: it prevents any single party from decrypting without the board's collective authorization.</div>
<p>In the Go PoC, the Electoral Board key is generated automatically during the <code>demo</code> command. The system simulates the password entry process.</p>
<h3>3.3 Authorizing Decryption (Day 3)</h3>
<divclass="step">
<spanclass="step-num">1</span>
<divclass="step-title">Enter passwords on the Tally SDM</div>
<pstyle="margin-top:8px;">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.</p>
</div>
<divclass="step">
<spanclass="step-num">2</span>
<divclass="step-title">Authorize the final shuffle and decryption</div>
<pstyle="margin-top:8px;">The system performs the 5th Bayer-Groth shuffle, generates its proof, and removes the last encryption layer. The decrypted votes appear in random order.</p>
</div>
<divclass="note-box">The Electoral Board never sees which voter cast which vote. The 5 independent shuffles have permanently destroyed the link between voter identities and ballot contents.</div>
<divclass="role-name">Swiss Post (Schweizerische Post / System Provider)</div>
<divclass="role-desc">Develops and maintains the e-voting software. Operates the central infrastructure including the Voting Server, Access Layer, message broker, databases, and 3 of the 4 Control Components. Swiss Post does <strong>not</strong> operate the SDM, Verifier, or the cantonal Control Component.</div>
</div>
<h3>4.2 Infrastructure & Central Services</h3>
<p>In the production system, Swiss Post operates:</p>
<p>In the Go PoC, all of Swiss Post's infrastructure is simulated within the <code>evote</code> binary. The Voting Server, message broker, and database are replaced by in-memory data structures. The cryptographic operations are identical.</p>
<h3>4.3 Red Phase (Voting Period)</h3>
<p>During the voting period, Swiss Post enforces a "red phase":</p>
<ul>
<li>No system modifications are permitted</li>
<li>Infrastructure access is strictly controlled</li>
<li>SIEM monitoring is active for anomaly detection</li>
<li>Only pre-authorized personnel may access the systems</li>
</ul>
<divclass="note-box">In the Go PoC, there is no persistent infrastructure. The "red phase" is conceptual: once the <code>demo</code> command enters the voting phase, the system processes all ballots without interruption.</div>
<divclass="role-desc">Each of the 4 Control Components is operated by a separate team. No person with access to one CC may have access to any other CC. The CCs collectively ensure ballot secrecy (privacy) and election integrity (correctness). The system's security guarantees hold as long as at least one CC is honest.</div>
</div>
<divclass="legal-box">OEV Art. 3.15: "If a person has physical or logical access to a control component, that person may not have access to any other control component." The 4 CCs use maximally diverse hardware and operating systems to reduce common-mode failures.</div>
<p>In the production system, the 4 CCs are deployed on bare-metal servers:</p>
<tr><td>CC1</td><td>Swiss Post DC</td><td>ProLiant BL460c</td><td>Debian 12.12</td><td>Swiss Post Team A</td></tr>
<tr><td>CC2</td><td>Swiss Post DC</td><td>ProLiant BL460c</td><td>Ubuntu 24.04</td><td>Swiss Post Team B</td></tr>
<tr><td>CC3</td><td>Swiss Post DC</td><td>ProLiant DL385</td><td>Windows Server 2022</td><td>Swiss Post Team C</td></tr>
</table>
<p>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.</p>
<h3>5.2 Key Generation (Setup Phase)</h3>
<divclass="step">
<spanclass="step-num">1</span>
<divclass="step-title">Generate the key pair</div>
<pstyle="margin-top:8px;">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.</p>
</div>
<divclass="step">
<spanclass="step-num">2</span>
<divclass="step-title">Generate the Schnorr proof of knowledge</div>
<pstyle="margin-top:8px;">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.</p>
</div>
<divclass="step">
<spanclass="step-num">3</span>
<divclass="step-title">Publish public key and proof</div>
<pstyle="margin-top:8px;">The public key and Schnorr proof are transmitted to the central system for combination with the other CCs' keys.</p>
</div>
<h3>5.3 Shuffle & Partial Decryption (Tally Phase)</h3>
<p>On Day 3, each CC performs the following operations in sequence (CC0 first, then CC1, CC2, CC3):</p>
<divclass="step">
<spanclass="step-num">1</span>
<divclass="step-title">Receive the current ciphertext batch</div>
<pstyle="margin-top:8px;">CC0 receives the original encrypted ballots from the ballot box. Subsequent CCs receive the output of the previous CC's shuffle.</p>
</div>
<divclass="step">
<spanclass="step-num">2</span>
<divclass="step-title">Generate a random permutation</div>
<pstyle="margin-top:8px;">Sample a uniformly random permutation π of {0, ..., N-1}. This permutation determines the new order of the ballots.</p>
</div>
<divclass="step">
<spanclass="step-num">3</span>
<divclass="step-title">Re-encrypt and shuffle</div>
<pstyle="margin-top:8px;">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.</p>
</div>
<divclass="step">
<spanclass="step-num">4</span>
<divclass="step-title">Generate the Bayer-Groth shuffle proof</div>
<pstyle="margin-top:8px;">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.</p>
</div>
<divclass="step">
<spanclass="step-num">5</span>
<divclass="step-title">Destroy the permutation</div>
<pstyle="margin-top:8px;">Securely erase the permutation π and all re-encryption randomness. After this step, <strong>even the CC operator cannot determine the correspondence</strong> between input and output ciphertexts.</p>
<pstyle="margin-top:8px;">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.</p>
</div>
<divclass="warning">The permutation must be destroyed <strong>immediately</strong> after the proof is generated. If any CC retains its permutation, the privacy guarantee for that shuffle step is compromised.</div>
<divclass="role-desc">Prints and mails the physical voting cards to eligible voters. The voting card is the root of individual verifiability: it contains secret codes that enable the voter to verify that their vote was recorded correctly.</div>
</div>
<h3>6.2 Voting Card Generation & Distribution</h3>
<p>The Cantonal Administrator generates voting card data during the Configuration Phase. The Printing Office receives the data and produces physical cards.</p>
<divclass="warning">Voting cards must be printed on physical paper and delivered via postal mail. The codes must <strong>never</strong> be transmitted electronically (no email, no SMS, no online download). The physical card is the out-of-band channel that enables individual verifiability even if the voting device is compromised.</div>
<divclass="role-desc">An eligible citizen who casts a vote using the e-voting system. The voter interacts with the system through a web browser and verifies correct recording using the physical voting card received by mail.</div>
</div>
<h3>7.2 Voting Procedure</h3>
<divclass="step">
<spanclass="step-num">1</span>
<divclass="step-title">Open the voting portal</div>
<pstyle="margin-top:8px;">Navigate to the official URL provided on your voting card or the cantonal website. Verify the TLS certificate. Accept the legal terms.</p>
</div>
<divclass="step">
<spanclass="step-num">2</span>
<divclass="step-title">Authenticate</div>
<pstyle="margin-top:8px;">Enter your <strong>Start Voting Key (SVK)</strong> and <strong>date of birth</strong>. The server verifies your identity using an Argon2id hash (the SVK is never stored in plaintext).</p>
<p>In the Go PoC, authentication is simulated automatically.</p>
</div>
<divclass="step">
<spanclass="step-num">3</span>
<divclass="step-title">Cast your vote</div>
<pstyle="margin-top:8px;">Select your candidate(s) on the ballot. Your browser encrypts the vote locally using ElGamal encryption under the Election Public Key. <strong>The plaintext vote never leaves your device.</strong></p>
<p>The browser sends two large numbers (γ, φ) to the server -- pure noise to anyone without all 5 secret keys.</p>
</div>
<divclass="step">
<spanclass="step-num">4</span>
<divclass="step-title">Verify the Choice Return Code</div>
<pstyle="margin-top:8px;">The server displays a <strong>Choice Return Code</strong>. Compare it to the code on your physical voting card for the candidate you selected.</p>
<ul>
<li>If the codes <strong>match</strong>: your vote was recorded correctly. Proceed to confirm.</li>
<li>If the codes <strong>do not match</strong>: <strong>STOP. Do not confirm.</strong> Contact the cantonal authority. Your vote may have been intercepted or modified.</li>
</ul>
</div>
<divclass="step">
<spanclass="step-num">5</span>
<divclass="step-title">Confirm with the Ballot Casting Key</div>
<pstyle="margin-top:8px;">Enter your <strong>Ballot Casting Key (BCK)</strong> to finalize your vote. This is the second factor that prevents the server from confirming a vote without your explicit action.</p>
</div>
<divclass="step">
<spanclass="step-num">6</span>
<divclass="step-title">Verify the Vote Cast Code</div>
<pstyle="margin-top:8px;">The server displays a <strong>Vote Cast Code (VCC)</strong>. Compare it to your voting card. If it matches, your vote is sealed and confirmed.</p>
</div>
<h3>7.3 Verifying Your Vote (Individual Verifiability)</h3>
<p>The return code mechanism provides <strong>individual verifiability</strong>: each voter can personally verify that their vote was cast as intended and recorded as cast, without needing to trust any single system component.</p>
<p>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).</p>
<divclass="note-box">Even if your computer is compromised with malware, the return codes on the physical card were generated during setup by the 4 CCs -- independently of your browser. A malware-modified vote would produce the wrong return code.</div>
<divclass="role-desc">Operates the verification software that independently checks whether all protocol participants faithfully executed their operations. The Verifier runs on an offline, hardened machine under cantonal authority -- <strong>not</strong> under Swiss Post. The Verifier requires no secret keys and uses only publicly available data.</div>
</div>
<divclass="legal-box">The Verifier is operated by the electoral commission under the responsibility of the cantons. It provides <strong>universal verifiability</strong>: any party can audit the election result using only public data and mathematics.</div>
<h3>8.2 Setup Verification (Day 2)</h3>
<p>After the Configuration Phase, the Verifier checks that the setup was performed correctly:</p>
<ul>
<li><strong>Key proofs:</strong> Verify the Schnorr proof for each CC's public key (proves the CC knows the corresponding secret key)</li>
<li><strong>Key combination:</strong> Verify the Election Public Key is the correct product of all 5 individual keys</li>
<li><strong>Voting card integrity:</strong> Verify return code mappings are consistent</li>
</ul>
<p>In the Go PoC, setup verification is performed automatically as part of the <code>demo</code> command.</p>
<h3>8.3 Tally Verification (Day 3)</h3>
<p>After tallying, the Verifier performs the most critical checks:</p>
<divclass="step">
<spanclass="step-num">1</span>
<divclass="step-title">Verify all Schnorr proofs (4 key proofs)</div>
<pstyle="margin-top:8px;">For each CC, recompute the Schnorr verification equation: g<sup>z</sup>· pk<sup>-e</sup> should reconstruct the commitment c, and H(p, q, g, pk, c) should equal e.</p>
<divclass="code-block"> CC0 (Bern): [PASS]
CC1 (Zurich): [PASS]
CC2 (Geneva): [PASS]
CC3 (Lugano): [PASS]</div>
</div>
<divclass="step">
<spanclass="step-num">2</span>
<divclass="step-title">Verify all Bayer-Groth shuffle proofs (5 shuffle proofs)</div>
<pstyle="margin-top:8px;">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.</p>
<pstyle="margin-top:8px;">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.</p>
<divclass="code-block"> Ballots submitted: 6
Ballots decrypted: 6
==> PASS: Every ballot is accounted for.</div>
</div>
<h3>8.4 Interpreting Verification Results</h3>
<p>If all checks pass, the Verifier provides mathematical certainty that:</p>
<ol>
<li>All key holders proved knowledge of their secret keys</li>
<li>All shuffles were honest permutations + re-encryptions (no votes added, removed, or changed)</li>
<li>The ballot count is consistent throughout the pipeline</li>
<li>The final tally correctly reflects the decrypted ballots</li>
</ol>
<divclass="warning">If <strong>any</strong> check fails, the election result <strong>must not be published</strong>. A failed shuffle proof indicates that a CC may have tampered with the ballots. Contact the Federal Chancellery and the cantonal authority immediately.</div>
<divclass="role-desc">The highest authority overseeing the e-voting system. Issues the Ordinance on Electronic Voting (OEV), commissions independent examinations, approves cantons for e-voting, and publishes examination reports.</div>
</div>
<p>The Federal Chancellery does not directly operate any component of the e-voting system. Its role is regulatory and supervisory.</p>
<h3>9.2 Four Audit Scopes</h3>
<p>The Federal Chancellery commissions independent examiners across 4 scopes:</p>
<p>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.</p>
<divclass="note-box">The Go PoC is a reimplementation for educational and demonstration purposes. It has not undergone the formal examination process. In a production deployment, all four audit scopes would need to be passed before the system is approved for use in federal elections.</div>
<tr><td>Infrastructure</td><td>Kubernetes cluster + 4 bare-metal CCs + SDM machines</td><td>Single binary; <code>netdemo</code> splits parties into separate in-process endpoints</td></tr>
<tr><td>Networking</td><td>HTTPS/TLS, RSocket/CBOR, ActiveMQ</td><td>In-process signed message bus (<code>netdemo</code>); no external network</td></tr>
<tr><td>Role structure</td><td>Distributed across organizations</td><td>Same roles; <code>netdemo</code> separates them over a signed transport</td></tr>