swisspost-evoting-go-poc/pkg/protocol/config.go
saymrwulf e8b6f30871 Swiss Post E-Voting Go PoC
Proof-of-concept reimplementation of the Swiss Post e-voting
cryptographic protocol in Go. Single binary, 52 source files,
2 dependencies. Covers ElGamal encryption, Bayer-Groth verifiable
shuffles, zero-knowledge proofs, return codes, and a full
election ceremony demo.
2026-02-13 19:53:09 +01:00

75 lines
2.1 KiB
Go

package protocol
import (
"crypto/rand"
"fmt"
"math/big"
emath "github.com/user/evote/pkg/math"
)
// Config holds the election configuration.
type Config struct {
Group *emath.GqGroup
NumCCs int // Number of control components (typically 4)
NumOptions int // Number of voting options
NumVoters int // Number of eligible voters
ElectionID string // Election event identifier
SecurityLvl int // Security level in bits (128)
}
// DefaultConfig creates a config with a safe prime group.
func DefaultConfig(numVoters, numOptions int) *Config {
group := DefaultGroup()
return &Config{
Group: group,
NumCCs: 4,
NumOptions: numOptions,
NumVoters: numVoters,
ElectionID: "test-election-001",
SecurityLvl: 128,
}
}
// DefaultGroup returns a safe prime group for the PoC.
// Uses a pre-generated 512-bit safe prime for fast PoC testing.
// Production would use 3072 bits.
func DefaultGroup() *emath.GqGroup {
// Pre-computed 512-bit safe prime: q is prime, p = 2q + 1 is prime
// q = a prime ~255 bits, p = 2q+1 ~256 bits
// Using a known safe prime from literature for reproducibility.
// Generate a safe prime: p = 2q + 1 where both are prime.
q := generateSafePrimeQ(256)
p := new(big.Int).Mul(big.NewInt(2), q)
p.Add(p, big.NewInt(1))
// g = 4 (2^2 is a quadratic residue when 2 is a non-residue, which holds for p ≡ 3 mod 8)
// But we need to verify. If Jacobi(4, p) != 1, try g = 9.
g := big.NewInt(4)
if big.Jacobi(g, p) != 1 {
g = big.NewInt(9)
}
group, err := emath.NewGqGroup(p, q, g)
if err != nil {
panic("failed to create group: " + err.Error())
}
fmt.Printf(" Generated safe prime group (q: %d bits, p: %d bits)\n", q.BitLen(), p.BitLen())
return group
}
// generateSafePrimeQ generates a prime q such that p = 2q + 1 is also prime.
func generateSafePrimeQ(bits int) *big.Int {
for {
q, err := rand.Prime(rand.Reader, bits)
if err != nil {
panic("failed to generate prime: " + err.Error())
}
// Check if p = 2q + 1 is also prime
p := new(big.Int).Mul(big.NewInt(2), q)
p.Add(p, big.NewInt(1))
if p.ProbablyPrime(64) {
return q
}
}
}