swisspost-evoting-go-poc/pkg/elgamal/encrypt.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

50 lines
1.1 KiB
Go

package elgamal
import (
emath "github.com/user/evote/pkg/math"
)
// Encrypt computes the ElGamal encryption of a message.
// gamma = g^r
// phi_i = pk_i^r * m_i
func Encrypt(msg Message, r emath.ZqElement, pk PublicKey) Ciphertext {
if msg.Size() != pk.Size() {
panic("message size must match public key size")
}
group := pk.Group()
g := group.Generator()
// gamma = g^r
gamma := g.Exponentiate(r)
// phi_i = pk_i^r * m_i
phis := make([]emath.GqElement, msg.Size())
for i := 0; i < msg.Size(); i++ {
pkR := pk.Get(i).Exponentiate(r)
phis[i] = pkR.Multiply(msg.Get(i))
}
return Ciphertext{
Gamma: gamma,
Phis: emath.GqVectorOf(phis...),
}
}
// EncryptOnes encrypts an all-ones message (used for trivial ciphertexts).
// gamma = g^r, phi_i = pk_i^r
func EncryptOnes(r emath.ZqElement, pk PublicKey) Ciphertext {
group := pk.Group()
g := group.Generator()
gamma := g.Exponentiate(r)
phis := make([]emath.GqElement, pk.Size())
for i := 0; i < pk.Size(); i++ {
phis[i] = pk.Get(i).Exponentiate(r)
}
return Ciphertext{
Gamma: gamma,
Phis: emath.GqVectorOf(phis...),
}
}