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

77 lines
1.8 KiB
Go

package elgamal
import (
emath "github.com/user/evote/pkg/math"
)
// PrivateKey is a vector of Z_q elements.
type PrivateKey struct {
Elements *emath.ZqVector
}
// PublicKey is a vector of G_q elements.
type PublicKey struct {
Elements *emath.GqVector
}
// KeyPair holds a matching private and public key.
type KeyPair struct {
SK PrivateKey
PK PublicKey
}
// GenKeyPair generates an ElGamal key pair with l elements.
// sk = [x_0, ..., x_{l-1}] random in Z_q
// pk = [g^x_0, ..., g^x_{l-1}]
func GenKeyPair(group *emath.GqGroup, l int) KeyPair {
zqGroup := emath.ZqGroupFromGqGroup(group)
skElements := emath.RandomZqVector(l, zqGroup)
g := group.Generator()
pkElems := make([]emath.GqElement, l)
for i := 0; i < l; i++ {
pkElems[i] = g.Exponentiate(skElements.Get(i))
}
return KeyPair{
SK: PrivateKey{Elements: skElements},
PK: PublicKey{Elements: emath.GqVectorOf(pkElems...)},
}
}
// CombinePublicKeys computes the element-wise product of multiple public keys.
func CombinePublicKeys(keys ...PublicKey) PublicKey {
if len(keys) == 0 {
panic("must provide at least one key")
}
result := keys[0].Elements
for i := 1; i < len(keys); i++ {
result = result.Multiply(keys[i].Elements)
}
return PublicKey{Elements: result}
}
// Size returns the number of key elements.
func (pk PublicKey) Size() int {
return pk.Elements.Size()
}
// Get returns the i-th element of the public key.
func (pk PublicKey) Get(i int) emath.GqElement {
return pk.Elements.Get(i)
}
// Size returns the number of key elements.
func (sk PrivateKey) Size() int {
return sk.Elements.Size()
}
// Get returns the i-th element of the private key.
func (sk PrivateKey) Get(i int) emath.ZqElement {
return sk.Elements.Get(i)
}
// Group returns the GqGroup associated with this public key.
func (pk PublicKey) Group() *emath.GqGroup {
return pk.Elements.Group()
}