swisspost-evoting-go-poc/pkg/math/random.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

60 lines
1.5 KiB
Go

package math
import (
"crypto/rand"
"math/big"
)
// RandomZqElement generates a random element in Z_q.
func RandomZqElement(group *ZqGroup) ZqElement {
for {
r, err := rand.Int(rand.Reader, group.q)
if err != nil {
panic("crypto/rand failed: " + err.Error())
}
return ZqElement{value: r, group: group}
}
}
// RandomZqVector generates a vector of n random elements in Z_q.
func RandomZqVector(n int, group *ZqGroup) *ZqVector {
elements := make([]ZqElement, n)
for i := range elements {
elements[i] = RandomZqElement(group)
}
return &ZqVector{elements: elements, group: group}
}
// RandomGqElement generates a random element in G_q by squaring a random value.
func RandomGqElement(group *GqGroup) GqElement {
for {
// Generate random value in [1, q)
r, err := rand.Int(rand.Reader, new(big.Int).Sub(group.q, big.NewInt(1)))
if err != nil {
panic("crypto/rand failed: " + err.Error())
}
r.Add(r, big.NewInt(1)) // Shift to [1, q)
// Square to get quadratic residue
squared := new(big.Int).Exp(r, big.NewInt(2), group.p)
return GqElement{value: squared, group: group}
}
}
// RandomBigInt generates a random big.Int in [0, max).
func RandomBigInt(max *big.Int) *big.Int {
r, err := rand.Int(rand.Reader, max)
if err != nil {
panic("crypto/rand failed: " + err.Error())
}
return r
}
// RandomNonZeroZqElement generates a random non-zero element in Z_q.
func RandomNonZeroZqElement(group *ZqGroup) ZqElement {
for {
e := RandomZqElement(group)
if !e.IsZero() {
return e
}
}
}