swisspost-evoting-go-poc/pkg/protocol/confirm.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

62 lines
1.8 KiB
Go

package protocol
import (
"fmt"
"math/big"
"github.com/user/evote/pkg/hash"
emath "github.com/user/evote/pkg/math"
"github.com/user/evote/pkg/returncodes"
)
// ConfirmVote simulates vote confirmation (voter enters BCK).
func ConfirmVote(event *ElectionEvent, voterIdx int) string {
cfg := event.Config
vc := event.VotingCards[voterIdx]
// Combine LVCC shares from all CCs
combined := cfg.Group.Identity()
for _, cc := range event.CCs {
share := computeLVCCShare(cc, event, vc.VerificationCardID)
combined = combined.Multiply(share)
}
// Hash to get lVCC value
lVCCVal := returncodes.ComputeLVCCValue(combined, vc.VerificationCardID, cfg.ElectionID)
// Look up in mapping table
code, err := event.MappingTable.Lookup(lVCCVal)
if err != nil {
return "???"
}
fmt.Printf(" Voter %d: vote confirmed (VCC: %s)\n", voterIdx, code)
return code
}
func computeLVCCShare(cc *ControlComponent, event *ElectionEvent, vcID string) emath.GqElement {
cfg := event.Config
group := cfg.Group
zqGroup := emath.ZqGroupFromGqGroup(group)
// Derive voter-specific confirmation key
info := fmt.Sprintf("VoterVoteCastReturnCodeGeneration%s%s", cfg.ElectionID, vcID)
kVal := new(big.Int).SetBytes(hash.RecursiveHash(
hash.HashableString{Value: info},
hash.HashableBigInt{Value: cc.ReturnCodeSecret.Value()},
))
kVal.Mod(kVal, group.Q())
k, _ := emath.NewZqElement(kVal, zqGroup)
// Hash the confirmation key
ckVal := hash.RecursiveHashToZq(group.Q(),
hash.HashableString{Value: "ConfirmationKey"},
hash.HashableString{Value: vcID},
)
ckPlusOne := new(big.Int).Add(ckVal, big.NewInt(1))
// Square to ensure group membership
ckSquared := new(big.Int).Exp(ckPlusOne, big.NewInt(2), group.P())
hCK := hash.HashAndSquare(ckSquared, group)
return hCK.Exponentiate(k)
}