mirror of
https://github.com/saymrwulf/swisspost-evoting-go-poc.git
synced 2026-05-14 20:58:03 +00:00
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.
65 lines
2 KiB
Go
65 lines
2 KiB
Go
package elgamal
|
|
|
|
import (
|
|
emath "github.com/user/evote/pkg/math"
|
|
)
|
|
|
|
// CiphertextProduct computes the component-wise product of a vector of ciphertexts.
|
|
// Returns a single ciphertext: (Π gamma_i, Π phi_i,j for each j)
|
|
func CiphertextProduct(cts *CiphertextVector) Ciphertext {
|
|
if cts.Size() == 0 {
|
|
panic("cannot compute product of empty vector")
|
|
}
|
|
result := cts.Get(0)
|
|
for i := 1; i < cts.Size(); i++ {
|
|
result = result.Multiply(cts.Get(i))
|
|
}
|
|
return result
|
|
}
|
|
|
|
// CiphertextVectorExponentiate exponentiates each ciphertext by the corresponding exponent.
|
|
func CiphertextVectorExponentiate(cts *CiphertextVector, exps *emath.ZqVector) *CiphertextVector {
|
|
if cts.Size() != exps.Size() {
|
|
panic("vectors must have same size")
|
|
}
|
|
result := make([]Ciphertext, cts.Size())
|
|
for i := 0; i < cts.Size(); i++ {
|
|
result[i] = cts.Get(i).Exponentiate(exps.Get(i))
|
|
}
|
|
return NewCiphertextVector(result)
|
|
}
|
|
|
|
// CiphertextVectorMultiply multiplies two ciphertext vectors element-wise.
|
|
func CiphertextVectorMultiply(a, b *CiphertextVector) *CiphertextVector {
|
|
if a.Size() != b.Size() {
|
|
panic("vectors must have same size")
|
|
}
|
|
result := make([]Ciphertext, a.Size())
|
|
for i := 0; i < a.Size(); i++ {
|
|
result[i] = a.Get(i).Multiply(b.Get(i))
|
|
}
|
|
return NewCiphertextVector(result)
|
|
}
|
|
|
|
// ReEncrypt re-encrypts a ciphertext with fresh randomness.
|
|
// C' = C * Enc(1^l, r', pk) = (gamma * g^r', phi_i * pk_i^r')
|
|
func ReEncrypt(ct Ciphertext, rPrime emath.ZqElement, pk PublicKey) Ciphertext {
|
|
enc := EncryptOnes(rPrime, pk)
|
|
return ct.Multiply(enc)
|
|
}
|
|
|
|
// MultiExponentiation computes the multi-exponentiation of ciphertexts.
|
|
// Returns Π C_i^e_i = (Π gamma_i^e_i, Π phi_i,j^e_i for each j)
|
|
func MultiExponentiation(cts *CiphertextVector, exps *emath.ZqVector) Ciphertext {
|
|
if cts.Size() != exps.Size() {
|
|
panic("vectors must have same size")
|
|
}
|
|
if cts.Size() == 0 {
|
|
panic("vectors must not be empty")
|
|
}
|
|
result := cts.Get(0).Exponentiate(exps.Get(0))
|
|
for i := 1; i < cts.Size(); i++ {
|
|
result = result.Multiply(cts.Get(i).Exponentiate(exps.Get(i)))
|
|
}
|
|
return result
|
|
}
|