mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
Pippenger's window method (banderwagon.MultiExp) branches on scalar digits, leaking secret prover-side scalars to a Flush+Reload attacker. Wrap MultiExp with multiplicative blinding (k_i -> k_i*r, post-multiply by r^-1 via Fermat) so the cache trace depends on a fresh per-call r instead of the underlying witness/blinding scalars. Five prover-side call sites switched to the blinded path: - prover.go:109,113,118,122 (a_R/a_L witness halves and z_L/z_R) - config.go:64 IPAConfig.Commit (full witness polynomial; trades the PrecompMSM precomputed-table speedup for protection of secret coeffs) Verifier-side callers (verifier.go:50,70 and multiproof.go:241) keep using the unblinded MultiScalar since they only consume public scalars. r is sampled via crypto/rand and converted to Montgomery form so the downstream Mul/Exp operate consistently with ScalarsMont:true. r^-1 uses Fermat (r^(q-2)) for a constant-iteration inversion ladder rather than the variable-time extended-Euclidean Inverse. A post-MSM normalization restores the canonical (0,1,1) projective form for the identity element, since gnark's scalarMulGLV produces a non-canonical representation that confuses Element.Equal. Tests in ipa/ipa/prover_blinding_test.go: 600 random correctness checks across 6 input sizes (n=2,4,8,64,128,256), input-mutation guard, length-mismatch error, and a timing-variance smoke test (cv ~34%, indicates fresh r per call exercises the masking path).