From 577205a2ff25b46c1db2e2e6ac559b5dbdaa7728 Mon Sep 17 00:00:00 2001 From: saymrwulf Date: Mon, 6 Jul 2026 15:45:01 +0200 Subject: [PATCH] =?UTF-8?q?Return-code=20base:=20use=20prime^=CE=A3k=20(al?= =?UTF-8?q?gebraic)=20instead=20of=20HashAndSquare?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes the choice-code base from HashAndSquare(prime_i) to the encoding prime itself (a G_q element). The card code becomes prime_i^{Σ_j k_j}, which is algebraic and therefore recomputable by the CCs directly from the submitted ciphertext at vote time — the prerequisite for a genuine cast-as-intended return-code path. Setup and (upcoming) vote-time extraction use the same base, keeping them consistent. Co-Authored-By: Claude Fable 5 --- pkg/party/codes.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/party/codes.go b/pkg/party/codes.go index 23baa19..21848b8 100644 --- a/pkg/party/codes.go +++ b/pkg/party/codes.go @@ -64,8 +64,15 @@ func (p *ControlComponent) handleLongCodeShare(env *transport.Envelope) (*transp if !ok { return nil, fmt.Errorf("cc%d: invalid prime %q", p.index, ps) } - hpCC := hash.HashAndSquare(prime, group) - choiceShares[i] = hpCC.Exponentiate(kChoice).Value().String() + // Base is the encoding prime itself (a G_q element), NOT a hash of it: + // this keeps the code base algebraic so the CCs can recompute prime^k + // homomorphically from the submitted ciphertext at vote time + // (cast-as-intended). The combined card code is prime_i^{Σ_j k_j}. + base, err := emath.NewGqElement(prime, group) + if err != nil { + return nil, fmt.Errorf("cc%d: prime %d not in group: %w", p.index, i, err) + } + choiceShares[i] = base.Exponentiate(kChoice).Value().String() } // Confirmation-code share, keyed off a per-voter confirmation key.