Compare commits

...

2 commits

6 changed files with 185 additions and 4 deletions

View file

@ -7,7 +7,7 @@ package edwards25519
import (
"errors"
"filippo.io/edwards25519/field"
"git.gammaspectra.live/P2Pool/edwards25519/field"
)
// Point types.

View file

@ -11,7 +11,7 @@ import (
"strings"
"testing"
"filippo.io/edwards25519/field"
"git.gammaspectra.live/P2Pool/edwards25519/field"
)
var B = NewGeneratorPoint()

View file

@ -10,7 +10,7 @@ package edwards25519
import (
"errors"
"filippo.io/edwards25519/field"
"git.gammaspectra.live/P2Pool/edwards25519/field"
)
// ExtendedCoordinates returns v in extended coordinates (X:Y:Z:T) where

2
go.mod
View file

@ -1,3 +1,3 @@
module filippo.io/edwards25519
module git.gammaspectra.live/P2Pool/edwards25519
go 1.17

81
unsafe.go Normal file
View 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
View 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)
}
}