internal/edwards25519,internal/scalar: apply some Go style touches

Including unexporting the table types (which are not used in any API) to
declutter the godoc page.
This commit is contained in:
Filippo Valsorda 2019-05-12 03:05:41 -04:00
parent 24394cb387
commit 4baac9a766
9 changed files with 109 additions and 81 deletions

View File

@ -18,7 +18,7 @@ import (
// D is a constant in the curve equation. // D is a constant in the curve equation.
var D = &radix51.FieldElement{929955233495203, 466365720129213, var D = &radix51.FieldElement{929955233495203, 466365720129213,
1662059464998953, 2033849074728123, 1442794654840575} 1662059464998953, 2033849074728123, 1442794654840575}
var D2 = new(radix51.FieldElement).Add(D, D) var d2 = new(radix51.FieldElement).Add(D, D)
// Point types. // Point types.
@ -129,14 +129,14 @@ func (v *ProjCached) FromP3(p *ProjP3) *ProjCached {
v.YplusX.Add(&p.Y, &p.X) v.YplusX.Add(&p.Y, &p.X)
v.YminusX.Sub(&p.Y, &p.X) v.YminusX.Sub(&p.Y, &p.X)
v.Z.Set(&p.Z) v.Z.Set(&p.Z)
v.T2d.Mul(&p.T, D2) v.T2d.Mul(&p.T, d2)
return v return v
} }
func (v *AffineCached) FromP3(p *ProjP3) *AffineCached { func (v *AffineCached) FromP3(p *ProjP3) *AffineCached {
v.YplusX.Add(&p.Y, &p.X) v.YplusX.Add(&p.Y, &p.X)
v.YminusX.Sub(&p.Y, &p.X) v.YminusX.Sub(&p.Y, &p.X)
v.T2d.Mul(&p.T, D2) v.T2d.Mul(&p.T, d2)
var invZ radix51.FieldElement var invZ radix51.FieldElement
invZ.Invert(&p.Z) invZ.Invert(&p.Z)

View File

@ -1,8 +1,13 @@
// Copyright 2019 Henry de Valence. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package edwards25519 package edwards25519
import ( import (
"github.com/gtank/ristretto255/internal/radix51"
"testing" "testing"
"github.com/gtank/ristretto255/internal/radix51"
) )
var ( var (

View File

@ -62,7 +62,7 @@ func (v *ProjP3) BasepointMul(x *scalar.Scalar) *ProjP3 {
// //
// The scalar multiplication is done in constant time. // The scalar multiplication is done in constant time.
func (v *ProjP3) ScalarMul(x *scalar.Scalar, q *ProjP3) *ProjP3 { func (v *ProjP3) ScalarMul(x *scalar.Scalar, q *ProjP3) *ProjP3 {
var table ProjLookupTable var table projLookupTable
table.FromP3(q) table.FromP3(q)
// v and q could alias, but once the table is built we can clobber v. // v and q could alias, but once the table is built we can clobber v.
v.Zero() v.Zero()
@ -113,7 +113,7 @@ func (v *ProjP3) MultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *Proj
// between each point in the multiscalar equation. // between each point in the multiscalar equation.
// Build lookup tables for each point // Build lookup tables for each point
tables := make([]ProjLookupTable, len(points)) tables := make([]projLookupTable, len(points))
for i := range tables { for i := range tables {
tables[i].FromP3(points[i]) tables[i].FromP3(points[i])
} }
@ -172,7 +172,7 @@ func (v *ProjP3) VartimeDoubleBaseMul(a *scalar.Scalar, A *ProjP3, b *scalar.Sca
// "mass" of the scalar onto sparse coefficients (meaning // "mass" of the scalar onto sparse coefficients (meaning
// fewer additions). // fewer additions).
var aTable NafLookupTable5 var aTable nafLookupTable5
aTable.FromP3(A) aTable.FromP3(A)
// Because the basepoint is fixed, we can use a wider NAF // Because the basepoint is fixed, we can use a wider NAF
// corresponding to a bigger table. // corresponding to a bigger table.
@ -243,7 +243,7 @@ func (v *ProjP3) VartimeMultiscalarMul(scalars []scalar.Scalar, points []*ProjP3
// tables. // tables.
// Build lookup tables for each point // Build lookup tables for each point
tables := make([]NafLookupTable5, len(points)) tables := make([]nafLookupTable5, len(points))
for i := range tables { for i := range tables {
tables[i].FromP3(points[i]) tables[i].FromP3(points[i])
} }

View File

@ -1,10 +1,15 @@
// Copyright 2019 Henry de Valence. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package edwards25519 package edwards25519
import ( import (
"github.com/gtank/ristretto255/internal/radix51"
"github.com/gtank/ristretto255/internal/scalar"
"testing" "testing"
"testing/quick" "testing/quick"
"github.com/gtank/ristretto255/internal/radix51"
"github.com/gtank/ristretto255/internal/scalar"
) )
// quickCheckConfig will make each quickcheck test run (2^6 * -quickchecks) // quickCheckConfig will make each quickcheck test run (2^6 * -quickchecks)
@ -93,14 +98,14 @@ func TestScalarMulDistributesOverAdd(t *testing.T) {
} }
func TestBasepointTableGeneration(t *testing.T) { func TestBasepointTableGeneration(t *testing.T) {
// The basepoint table is 32 AffineLookupTables, // The basepoint table is 32 affineLookupTables,
// corresponding to (16^2i)*B for table i. // corresponding to (16^2i)*B for table i.
tmp1 := &ProjP1xP1{} tmp1 := &ProjP1xP1{}
tmp2 := &ProjP2{} tmp2 := &ProjP2{}
tmp3 := &ProjP3{} tmp3 := &ProjP3{}
tmp3.Set(&B) tmp3.Set(&B)
table := make([]AffineLookupTable, 32) table := make([]affineLookupTable, 32)
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
// Build the table // Build the table
table[i].FromP3(tmp3) table[i].FromP3(tmp3)
@ -160,7 +165,7 @@ func TestMultiScalarMulMatchesBasepointMul(t *testing.T) {
} }
func TestBasepointNafTableGeneration(t *testing.T) { func TestBasepointNafTableGeneration(t *testing.T) {
var table NafLookupTable8 var table nafLookupTable8
table.FromP3(&B) table.FromP3(&B)
if table != basepointNafTable { if table != basepointNafTable {

File diff suppressed because one or more lines are too long

View File

@ -9,29 +9,29 @@ import (
) )
// A dynamic lookup table for variable-base, constant-time scalar muls. // A dynamic lookup table for variable-base, constant-time scalar muls.
type ProjLookupTable struct { type projLookupTable struct {
points [8]ProjCached points [8]ProjCached
} }
// A precomputed lookup table for fixed-base, constant-time scalar muls. // A precomputed lookup table for fixed-base, constant-time scalar muls.
type AffineLookupTable struct { type affineLookupTable struct {
points [8]AffineCached points [8]AffineCached
} }
// A dynamic lookup table for variable-base, variable-time scalar muls. // A dynamic lookup table for variable-base, variable-time scalar muls.
type NafLookupTable5 struct { type nafLookupTable5 struct {
points [8]ProjCached points [8]ProjCached
} }
// A precomputed lookup table for fixed-base, variable-time scalar muls. // A precomputed lookup table for fixed-base, variable-time scalar muls.
type NafLookupTable8 struct { type nafLookupTable8 struct {
points [64]AffineCached points [64]AffineCached
} }
// Constructors. // Constructors.
// Builds a lookup table at runtime. Fast. // Builds a lookup table at runtime. Fast.
func (v *ProjLookupTable) FromP3(q *ProjP3) { func (v *projLookupTable) FromP3(q *ProjP3) {
// Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
// This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
v.points[0].FromP3(q) v.points[0].FromP3(q)
@ -46,7 +46,7 @@ func (v *ProjLookupTable) FromP3(q *ProjP3) {
} }
// This is not optimised for speed; affine tables should be precomputed. // This is not optimised for speed; affine tables should be precomputed.
func (v *AffineLookupTable) FromP3(q *ProjP3) { func (v *affineLookupTable) FromP3(q *ProjP3) {
// Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
// This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
v.points[0].FromP3(q) v.points[0].FromP3(q)
@ -59,7 +59,7 @@ func (v *AffineLookupTable) FromP3(q *ProjP3) {
} }
// Builds a lookup table at runtime. Fast. // Builds a lookup table at runtime. Fast.
func (v *NafLookupTable5) FromP3(q *ProjP3) { func (v *nafLookupTable5) FromP3(q *ProjP3) {
// Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q // Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q
// This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q // This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q
v.points[0].FromP3(q) v.points[0].FromP3(q)
@ -73,7 +73,7 @@ func (v *NafLookupTable5) FromP3(q *ProjP3) {
} }
// This is not optimised for speed; affine tables should be precomputed. // This is not optimised for speed; affine tables should be precomputed.
func (v *NafLookupTable8) FromP3(q *ProjP3) { func (v *nafLookupTable8) FromP3(q *ProjP3) {
v.points[0].FromP3(q) v.points[0].FromP3(q)
q2 := ProjP3{} q2 := ProjP3{}
q2.Add(q, q) q2.Add(q, q)
@ -87,7 +87,7 @@ func (v *NafLookupTable8) FromP3(q *ProjP3) {
// Selectors. // Selectors.
// Set dest to x*Q, where -8 <= x <= 8, in constant time. // Set dest to x*Q, where -8 <= x <= 8, in constant time.
func (v *ProjLookupTable) SelectInto(dest *ProjCached, x int8) { func (v *projLookupTable) SelectInto(dest *ProjCached, x int8) {
// Compute xabs = |x| // Compute xabs = |x|
xmask := x >> 7 xmask := x >> 7
xabs := uint8((x + xmask) ^ xmask) xabs := uint8((x + xmask) ^ xmask)
@ -103,7 +103,7 @@ func (v *ProjLookupTable) SelectInto(dest *ProjCached, x int8) {
} }
// Set dest to x*Q, where -8 <= x <= 8, in constant time. // Set dest to x*Q, where -8 <= x <= 8, in constant time.
func (v *AffineLookupTable) SelectInto(dest *AffineCached, x int8) { func (v *affineLookupTable) SelectInto(dest *AffineCached, x int8) {
// Compute xabs = |x| // Compute xabs = |x|
xmask := x >> 7 xmask := x >> 7
xabs := uint8((x + xmask) ^ xmask) xabs := uint8((x + xmask) ^ xmask)
@ -119,11 +119,11 @@ func (v *AffineLookupTable) SelectInto(dest *AffineCached, x int8) {
} }
// Given odd x with 0 < x < 2^4, return x*Q (in variable time). // Given odd x with 0 < x < 2^4, return x*Q (in variable time).
func (v *NafLookupTable5) SelectInto(dest *ProjCached, x int8) { func (v *nafLookupTable5) SelectInto(dest *ProjCached, x int8) {
*dest = v.points[x/2] *dest = v.points[x/2]
} }
// Given odd x with 0 < x < 2^7, return x*Q (in variable time). // Given odd x with 0 < x < 2^7, return x*Q (in variable time).
func (v *NafLookupTable8) SelectInto(dest *AffineCached, x int8) { func (v *nafLookupTable8) SelectInto(dest *AffineCached, x int8) {
*dest = v.points[x/2] *dest = v.points[x/2]
} }

View File

@ -1,3 +1,7 @@
// Copyright 2019 Henry de Valence. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package edwards25519 package edwards25519
import ( import (
@ -5,7 +9,7 @@ import (
) )
func TestProjLookupTable(t *testing.T) { func TestProjLookupTable(t *testing.T) {
var table ProjLookupTable var table projLookupTable
table.FromP3(&B) table.FromP3(&B)
var tmp1, tmp2, tmp3 ProjCached var tmp1, tmp2, tmp3 ProjCached
@ -32,7 +36,7 @@ func TestProjLookupTable(t *testing.T) {
} }
func TestAffineLookupTable(t *testing.T) { func TestAffineLookupTable(t *testing.T) {
var table AffineLookupTable var table affineLookupTable
table.FromP3(&B) table.FromP3(&B)
var tmp1, tmp2, tmp3 AffineCached var tmp1, tmp2, tmp3 AffineCached
@ -59,7 +63,7 @@ func TestAffineLookupTable(t *testing.T) {
} }
func TestNafLookupTable5(t *testing.T) { func TestNafLookupTable5(t *testing.T) {
var table NafLookupTable5 var table nafLookupTable5
table.FromP3(&B) table.FromP3(&B)
var tmp1, tmp2, tmp3, tmp4 ProjCached var tmp1, tmp2, tmp3, tmp4 ProjCached
@ -85,12 +89,12 @@ func TestNafLookupTable5(t *testing.T) {
rhs.FromP1xP1(&accP1xP1) rhs.FromP1xP1(&accP1xP1)
if lhs.Equal(&rhs) != 1 { if lhs.Equal(&rhs) != 1 {
t.Errorf("Sanity check on NafLookupTable5 failed") t.Errorf("Sanity check on nafLookupTable5 failed")
} }
} }
func TestNafLookupTable8(t *testing.T) { func TestNafLookupTable8(t *testing.T) {
var table NafLookupTable8 var table nafLookupTable8
table.FromP3(&B) table.FromP3(&B)
var tmp1, tmp2, tmp3, tmp4 AffineCached var tmp1, tmp2, tmp3, tmp4 AffineCached
@ -116,6 +120,6 @@ func TestNafLookupTable8(t *testing.T) {
rhs.FromP1xP1(&accP1xP1) rhs.FromP1xP1(&accP1xP1)
if lhs.Equal(&rhs) != 1 { if lhs.Equal(&rhs) != 1 {
t.Errorf("Sanity check on NafLookupTable8 failed") t.Errorf("Sanity check on nafLookupTable8 failed")
} }
} }

View File

@ -1,4 +1,9 @@
// A ristretto255 scalar is an element of the group of order l = 2^252 + 27742317777372353535851937790883648493. // Copyright 2016 The Go Authors. All rights reserved.
// Copyright 2019 Henry de Valence. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package scalar implements the ristretto255 scalar group.
package scalar package scalar
import ( import (
@ -6,7 +11,9 @@ import (
"encoding/binary" "encoding/binary"
) )
// A ristretto255 scalar is an element of the group of order l = 2^252 + 27742317777372353535851937790883648493, here represented as an opaque little-endian byte string. // A Scalar is an element of the group of order
// l = 2^252 + 27742317777372353535851937790883648493,
// here represented as an opaque little-endian byte string.
type Scalar [32]byte type Scalar [32]byte
var ( var (
@ -45,10 +52,11 @@ func (s *Scalar) Mul(x, y *Scalar) *Scalar {
return s return s
} }
// FromBytes sets s = x mod l, where x should be should be 64 bytes of uniform randomness. // FromBytes sets s = x mod l, where x should be 64 bytes of uniform randomness
func (s *Scalar) FromBytes(in []byte) *Scalar { // interpreted in little-endian.
func (s *Scalar) FromBytes(x []byte) *Scalar {
var wideBytes [64]byte var wideBytes [64]byte
copy(wideBytes[:], in[:]) copy(wideBytes[:], x[:])
scReduce(s, &wideBytes) scReduce(s, &wideBytes)
return s return s
} }
@ -78,11 +86,11 @@ func (s *Scalar) IsCanonical() bool {
} }
// Equal returns 1 if v and u are equal, and 0 otherwise. // Equal returns 1 if v and u are equal, and 0 otherwise.
func (v *Scalar) Equal(u *Scalar) int { func (s *Scalar) Equal(u *Scalar) int {
var sa, sv [32]byte var su, ss [32]byte
u.Bytes(sa[:0]) u.Bytes(su[:0])
v.Bytes(sv[:0]) s.Bytes(ss[:0])
return subtle.ConstantTimeCompare(sa[:], sv[:]) return subtle.ConstantTimeCompare(su[:], ss[:])
} }
// sliceForAppend extends the input slice by n bytes. head is the full extended // sliceForAppend extends the input slice by n bytes. head is the full extended
@ -100,16 +108,14 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) {
} }
func load3(in []byte) int64 { func load3(in []byte) int64 {
var r int64 r := int64(in[0])
r = int64(in[0])
r |= int64(in[1]) << 8 r |= int64(in[1]) << 8
r |= int64(in[2]) << 16 r |= int64(in[2]) << 16
return r return r
} }
func load4(in []byte) int64 { func load4(in []byte) int64 {
var r int64 r := int64(in[0])
r = int64(in[0])
r |= int64(in[1]) << 8 r |= int64(in[1]) << 8
r |= int64(in[2]) << 16 r |= int64(in[2]) << 16
r |= int64(in[3]) << 24 r |= int64(in[3]) << 24
@ -876,7 +882,7 @@ func scReduce(out *Scalar, s *[64]byte) {
// order is the order of Curve25519 in little-endian form. // order is the order of Curve25519 in little-endian form.
var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000}
// ScMinimal returns true if the given scalar is less than the order of the // scMinimal returns true if the given scalar is less than the order of the
// curve. // curve.
func scMinimal(sc *Scalar) bool { func scMinimal(sc *Scalar) bool {
for i := 3; ; i-- { for i := 3; ; i-- {
@ -893,7 +899,7 @@ func scMinimal(sc *Scalar) bool {
return true return true
} }
// Computes a width-w non-adjacent form for this scalar. // NonAdjacentForm computes a width-w non-adjacent form for this scalar.
func (s *Scalar) NonAdjacentForm(w uint) [256]int8 { func (s *Scalar) NonAdjacentForm(w uint) [256]int8 {
// This implementation is adapted from the one // This implementation is adapted from the one
// in curve25519-dalek and is documented there: // in curve25519-dalek and is documented there:

View File

@ -1,3 +1,7 @@
// Copyright 2019 Henry de Valence. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package scalar package scalar
import ( import (