Added PointTablePrecompute / UnsafeVarTimeScalarMultPrecomputed

This commit is contained in:
DataHoarder 2024-04-05 10:38:45 +02:00
parent a67b1e9d0a
commit e2f706cb5c
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
3 changed files with 102 additions and 0 deletions

18
precomp.go Normal file
View file

@ -0,0 +1,18 @@
package edwards25519
type PrecomputedTable [32]affineLookupTable
func PointTablePrecompute(q *Point) *PrecomputedTable {
p := new(Point)
p.Set(q)
var table PrecomputedTable
for i := 0; i < 32; i++ {
table[i].FromP3(p)
for j := 0; j < 8; j++ {
p.Add(p, p)
}
}
return &table
}

View file

@ -105,6 +105,55 @@ func (v *Point) UnsafeVarTimeScalarBaseMult(x *Scalar) *Point {
return v
}
// UnsafeVarTimeScalarMultPrecomputed sets v = x * q, and returns v., and returns v. Execution time depends on the inputs.
// Deprecated: Unsafe for private operations
func (v *Point) UnsafeVarTimeScalarMultPrecomputed(x *Scalar, table *PrecomputedTable) *Point {
// Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i )
// as described in the Ed25519 paper
//
// Group even and odd coefficients
// x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
// + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B
// x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B
// + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B)
//
// We use a lookup table for each i to get x_i*16^(2*i)*B
// and do four doublings to multiply by 16.
digits := x.signedRadix16()
multiple := &affineCached{}
tmp1 := &projP1xP1{}
tmp2 := &projP2{}
// Accumulate the odd components first
v.Set(NewIdentityPoint())
for i := 1; i < 64; i += 2 {
table[i/2].UnsafeVarTimeSelectInto(multiple, digits[i])
tmp1.AddAffine(v, multiple)
v.fromP1xP1(tmp1)
}
// Multiply by 16
tmp2.FromP3(v) // tmp2 = v in P2 coords
tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords
tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords
tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords
tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords
tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords
tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords
tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords
v.fromP1xP1(tmp1) // now v = 16*(odd components)
// Accumulate the even components
for i := 0; i < 64; i += 2 {
table[i/2].UnsafeVarTimeSelectInto(multiple, digits[i])
tmp1.AddAffine(v, multiple)
v.fromP1xP1(tmp1)
}
return v
}
// Set dest to x*Q, where -8 <= x <= 8, in variable time.
// Deprecated: Unsafe for private operations
func (v *affineLookupTable) UnsafeVarTimeSelectInto(dest *affineCached, x int8) {

View file

@ -61,6 +61,29 @@ func TestUnsafeVarTimeScalarMultNonIdentityPoint(t *testing.T) {
}
}
func TestUnsafeVarTimeScalarMultPrecomputedNonIdentityPoint(t *testing.T) {
// Check whether p.ScalarMult and q.ScalaBaseMult give the same,
// when p and q are originally set to the base point.
table := PointTablePrecompute(B)
unsafeVarTimeScalarMultPrecomputedNonIdentityPoint := func(x Scalar) bool {
var p, q Point
q.Set(B)
p.UnsafeVarTimeScalarMultPrecomputed(&x, table)
q.ScalarBaseMult(&x)
checkOnCurve(t, &p, &q)
return p.Equal(&q) == 1
}
if err := quick.Check(unsafeVarTimeScalarMultPrecomputedNonIdentityPoint, quickCheckConfig(32)); 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.
@ -98,3 +121,15 @@ func BenchmarkUnsafeVarTimeScalarBaseMult(b *testing.B) {
p.UnsafeVarTimeScalarBaseMult(dalekScalar)
}
}
func BenchmarkUnsafeVarTimeScalarMultPrecomputed(b *testing.B) {
var p Point
table := PointTablePrecompute(B)
b.ResetTimer()
for i := 0; i < b.N; i++ {
p.UnsafeVarTimeScalarMultPrecomputed(dalekScalar, table)
}
}