internal/ed25519: add variable-time multiscalar mul

This commit is contained in:
Henry de Valence 2019-05-09 00:05:08 -07:00 committed by Filippo Valsorda
parent 4ba8cc9326
commit 8186dbd6e1
2 changed files with 74 additions and 1 deletions

View File

@ -234,6 +234,55 @@ func (v *ProjP3) VartimeDoubleBaseMul(a, b *scalar.Scalar, A *ProjP3) *ProjP3 {
//
// The multiscalar multiplication is performed in variable time.
func (v *ProjP3) VartimeMultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *ProjP3 {
panic("unimplemented")
if len(scalars) != len(points) {
panic("called MultiscalarMul with different size inputs")
}
// Generalize double-base NAF computation to arbitrary sizes.
// Here all the points are dynamic, so we only use the smaller
// tables.
// Build lookup tables for each point
tables := make([]NafLookupTable5, len(points))
for i := range tables {
tables[i].FromP3(points[i])
}
// Compute a NAF for each scalar
nafs := make([][256]int8, len(scalars))
for i := range nafs {
nafs[i] = scalars[i].NonAdjacentForm(5)
}
multiple := &ProjCached{}
tmp1 := &ProjP1xP1{}
tmp2 := &ProjP2{}
tmp2.Zero()
v.Zero()
// Move from high to low bits, doubling the accumulator
// at each iteration and checking whether there is a nonzero
// coefficient to look up a multiple of.
//
// Skip trying to find the first nonzero coefficent, because
// searching might be more work than a few extra doublings.
for i := 255; i >= 0; i-- {
tmp1.Double(tmp2)
for j := range nafs {
if nafs[j][i] > 0 {
v.FromP1xP1(tmp1)
tables[j].SelectInto(multiple, nafs[j][i])
tmp1.Add(v, multiple)
} else if nafs[j][i] < 0 {
v.FromP1xP1(tmp1)
tables[j].SelectInto(multiple, -nafs[j][i])
tmp1.Sub(v, multiple)
}
}
tmp2.FromP1xP1(tmp1)
}
v.FromP2(tmp2)
return v
}

View File

@ -189,3 +189,27 @@ func TestVartimeDoubleBaseMulMatchesBasepointMul(t *testing.T) {
t.Error(err)
}
}
func TestVartimeMultiScalarMulMatchesBasepointMul(t *testing.T) {
vartimeMultiScalarMulMatchesBasepointMul := func(x, y, z scalar.Scalar) bool {
// FIXME opaque scalars
x[31] &= 127
y[31] &= 127
z[31] &= 127
var p, q1, q2, q3, check ProjP3
p.VartimeMultiscalarMul([]scalar.Scalar{x, y, z}, []*ProjP3{&B, &B, &B})
q1.BasepointMul(&x)
q2.BasepointMul(&y)
q3.BasepointMul(&z)
check.Zero()
check.Add(&q1, &q2).Add(&check, &q3)
return p.Equal(&check) == 1
}
if err := quick.Check(vartimeMultiScalarMulMatchesBasepointMul, quickCheckConfig); err != nil {
t.Error(err)
}
}