Added unsafe VarTime methods for ScalarMult, ScalarBaseMult
This commit is contained in:
parent
8c58ed0e35
commit
e42c4b5eb9
81
unsafe.go
Normal file
81
unsafe.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package edwards25519
|
||||
|
||||
// UnsafeVarTimeScalarMult sets v = x * q, and returns v., and returns v. Execution time depends on the inputs.
|
||||
// Deprecated: Unsafe for private operations
|
||||
func (v *Point) UnsafeVarTimeScalarMult(x *Scalar, q *Point) *Point {
|
||||
checkInitialized(q)
|
||||
|
||||
// Build lookup table for point q
|
||||
var table nafLookupTable5
|
||||
table.FromP3(q)
|
||||
// Compute a NAF for scalar x
|
||||
naf := x.nonAdjacentForm(5)
|
||||
|
||||
multiple := &projCached{}
|
||||
tmp1 := &projP1xP1{}
|
||||
tmp2 := &projP2{}
|
||||
tmp2.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)
|
||||
if naf[i] > 0 {
|
||||
v.fromP1xP1(tmp1)
|
||||
table.SelectInto(multiple, naf[i])
|
||||
tmp1.Add(v, multiple)
|
||||
} else if naf[i] < 0 {
|
||||
v.fromP1xP1(tmp1)
|
||||
table.SelectInto(multiple, -naf[i])
|
||||
tmp1.Sub(v, multiple)
|
||||
}
|
||||
|
||||
tmp2.FromP1xP1(tmp1)
|
||||
}
|
||||
|
||||
v.fromP2(tmp2)
|
||||
return v
|
||||
}
|
||||
|
||||
// UnsafeVarTimeScalarBaseMult sets v = x * B, where B is the canonical generator, and returns v. Execution time depends on the inputs.
|
||||
// Deprecated: Unsafe for private operations
|
||||
// This is not faster than ScalarBaseMult
|
||||
func (v *Point) UnsafeVarTimeScalarBaseMult(x *Scalar) *Point {
|
||||
basepointNafTable := basepointNafTable()
|
||||
// Because the basepoint is fixed, we can use a wider NAF
|
||||
// corresponding to a bigger table.
|
||||
naf := x.nonAdjacentForm(8)
|
||||
|
||||
multiple := &affineCached{}
|
||||
tmp1 := &projP1xP1{}
|
||||
tmp2 := &projP2{}
|
||||
tmp2.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)
|
||||
if naf[i] > 0 {
|
||||
v.fromP1xP1(tmp1)
|
||||
basepointNafTable.SelectInto(multiple, naf[i])
|
||||
tmp1.AddAffine(v, multiple)
|
||||
} else if naf[i] < 0 {
|
||||
v.fromP1xP1(tmp1)
|
||||
basepointNafTable.SelectInto(multiple, -naf[i])
|
||||
tmp1.SubAffine(v, multiple)
|
||||
}
|
||||
|
||||
tmp2.FromP1xP1(tmp1)
|
||||
}
|
||||
|
||||
v.fromP2(tmp2)
|
||||
return v
|
||||
}
|
100
unsafe_test.go
Normal file
100
unsafe_test.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
package edwards25519
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
func TestUnsafeVarTimeScalarMultMatchesScalarBaseMult(t *testing.T) {
|
||||
unsafeVarTimeScalarMultMatchesScalarMult := func(x Scalar) bool {
|
||||
var p, check Point
|
||||
|
||||
p.UnsafeVarTimeScalarMult(&x, B)
|
||||
|
||||
check.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &check)
|
||||
return p.Equal(&check) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarMultMatchesScalarMult, quickCheckConfig32); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsafeVarTimeScalarBaseMultMatchesScalarBaseMult(t *testing.T) {
|
||||
unsafeVarTimeScalarBaseMultMatchesScalarMult := func(x Scalar) bool {
|
||||
var p, check Point
|
||||
|
||||
p.UnsafeVarTimeScalarBaseMult(&x)
|
||||
|
||||
check.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &check)
|
||||
return p.Equal(&check) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarBaseMultMatchesScalarMult, quickCheckConfig32); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsafeVarTimeScalarMultNonIdentityPoint(t *testing.T) {
|
||||
// Check whether p.ScalarMult and q.ScalaBaseMult give the same,
|
||||
// when p and q are originally set to the base point.
|
||||
|
||||
unsafeVarTimeScalarMultNonIdentityPoint := func(x Scalar) bool {
|
||||
var p, q Point
|
||||
p.Set(B)
|
||||
q.Set(B)
|
||||
|
||||
p.UnsafeVarTimeScalarMult(&x, B)
|
||||
q.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &q)
|
||||
|
||||
return p.Equal(&q) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarMultNonIdentityPoint, quickCheckConfig32); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsafeVarTimeScalarBaseMultNonIdentityPoint(t *testing.T) {
|
||||
// Check whether p.ScalarMult and q.ScalaBaseMult give the same,
|
||||
// when p and q are originally set to the base point.
|
||||
|
||||
unsafeVarTimeScalarBaseMultNonIdentityPoint := func(x Scalar) bool {
|
||||
var p, q Point
|
||||
p.Set(B)
|
||||
q.Set(B)
|
||||
|
||||
p.UnsafeVarTimeScalarBaseMult(&x)
|
||||
q.ScalarBaseMult(&x)
|
||||
|
||||
checkOnCurve(t, &p, &q)
|
||||
|
||||
return p.Equal(&q) == 1
|
||||
}
|
||||
|
||||
if err := quick.Check(unsafeVarTimeScalarBaseMultNonIdentityPoint, quickCheckConfig32); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnsafeVarTimeScalarMult(b *testing.B) {
|
||||
var p Point
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.UnsafeVarTimeScalarMult(dalekScalar, B)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnsafeVarTimeScalarBaseMult(b *testing.B) {
|
||||
var p Point
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.UnsafeVarTimeScalarBaseMult(dalekScalar)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue