mirror of https://github.com/gtank/ristretto255
internal/ed25519: add constant-time variable-base scmul.
This also adds stub functions for the other scalar mul functionality.
This commit is contained in:
parent
af6c23d070
commit
95e035b5e5
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2019 Henry de Valence.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package edwards25519
|
||||
|
||||
import (
|
||||
"github.com/gtank/ristretto255/internal/scalar"
|
||||
)
|
||||
|
||||
// Set v to x*B, where B is the Ed25519 basepoint, and return v.
|
||||
//
|
||||
// The scalar multiplication is done in constant time.
|
||||
func (v *ProjP3) BasepointMul(x *scalar.Scalar) *ProjP3 {
|
||||
panic("unimplemented")
|
||||
return v
|
||||
}
|
||||
|
||||
// Set v to x*Q, and return v. v and q may alias.
|
||||
//
|
||||
// The scalar multiplication is done in constant time.
|
||||
func (v *ProjP3) ScalarMul(x *scalar.Scalar, q *ProjP3) *ProjP3 {
|
||||
var table ProjLookupTable
|
||||
table.FromP3(q)
|
||||
// v and q could alias, but once the table is built we can clobber v.
|
||||
v.Zero()
|
||||
|
||||
// Write x = sum(x_i * 16^i)
|
||||
// so x*Q = sum( Q*x_i*16^i )
|
||||
// = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... )
|
||||
// <------compute inside out---------
|
||||
//
|
||||
// We use the lookup table to get the x_i*Q values
|
||||
// and do four doublings to compute 16*Q
|
||||
digits := x.SignedRadix16()
|
||||
|
||||
// Unwrap first loop iteration to save computing 16*identity
|
||||
multiple := &ProjCached{}
|
||||
tmp1 := &ProjP1xP1{}
|
||||
tmp2 := &ProjP2{}
|
||||
table.SelectInto(multiple, digits[63])
|
||||
tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords
|
||||
for i := 62; i >= 0; i-- {
|
||||
tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords
|
||||
tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords
|
||||
tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords
|
||||
tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords
|
||||
tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords
|
||||
v.FromP1xP1(tmp1) // v = 16*(prev) in P3 coords
|
||||
table.SelectInto(multiple, digits[i])
|
||||
tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords
|
||||
}
|
||||
v.FromP1xP1(tmp1)
|
||||
return v
|
||||
}
|
||||
|
||||
// Set v to a*A + b*B, where B is the Ed25519 basepoint, and return v.
|
||||
//
|
||||
// The scalar multiplication is done in variable time.
|
||||
func (v *ProjP3) VartimeDoubleBaseMul(a, b *scalar.Scalar, A *ProjP3) *ProjP3 {
|
||||
panic("unimplemented")
|
||||
return v
|
||||
}
|
||||
|
||||
// Set v to the result of a multiscalar multiplication and return v.
|
||||
//
|
||||
// The multiscalar multiplication is sum(scalars[i]*points[i]).
|
||||
//
|
||||
// The multiscalar multiplication is performed in constant time.
|
||||
func (v *ProjP3) MultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *ProjP3 {
|
||||
panic("unimplemented")
|
||||
return v
|
||||
}
|
||||
|
||||
// Set v to the result of a multiscalar multiplication and return v.
|
||||
//
|
||||
// The multiscalar multiplication is sum(scalars[i]*points[i]).
|
||||
//
|
||||
// The multiscalar multiplication is performed in variable time.
|
||||
func (v *ProjP3) VartimeMultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *ProjP3 {
|
||||
panic("unimplemented")
|
||||
return v
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package edwards25519
|
||||
|
||||
import (
|
||||
"github.com/gtank/ristretto255/internal/radix51"
|
||||
"github.com/gtank/ristretto255/internal/scalar"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
// quickCheckConfig will make each quickcheck test run (1024 * -quickchecks)
|
||||
// times. The default value of -quickchecks is 100.
|
||||
var (
|
||||
quickCheckConfig = &quick.Config{MaxCountScale: 1 << 10}
|
||||
)
|
||||
|
||||
func TestScalarMulSmallScalars(t *testing.T) {
|
||||
var z scalar.Scalar
|
||||
var p, check ProjP3
|
||||
p.ScalarMul(&z, &B)
|
||||
check.Zero()
|
||||
if check.Equal(&p) != 1 {
|
||||
t.Error("0*B != 0")
|
||||
}
|
||||
|
||||
z = scalar.Scalar([32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
|
||||
p.ScalarMul(&z, &B)
|
||||
check.Set(&B)
|
||||
if check.Equal(&p) != 1 {
|
||||
t.Error("1*B != 1")
|
||||
}
|
||||
}
|
||||
|
||||
func TestScalarMulVsDalek(t *testing.T) {
|
||||
expected := ProjP3{
|
||||
X: radix51.FieldElement([5]uint64{778774234987948, 1589187156384239, 1213330452914652, 186161118421127, 2186284806803213}),
|
||||
Y: radix51.FieldElement([5]uint64{1241255309069369, 1115278942994853, 1016511918109334, 1303231926552315, 1801448517689873}),
|
||||
Z: radix51.FieldElement([5]uint64{353337085654440, 1327844406437681, 2207296012811921, 707394926933424, 917408459573183}),
|
||||
T: radix51.FieldElement([5]uint64{585487439439725, 1792815221887900, 946062846079052, 1954901232609667, 1418300670001780}),
|
||||
}
|
||||
z := scalar.Scalar([32]byte{219, 106, 114, 9, 174, 249, 155, 89, 69, 203, 201, 93, 92, 116, 234, 187, 78, 115, 103, 172, 182, 98, 62, 103, 187, 136, 13, 100, 248, 110, 12, 4})
|
||||
|
||||
var p ProjP3
|
||||
p.ScalarMul(&z, &B)
|
||||
if expected.Equal(&p) != 1 {
|
||||
t.Error("Scalar mul does not match dalek")
|
||||
}
|
||||
}
|
||||
|
||||
func TestScalarMulDistributesOverAdd(t *testing.T) {
|
||||
scalarMulDistributesOverAdd := func(x, y scalar.Scalar) bool {
|
||||
// The quickcheck generation strategy chooses a random
|
||||
// 32-byte array, but we require that the high bit is
|
||||
// unset. FIXME: make Scalar opaque. Until then,
|
||||
// mask the high bits:
|
||||
x[31] &= 127
|
||||
y[31] &= 127
|
||||
var z scalar.Scalar
|
||||
z.Add(&x, &y)
|
||||
var p, q, r, check ProjP3
|
||||
p.ScalarMul(&x, &B)
|
||||
q.ScalarMul(&y, &B)
|
||||
r.ScalarMul(&z, &B)
|
||||
check.Add(&p, &q)
|
||||
return check.Equal(&r) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(scalarMulDistributesOverAdd, quickCheckConfig); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue