all: flatten the package and make FieldElement opaque
For the license changes, see gtank/ristretto255-private#28 and gtank/ristretto255#32, that contribute all code in those repositories to the Go project under the Google CLA.
This commit is contained in:
parent
6f5f5828e1
commit
d3569cbbb3
2
LICENSE
2
LICENSE
|
@ -1,6 +1,4 @@
|
||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||||
Copyright (c) 2017 George Tankersley. All rights reserved.
|
|
||||||
Copyright (c) 2019 Henry de Valence. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,16 +6,23 @@
|
||||||
//
|
//
|
||||||
// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2
|
// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2
|
||||||
//
|
//
|
||||||
// This is better known as the Edwards curve equivalent to curve25519, and is
|
// as well as GF(2^255-19) field arithmetic.
|
||||||
|
//
|
||||||
|
// This is better known as the Edwards curve equivalent to Curve25519, and is
|
||||||
// the curve used by the Ed25519 signature scheme.
|
// the curve used by the Ed25519 signature scheme.
|
||||||
|
//
|
||||||
|
// Most users don't need this package, and should instead use crypto/ed25519 for
|
||||||
|
// signatures, golang.org/x/crypto/curve25519 for Diffie-Hellman, or
|
||||||
|
// github.com/gtank/ristretto255 for prime order group logic. However, for
|
||||||
|
// anyone currently using a fork of crypto/ed25519/internal/edwards25519 or
|
||||||
|
// github.com/agl/edwards25519, this package should be a safer, faster, and more
|
||||||
|
// powerful alternative.
|
||||||
package edwards25519
|
package edwards25519
|
||||||
|
|
||||||
import "filippo.io/edwards25519/base"
|
|
||||||
|
|
||||||
// D is a constant in the curve equation.
|
// D is a constant in the curve equation.
|
||||||
var D = &base.FieldElement{929955233495203, 466365720129213,
|
var D = &FieldElement{929955233495203, 466365720129213,
|
||||||
1662059464998953, 2033849074728123, 1442794654840575}
|
1662059464998953, 2033849074728123, 1442794654840575}
|
||||||
var d2 = new(base.FieldElement).Add(D, D)
|
var d2 = new(FieldElement).Add(D, D)
|
||||||
|
|
||||||
// Point types.
|
// Point types.
|
||||||
|
|
||||||
|
@ -25,31 +31,31 @@ var d2 = new(base.FieldElement).Add(D, D)
|
||||||
// https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html
|
// https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html
|
||||||
|
|
||||||
type ProjP1xP1 struct {
|
type ProjP1xP1 struct {
|
||||||
X, Y, Z, T base.FieldElement
|
X, Y, Z, T FieldElement
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjP2 struct {
|
type ProjP2 struct {
|
||||||
X, Y, Z base.FieldElement
|
X, Y, Z FieldElement
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjP3 struct {
|
type ProjP3 struct {
|
||||||
X, Y, Z, T base.FieldElement
|
X, Y, Z, T FieldElement
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjCached struct {
|
type ProjCached struct {
|
||||||
YplusX, YminusX, Z, T2d base.FieldElement
|
YplusX, YminusX, Z, T2d FieldElement
|
||||||
}
|
}
|
||||||
|
|
||||||
type AffineCached struct {
|
type AffineCached struct {
|
||||||
YplusX, YminusX, T2d base.FieldElement
|
YplusX, YminusX, T2d FieldElement
|
||||||
}
|
}
|
||||||
|
|
||||||
// B is the Ed25519 basepoint.
|
// B is the Ed25519 basepoint.
|
||||||
var B = ProjP3{
|
var B = ProjP3{
|
||||||
X: base.FieldElement([5]uint64{1738742601995546, 1146398526822698, 2070867633025821, 562264141797630, 587772402128613}),
|
X: FieldElement{1738742601995546, 1146398526822698, 2070867633025821, 562264141797630, 587772402128613},
|
||||||
Y: base.FieldElement([5]uint64{1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198}),
|
Y: FieldElement{1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198},
|
||||||
Z: base.FieldElement([5]uint64{1, 0, 0, 0, 0}),
|
Z: FieldElement{1, 0, 0, 0, 0},
|
||||||
T: base.FieldElement([5]uint64{1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039}),
|
T: FieldElement{1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructors.
|
// Constructors.
|
||||||
|
@ -144,7 +150,7 @@ func (v *AffineCached) FromP3(p *ProjP3) *AffineCached {
|
||||||
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 base.FieldElement
|
var invZ FieldElement
|
||||||
invZ.Invert(&p.Z)
|
invZ.Invert(&p.Z)
|
||||||
v.YplusX.Mul(&v.YplusX, &invZ)
|
v.YplusX.Mul(&v.YplusX, &invZ)
|
||||||
v.YminusX.Mul(&v.YminusX, &invZ)
|
v.YminusX.Mul(&v.YminusX, &invZ)
|
||||||
|
@ -173,7 +179,7 @@ func (v *ProjP3) Sub(p, q *ProjP3) *ProjP3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ProjP1xP1) Add(p *ProjP3, q *ProjCached) *ProjP1xP1 {
|
func (v *ProjP1xP1) Add(p *ProjP3, q *ProjCached) *ProjP1xP1 {
|
||||||
var YplusX, YminusX, PP, MM, TT2d, ZZ2 base.FieldElement
|
var YplusX, YminusX, PP, MM, TT2d, ZZ2 FieldElement
|
||||||
|
|
||||||
YplusX.Add(&p.Y, &p.X)
|
YplusX.Add(&p.Y, &p.X)
|
||||||
YminusX.Sub(&p.Y, &p.X)
|
YminusX.Sub(&p.Y, &p.X)
|
||||||
|
@ -193,7 +199,7 @@ func (v *ProjP1xP1) Add(p *ProjP3, q *ProjCached) *ProjP1xP1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ProjP1xP1) Sub(p *ProjP3, q *ProjCached) *ProjP1xP1 {
|
func (v *ProjP1xP1) Sub(p *ProjP3, q *ProjCached) *ProjP1xP1 {
|
||||||
var YplusX, YminusX, PP, MM, TT2d, ZZ2 base.FieldElement
|
var YplusX, YminusX, PP, MM, TT2d, ZZ2 FieldElement
|
||||||
|
|
||||||
YplusX.Add(&p.Y, &p.X)
|
YplusX.Add(&p.Y, &p.X)
|
||||||
YminusX.Sub(&p.Y, &p.X)
|
YminusX.Sub(&p.Y, &p.X)
|
||||||
|
@ -213,7 +219,7 @@ func (v *ProjP1xP1) Sub(p *ProjP3, q *ProjCached) *ProjP1xP1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ProjP1xP1) AddAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 {
|
func (v *ProjP1xP1) AddAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 {
|
||||||
var YplusX, YminusX, PP, MM, TT2d, Z2 base.FieldElement
|
var YplusX, YminusX, PP, MM, TT2d, Z2 FieldElement
|
||||||
|
|
||||||
YplusX.Add(&p.Y, &p.X)
|
YplusX.Add(&p.Y, &p.X)
|
||||||
YminusX.Sub(&p.Y, &p.X)
|
YminusX.Sub(&p.Y, &p.X)
|
||||||
|
@ -232,7 +238,7 @@ func (v *ProjP1xP1) AddAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ProjP1xP1) SubAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 {
|
func (v *ProjP1xP1) SubAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 {
|
||||||
var YplusX, YminusX, PP, MM, TT2d, Z2 base.FieldElement
|
var YplusX, YminusX, PP, MM, TT2d, Z2 FieldElement
|
||||||
|
|
||||||
YplusX.Add(&p.Y, &p.X)
|
YplusX.Add(&p.Y, &p.X)
|
||||||
YminusX.Sub(&p.Y, &p.X)
|
YminusX.Sub(&p.Y, &p.X)
|
||||||
|
@ -253,7 +259,7 @@ func (v *ProjP1xP1) SubAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 {
|
||||||
// Doubling.
|
// Doubling.
|
||||||
|
|
||||||
func (v *ProjP1xP1) Double(p *ProjP2) *ProjP1xP1 {
|
func (v *ProjP1xP1) Double(p *ProjP2) *ProjP1xP1 {
|
||||||
var XX, YY, ZZ2, XplusYsq base.FieldElement
|
var XX, YY, ZZ2, XplusYsq FieldElement
|
||||||
|
|
||||||
XX.Square(&p.X)
|
XX.Square(&p.X)
|
||||||
YY.Square(&p.Y)
|
YY.Square(&p.Y)
|
||||||
|
@ -283,7 +289,7 @@ func (v *ProjP3) Neg(p *ProjP3) *ProjP3 {
|
||||||
// by @ebfull
|
// by @ebfull
|
||||||
// https://github.com/dalek-cryptography/curve25519-dalek/pull/226/files
|
// https://github.com/dalek-cryptography/curve25519-dalek/pull/226/files
|
||||||
func (v *ProjP3) Equal(u *ProjP3) int {
|
func (v *ProjP3) Equal(u *ProjP3) int {
|
||||||
var t1, t2, t3, t4 base.FieldElement
|
var t1, t2, t3, t4 FieldElement
|
||||||
t1.Mul(&v.X, &u.Z)
|
t1.Mul(&v.X, &u.Z)
|
||||||
t2.Mul(&u.X, &v.Z)
|
t2.Mul(&u.X, &v.Z)
|
||||||
t3.Mul(&v.Y, &u.Z)
|
t3.Mul(&v.Y, &u.Z)
|
||||||
|
@ -313,14 +319,14 @@ func (v *AffineCached) Select(a, b *AffineCached, cond int) *AffineCached {
|
||||||
|
|
||||||
// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
|
// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
|
||||||
func (v *ProjCached) CondNeg(cond int) *ProjCached {
|
func (v *ProjCached) CondNeg(cond int) *ProjCached {
|
||||||
base.CondSwap(&v.YplusX, &v.YminusX, cond)
|
CondSwap(&v.YplusX, &v.YminusX, cond)
|
||||||
v.T2d.CondNeg(&v.T2d, cond)
|
v.T2d.CondNeg(&v.T2d, cond)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
|
// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0.
|
||||||
func (v *AffineCached) CondNeg(cond int) *AffineCached {
|
func (v *AffineCached) CondNeg(cond int) *AffineCached {
|
||||||
base.CondSwap(&v.YplusX, &v.YminusX, cond)
|
CondSwap(&v.YplusX, &v.YminusX, cond)
|
||||||
v.T2d.CondNeg(&v.T2d, cond)
|
v.T2d.CondNeg(&v.T2d, cond)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2019 Henry de Valence. All rights reserved.
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,8 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package base implements GF(2^255-19) field arithmetic in radix 2^51
|
package edwards25519
|
||||||
// representation. This code is a port of the public domain amd64-51-30k version
|
|
||||||
// of ed25519 from SUPERCOP.
|
|
||||||
//
|
|
||||||
// The interface works similarly to math/big.Int, and all arguments and
|
|
||||||
// receivers are allowed to alias.
|
|
||||||
package base
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
@ -18,15 +11,24 @@ import (
|
||||||
"math/bits"
|
"math/bits"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FieldElement represents an element of the field GF(2^255-19). An element t
|
// FieldElement represents an element of the field GF(2^255-19).
|
||||||
// represents the integer t[0] + t[1]*2^51 + t[2]*2^102 + t[3]*2^153 +
|
|
||||||
// t[4]*2^204.
|
|
||||||
//
|
//
|
||||||
// Between operations, all limbs are expected to be lower than 2^51, except the
|
// This type works similarly to math/big.Int, and all arguments and
|
||||||
// first one, which can be up to 2^255 + 2^13 * 19 due to carry propagation.
|
// receivers are allowed to alias.
|
||||||
//
|
//
|
||||||
// The zero value is a valid zero element.
|
// The zero value is a valid zero element.
|
||||||
type FieldElement [5]uint64
|
type FieldElement struct {
|
||||||
|
// An element t represents the integer
|
||||||
|
// t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204
|
||||||
|
//
|
||||||
|
// Between operations, all limbs are expected to be lower than 2^51, except
|
||||||
|
// l0, which can be up to 2^255 + 2^13 * 19 due to carry propagation.
|
||||||
|
l0 uint64
|
||||||
|
l1 uint64
|
||||||
|
l2 uint64
|
||||||
|
l3 uint64
|
||||||
|
l4 uint64
|
||||||
|
}
|
||||||
|
|
||||||
const maskLow51Bits uint64 = (1 << 51) - 1
|
const maskLow51Bits uint64 = (1 << 51) - 1
|
||||||
|
|
||||||
|
@ -53,19 +55,19 @@ func (v *FieldElement) One() *FieldElement {
|
||||||
// two because of the inliner heuristics. The two functions MUST be called one
|
// two because of the inliner heuristics. The two functions MUST be called one
|
||||||
// after the other.
|
// after the other.
|
||||||
func (v *FieldElement) carryPropagate1() *FieldElement {
|
func (v *FieldElement) carryPropagate1() *FieldElement {
|
||||||
v[1] += v[0] >> 51
|
v.l1 += v.l0 >> 51
|
||||||
v[0] &= maskLow51Bits
|
v.l0 &= maskLow51Bits
|
||||||
v[2] += v[1] >> 51
|
v.l2 += v.l1 >> 51
|
||||||
v[1] &= maskLow51Bits
|
v.l1 &= maskLow51Bits
|
||||||
v[3] += v[2] >> 51
|
v.l3 += v.l2 >> 51
|
||||||
v[2] &= maskLow51Bits
|
v.l2 &= maskLow51Bits
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
func (v *FieldElement) carryPropagate2() *FieldElement {
|
func (v *FieldElement) carryPropagate2() *FieldElement {
|
||||||
v[4] += v[3] >> 51
|
v.l4 += v.l3 >> 51
|
||||||
v[3] &= maskLow51Bits
|
v.l3 &= maskLow51Bits
|
||||||
v[0] += (v[4] >> 51) * 19
|
v.l0 += (v.l4 >> 51) * 19
|
||||||
v[4] &= maskLow51Bits
|
v.l4 &= maskLow51Bits
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,37 +80,37 @@ func (v *FieldElement) reduce() *FieldElement {
|
||||||
|
|
||||||
// If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1,
|
// If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1,
|
||||||
// generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise.
|
// generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise.
|
||||||
c := (v[0] + 19) >> 51
|
c := (v.l0 + 19) >> 51
|
||||||
c = (v[1] + c) >> 51
|
c = (v.l1 + c) >> 51
|
||||||
c = (v[2] + c) >> 51
|
c = (v.l2 + c) >> 51
|
||||||
c = (v[3] + c) >> 51
|
c = (v.l3 + c) >> 51
|
||||||
c = (v[4] + c) >> 51
|
c = (v.l4 + c) >> 51
|
||||||
|
|
||||||
// If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's
|
// If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's
|
||||||
// effectively applying the reduction identity to the carry.
|
// effectively applying the reduction identity to the carry.
|
||||||
v[0] += 19 * c
|
v.l0 += 19 * c
|
||||||
|
|
||||||
v[1] += v[0] >> 51
|
v.l1 += v.l0 >> 51
|
||||||
v[0] = v[0] & maskLow51Bits
|
v.l0 = v.l0 & maskLow51Bits
|
||||||
v[2] += v[1] >> 51
|
v.l2 += v.l1 >> 51
|
||||||
v[1] = v[1] & maskLow51Bits
|
v.l1 = v.l1 & maskLow51Bits
|
||||||
v[3] += v[2] >> 51
|
v.l3 += v.l2 >> 51
|
||||||
v[2] = v[2] & maskLow51Bits
|
v.l2 = v.l2 & maskLow51Bits
|
||||||
v[4] += v[3] >> 51
|
v.l4 += v.l3 >> 51
|
||||||
v[3] = v[3] & maskLow51Bits
|
v.l3 = v.l3 & maskLow51Bits
|
||||||
// no additional carry
|
// no additional carry
|
||||||
v[4] = v[4] & maskLow51Bits
|
v.l4 = v.l4 & maskLow51Bits
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add sets v = a + b and returns v.
|
// Add sets v = a + b and returns v.
|
||||||
func (v *FieldElement) Add(a, b *FieldElement) *FieldElement {
|
func (v *FieldElement) Add(a, b *FieldElement) *FieldElement {
|
||||||
v[0] = a[0] + b[0]
|
v.l0 = a.l0 + b.l0
|
||||||
v[1] = a[1] + b[1]
|
v.l1 = a.l1 + b.l1
|
||||||
v[2] = a[2] + b[2]
|
v.l2 = a.l2 + b.l2
|
||||||
v[3] = a[3] + b[3]
|
v.l3 = a.l3 + b.l3
|
||||||
v[4] = a[4] + b[4]
|
v.l4 = a.l4 + b.l4
|
||||||
return v.carryPropagate1().carryPropagate2()
|
return v.carryPropagate1().carryPropagate2()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,11 +118,11 @@ func (v *FieldElement) Add(a, b *FieldElement) *FieldElement {
|
||||||
func (v *FieldElement) Sub(a, b *FieldElement) *FieldElement {
|
func (v *FieldElement) Sub(a, b *FieldElement) *FieldElement {
|
||||||
// We first add 2 * p, to guarantee the subtraction won't underflow, and
|
// We first add 2 * p, to guarantee the subtraction won't underflow, and
|
||||||
// then subtract b (which can be up to 2^255 + 2^13 * 19).
|
// then subtract b (which can be up to 2^255 + 2^13 * 19).
|
||||||
v[0] = (a[0] + 0xFFFFFFFFFFFDA) - b[0]
|
v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0
|
||||||
v[1] = (a[1] + 0xFFFFFFFFFFFFE) - b[1]
|
v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1
|
||||||
v[2] = (a[2] + 0xFFFFFFFFFFFFE) - b[2]
|
v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2
|
||||||
v[3] = (a[3] + 0xFFFFFFFFFFFFE) - b[3]
|
v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3
|
||||||
v[4] = (a[4] + 0xFFFFFFFFFFFFE) - b[4]
|
v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4
|
||||||
return v.carryPropagate1().carryPropagate2()
|
return v.carryPropagate1().carryPropagate2()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,17 +212,22 @@ func (v *FieldElement) FromBytes(x []byte) *FieldElement {
|
||||||
panic("ed25519: invalid field element input size")
|
panic("ed25519: invalid field element input size")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide headroom for the slight binary.LittleEndian.Uint64 overread. (We
|
// Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51).
|
||||||
// read 64 bits at an offset of 200, but then take only 4+51 into account.)
|
v.l0 = binary.LittleEndian.Uint64(x[0:8])
|
||||||
var buf [33]byte
|
v.l0 &= maskLow51Bits
|
||||||
copy(buf[:], x)
|
// Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51).
|
||||||
|
v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3
|
||||||
for i := range v {
|
v.l1 &= maskLow51Bits
|
||||||
bitsOffset := i * 51
|
// Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51).
|
||||||
v[i] = binary.LittleEndian.Uint64(buf[bitsOffset/8:])
|
v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6
|
||||||
v[i] >>= uint(bitsOffset % 8)
|
v.l2 &= maskLow51Bits
|
||||||
v[i] &= maskLow51Bits
|
// Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51).
|
||||||
}
|
v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1
|
||||||
|
v.l3 &= maskLow51Bits
|
||||||
|
// Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51).
|
||||||
|
// Note: not bytes 25:33, shift 4, to avoid overread.
|
||||||
|
v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12
|
||||||
|
v.l4 &= maskLow51Bits
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
@ -236,9 +243,9 @@ func (v *FieldElement) Bytes(b []byte) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
for i := range t {
|
for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} {
|
||||||
bitsOffset := i * 51
|
bitsOffset := i * 51
|
||||||
binary.LittleEndian.PutUint64(buf[:], t[i]<<uint(bitsOffset%8))
|
binary.LittleEndian.PutUint64(buf[:], l<<uint(bitsOffset%8))
|
||||||
for i, b := range buf {
|
for i, b := range buf {
|
||||||
off := bitsOffset/8 + i
|
off := bitsOffset/8 + i
|
||||||
if off >= len(out) {
|
if off >= len(out) {
|
||||||
|
@ -316,32 +323,32 @@ const mask64Bits uint64 = (1 << 64) - 1
|
||||||
// Select sets v to a if cond == 1, and to b if cond == 0.
|
// Select sets v to a if cond == 1, and to b if cond == 0.
|
||||||
func (v *FieldElement) Select(a, b *FieldElement, cond int) *FieldElement {
|
func (v *FieldElement) Select(a, b *FieldElement, cond int) *FieldElement {
|
||||||
m := uint64(cond) * mask64Bits
|
m := uint64(cond) * mask64Bits
|
||||||
v[0] = (m & a[0]) | (^m & b[0])
|
v.l0 = (m & a.l0) | (^m & b.l0)
|
||||||
v[1] = (m & a[1]) | (^m & b[1])
|
v.l1 = (m & a.l1) | (^m & b.l1)
|
||||||
v[2] = (m & a[2]) | (^m & b[2])
|
v.l2 = (m & a.l2) | (^m & b.l2)
|
||||||
v[3] = (m & a[3]) | (^m & b[3])
|
v.l3 = (m & a.l3) | (^m & b.l3)
|
||||||
v[4] = (m & a[4]) | (^m & b[4])
|
v.l4 = (m & a.l4) | (^m & b.l4)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// CondSwap swaps a and b if cond == 1 or leaves them unchanged if cond == 0.
|
// CondSwap swaps a and b if cond == 1 or leaves them unchanged if cond == 0.
|
||||||
func CondSwap(a, b *FieldElement, cond int) {
|
func CondSwap(a, b *FieldElement, cond int) {
|
||||||
m := uint64(cond) * mask64Bits
|
m := uint64(cond) * mask64Bits
|
||||||
t := m & (a[0] ^ b[0])
|
t := m & (a.l0 ^ b.l0)
|
||||||
a[0] ^= t
|
a.l0 ^= t
|
||||||
b[0] ^= t
|
b.l0 ^= t
|
||||||
t = m & (a[1] ^ b[1])
|
t = m & (a.l1 ^ b.l1)
|
||||||
a[1] ^= t
|
a.l1 ^= t
|
||||||
b[1] ^= t
|
b.l1 ^= t
|
||||||
t = m & (a[2] ^ b[2])
|
t = m & (a.l2 ^ b.l2)
|
||||||
a[2] ^= t
|
a.l2 ^= t
|
||||||
b[2] ^= t
|
b.l2 ^= t
|
||||||
t = m & (a[3] ^ b[3])
|
t = m & (a.l3 ^ b.l3)
|
||||||
a[3] ^= t
|
a.l3 ^= t
|
||||||
b[3] ^= t
|
b.l3 ^= t
|
||||||
t = m & (a[4] ^ b[4])
|
t = m & (a.l4 ^ b.l4)
|
||||||
a[4] ^= t
|
a.l4 ^= t
|
||||||
b[4] ^= t
|
b.l4 ^= t
|
||||||
}
|
}
|
||||||
|
|
||||||
// CondNeg sets v to -u if cond == 1, and to u if cond == 0.
|
// CondNeg sets v to -u if cond == 1, and to u if cond == 0.
|
||||||
|
@ -376,16 +383,16 @@ func (v *FieldElement) Square(x *FieldElement) *FieldElement {
|
||||||
|
|
||||||
// Mul32 sets v = x * y and returns v.
|
// Mul32 sets v = x * y and returns v.
|
||||||
func (v *FieldElement) Mul32(x *FieldElement, y uint32) *FieldElement {
|
func (v *FieldElement) Mul32(x *FieldElement, y uint32) *FieldElement {
|
||||||
x0lo, x0hi := mul51(x[0], y)
|
x0lo, x0hi := mul51(x.l0, y)
|
||||||
x1lo, x1hi := mul51(x[1], y)
|
x1lo, x1hi := mul51(x.l1, y)
|
||||||
x2lo, x2hi := mul51(x[2], y)
|
x2lo, x2hi := mul51(x.l2, y)
|
||||||
x3lo, x3hi := mul51(x[3], y)
|
x3lo, x3hi := mul51(x.l3, y)
|
||||||
x4lo, x4hi := mul51(x[4], y)
|
x4lo, x4hi := mul51(x.l4, y)
|
||||||
v[0] = x0lo + 19*x4hi // carried over per the reduction identity
|
v.l0 = x0lo + 19*x4hi // carried over per the reduction identity
|
||||||
v[1] = x1lo + x0hi
|
v.l1 = x1lo + x0hi
|
||||||
v[2] = x2lo + x1hi
|
v.l2 = x2lo + x1hi
|
||||||
v[3] = x3lo + x2hi
|
v.l3 = x3lo + x2hi
|
||||||
v[4] = x4lo + x3hi
|
v.l4 = x4lo + x3hi
|
||||||
// The hi portions are going to be only 32 bits, plus any previous excess,
|
// The hi portions are going to be only 32 bits, plus any previous excess,
|
||||||
// so we can skip the carry propagation.
|
// so we can skip the carry propagation.
|
||||||
return v
|
return v
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package base
|
package edwards25519
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -1,10 +1,10 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build amd64,!purego
|
// +build amd64,!purego
|
||||||
|
|
||||||
package base
|
package edwards25519
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func feMul(out, a, b *FieldElement)
|
func feMul(out, a, b *FieldElement)
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package base_test
|
package edwards25519_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"filippo.io/edwards25519/base"
|
"filippo.io/edwards25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkAdd(b *testing.B) {
|
func BenchmarkAdd(b *testing.B) {
|
||||||
var x, y base.FieldElement
|
var x, y edwards25519.FieldElement
|
||||||
x.One()
|
x.One()
|
||||||
y.Add(base.One, base.One)
|
y.Add(edwards25519.One, edwards25519.One)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
x.Add(&x, &y)
|
x.Add(&x, &y)
|
||||||
|
@ -21,9 +21,9 @@ func BenchmarkAdd(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMul(b *testing.B) {
|
func BenchmarkMul(b *testing.B) {
|
||||||
var x, y base.FieldElement
|
var x, y edwards25519.FieldElement
|
||||||
x.One()
|
x.One()
|
||||||
y.Add(base.One, base.One)
|
y.Add(edwards25519.One, edwards25519.One)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
x.Mul(&x, &y)
|
x.Mul(&x, &y)
|
||||||
|
@ -31,7 +31,7 @@ func BenchmarkMul(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMul32(b *testing.B) {
|
func BenchmarkMul32(b *testing.B) {
|
||||||
var x base.FieldElement
|
var x edwards25519.FieldElement
|
||||||
x.One()
|
x.One()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
|
@ -1,21 +1,21 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package base
|
package edwards25519
|
||||||
|
|
||||||
func feMulGeneric(v, x, y *FieldElement) {
|
func feMulGeneric(v, x, y *FieldElement) {
|
||||||
x0 := x[0]
|
x0 := x.l0
|
||||||
x1 := x[1]
|
x1 := x.l1
|
||||||
x2 := x[2]
|
x2 := x.l2
|
||||||
x3 := x[3]
|
x3 := x.l3
|
||||||
x4 := x[4]
|
x4 := x.l4
|
||||||
|
|
||||||
y0 := y[0]
|
y0 := y.l0
|
||||||
y1 := y[1]
|
y1 := y.l1
|
||||||
y2 := y[2]
|
y2 := y.l2
|
||||||
y3 := y[3]
|
y3 := y.l3
|
||||||
y4 := y[4]
|
y4 := y.l4
|
||||||
|
|
||||||
// Reduction can be carried out simultaneously to multiplication. For
|
// Reduction can be carried out simultaneously to multiplication. For
|
||||||
// example, we do not compute a coefficient r_5 . Whenever the result of a
|
// example, we do not compute a coefficient r_5 . Whenever the result of a
|
||||||
|
@ -109,11 +109,11 @@ func feSquareGeneric(v, x *FieldElement) {
|
||||||
// this is combined with multiplication by 19 where possible. The coefficient
|
// this is combined with multiplication by 19 where possible. The coefficient
|
||||||
// reduction after squaring is the same as for multiplication.
|
// reduction after squaring is the same as for multiplication.
|
||||||
|
|
||||||
x0 := x[0]
|
x0 := x.l0
|
||||||
x1 := x[1]
|
x1 := x.l1
|
||||||
x2 := x[2]
|
x2 := x.l2
|
||||||
x3 := x[3]
|
x3 := x.l3
|
||||||
x4 := x[4]
|
x4 := x.l4
|
||||||
|
|
||||||
x0_2 := x0 << 1
|
x0_2 := x0 << 1
|
||||||
x1_2 := x1 << 1
|
x1_2 := x1 << 1
|
|
@ -1,11 +1,10 @@
|
||||||
// Copyright (c) 2019 George Tankersley. All rights reserved.
|
|
||||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build go1.13
|
// +build go1.13
|
||||||
|
|
||||||
package base
|
package edwards25519
|
||||||
|
|
||||||
import "math/bits"
|
import "math/bits"
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !go1.13
|
// +build !go1.13
|
||||||
|
|
||||||
package base
|
package edwards25519
|
||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// +build !amd64 purego
|
// +build !amd64 purego
|
||||||
|
|
||||||
package base
|
package edwards25519
|
||||||
|
|
||||||
func feMul(v, x, y *FieldElement) { feMulGeneric(v, x, y) }
|
func feMul(v, x, y *FieldElement) { feMulGeneric(v, x, y) }
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package base
|
package edwards25519
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -17,9 +16,9 @@ import (
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
)
|
)
|
||||||
|
|
||||||
// quickCheckConfig will make each quickcheck test run (1024 * -quickchecks)
|
// quickCheckConfig10 will make each quickcheck test run (1024 * -quickchecks)
|
||||||
// times. The default value of -quickchecks is 100.
|
// times. The default value of -quickchecks is 100.
|
||||||
var quickCheckConfig = &quick.Config{MaxCountScale: 1 << 10}
|
var quickCheckConfig10 = &quick.Config{MaxCountScale: 1 << 10}
|
||||||
|
|
||||||
func generateFieldElement(rand *mathrand.Rand) FieldElement {
|
func generateFieldElement(rand *mathrand.Rand) FieldElement {
|
||||||
// Generation strategy: generate random limb values of [52, 51, 51, 51, 51]
|
// Generation strategy: generate random limb values of [52, 51, 51, 51, 51]
|
||||||
|
@ -78,7 +77,7 @@ func generateWeirdFieldElement(rand *mathrand.Rand) FieldElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x FieldElement) Generate(rand *mathrand.Rand, size int) reflect.Value {
|
func (v FieldElement) Generate(rand *mathrand.Rand, size int) reflect.Value {
|
||||||
if rand.Intn(2) == 0 {
|
if rand.Intn(2) == 0 {
|
||||||
return reflect.ValueOf(generateWeirdFieldElement(rand))
|
return reflect.ValueOf(generateWeirdFieldElement(rand))
|
||||||
}
|
}
|
||||||
|
@ -88,11 +87,11 @@ func (x FieldElement) Generate(rand *mathrand.Rand, size int) reflect.Value {
|
||||||
// isInBounds returns whether the element is within the expected bit size bounds
|
// isInBounds returns whether the element is within the expected bit size bounds
|
||||||
// after a light reduction.
|
// after a light reduction.
|
||||||
func isInBounds(x *FieldElement) bool {
|
func isInBounds(x *FieldElement) bool {
|
||||||
return bits.Len64(x[0]) <= 52 &&
|
return bits.Len64(x.l0) <= 52 &&
|
||||||
bits.Len64(x[1]) <= 51 &&
|
bits.Len64(x.l1) <= 51 &&
|
||||||
bits.Len64(x[2]) <= 51 &&
|
bits.Len64(x.l2) <= 51 &&
|
||||||
bits.Len64(x[3]) <= 51 &&
|
bits.Len64(x.l3) <= 51 &&
|
||||||
bits.Len64(x[4]) <= 51
|
bits.Len64(x.l4) <= 51
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMulDistributesOverAdd(t *testing.T) {
|
func TestMulDistributesOverAdd(t *testing.T) {
|
||||||
|
@ -112,7 +111,7 @@ func TestMulDistributesOverAdd(t *testing.T) {
|
||||||
return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
|
return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil {
|
if err := quick.Check(mulDistributesOverAdd, quickCheckConfig10); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,11 +197,11 @@ func TestFromBytesRoundTrip(t *testing.T) {
|
||||||
}
|
}
|
||||||
var tests = []feRTTest{
|
var tests = []feRTTest{
|
||||||
{
|
{
|
||||||
fe: FieldElement([5]uint64{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}),
|
fe: FieldElement{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676},
|
||||||
b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31},
|
b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fe: FieldElement([5]uint64{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}),
|
fe: FieldElement{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972},
|
||||||
b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122},
|
b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -256,7 +255,7 @@ func TestSanity(t *testing.T) {
|
||||||
var x2, x2sq FieldElement
|
var x2, x2sq FieldElement
|
||||||
// var x2Go, x2sqGo FieldElement
|
// var x2Go, x2sqGo FieldElement
|
||||||
|
|
||||||
x = [5]uint64{1, 1, 1, 1, 1}
|
x = FieldElement{1, 1, 1, 1, 1}
|
||||||
x2.Mul(&x, &x)
|
x2.Mul(&x, &x)
|
||||||
// FeMulGo(&x2Go, &x, &x)
|
// FeMulGo(&x2Go, &x, &x)
|
||||||
x2sq.Square(&x)
|
x2sq.Square(&x)
|
||||||
|
@ -293,8 +292,8 @@ func TestSanity(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEqual(t *testing.T) {
|
func TestEqual(t *testing.T) {
|
||||||
var x FieldElement = [5]uint64{1, 1, 1, 1, 1}
|
x := FieldElement{1, 1, 1, 1, 1}
|
||||||
var y FieldElement = [5]uint64{5, 4, 3, 2, 1}
|
y := FieldElement{5, 4, 3, 2, 1}
|
||||||
|
|
||||||
eq := x.Equal(&x)
|
eq := x.Equal(&x)
|
||||||
if eq != 1 {
|
if eq != 1 {
|
||||||
|
@ -308,8 +307,8 @@ func TestEqual(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvert(t *testing.T) {
|
func TestInvert(t *testing.T) {
|
||||||
var x FieldElement = [5]uint64{1, 1, 1, 1, 1}
|
x := FieldElement{1, 1, 1, 1, 1}
|
||||||
var one FieldElement = [5]uint64{1, 0, 0, 0, 0}
|
one := FieldElement{1, 0, 0, 0, 0}
|
||||||
var xinv, r FieldElement
|
var xinv, r FieldElement
|
||||||
|
|
||||||
xinv.Invert(&x)
|
xinv.Invert(&x)
|
||||||
|
@ -338,8 +337,8 @@ func TestInvert(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSelectSwap(t *testing.T) {
|
func TestSelectSwap(t *testing.T) {
|
||||||
a := FieldElement([5]uint64{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676})
|
a := FieldElement{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}
|
||||||
b := FieldElement([5]uint64{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972})
|
b := FieldElement{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}
|
||||||
|
|
||||||
var c, d FieldElement
|
var c, d FieldElement
|
||||||
|
|
||||||
|
@ -365,11 +364,11 @@ func TestSelectSwap(t *testing.T) {
|
||||||
|
|
||||||
func TestMul32(t *testing.T) {
|
func TestMul32(t *testing.T) {
|
||||||
isAlmostInBounds := func(x *FieldElement) bool {
|
isAlmostInBounds := func(x *FieldElement) bool {
|
||||||
return bits.Len64(x[0]) <= 52 &&
|
return bits.Len64(x.l0) <= 52 &&
|
||||||
bits.Len64(x[1]) <= 52 &&
|
bits.Len64(x.l1) <= 52 &&
|
||||||
bits.Len64(x[2]) <= 52 &&
|
bits.Len64(x.l2) <= 52 &&
|
||||||
bits.Len64(x[3]) <= 52 &&
|
bits.Len64(x.l3) <= 52 &&
|
||||||
bits.Len64(x[4]) <= 52
|
bits.Len64(x.l4) <= 52
|
||||||
}
|
}
|
||||||
|
|
||||||
mul32EquivalentToMul := func(x FieldElement, y uint32) bool {
|
mul32EquivalentToMul := func(x FieldElement, y uint32) bool {
|
||||||
|
@ -379,7 +378,7 @@ func TestMul32(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty := new(FieldElement)
|
ty := new(FieldElement)
|
||||||
ty[0] = uint64(y)
|
ty.l0 = uint64(y)
|
||||||
|
|
||||||
t2 := new(FieldElement)
|
t2 := new(FieldElement)
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
|
@ -389,7 +388,7 @@ func TestMul32(t *testing.T) {
|
||||||
return t1.Equal(t2) == 1 && isAlmostInBounds(t1) && isInBounds(t2)
|
return t1.Equal(t2) == 1 && isAlmostInBounds(t1) && isInBounds(t2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(mul32EquivalentToMul, quickCheckConfig); err != nil {
|
if err := quick.Check(mul32EquivalentToMul, quickCheckConfig10); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
// Copyright (c) 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
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package scalar implements the ristretto255 scalar group.
|
package edwards25519
|
||||||
package scalar
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
@ -13,8 +11,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Scalar is an integer modulo
|
// A Scalar is an integer modulo
|
||||||
// l = 2^252 + 27742317777372353535851937790883648493,
|
//
|
||||||
// here represented as an opaque little-endian byte string.
|
// l = 2^252 + 27742317777372353535851937790883648493
|
||||||
|
//
|
||||||
|
// represented as a little-endian byte string.
|
||||||
type Scalar [32]byte
|
type Scalar [32]byte
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -106,20 +106,6 @@ func (s *Scalar) Equal(t *Scalar) int {
|
||||||
return subtle.ConstantTimeCompare(ss[:], st[:])
|
return subtle.ConstantTimeCompare(ss[:], st[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// sliceForAppend extends the input slice by n bytes. head is the full extended
|
|
||||||
// slice, while tail is the appended part. If the original slice has sufficient
|
|
||||||
// capacity no allocation is performed.
|
|
||||||
func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
|
||||||
if total := len(in) + n; cap(in) >= total {
|
|
||||||
head = in[:total]
|
|
||||||
} else {
|
|
||||||
head = make([]byte, total)
|
|
||||||
copy(head, in)
|
|
||||||
}
|
|
||||||
tail = head[len(in):]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func load3(in []byte) int64 {
|
func load3(in []byte) int64 {
|
||||||
r := int64(in[0])
|
r := int64(in[0])
|
||||||
r |= int64(in[1]) << 8
|
r |= int64(in[1]) << 8
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright 2019 Henry de Valence. All rights reserved.
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package scalar
|
package edwards25519
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -11,11 +11,7 @@ import (
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
)
|
)
|
||||||
|
|
||||||
// quickCheckConfig will make each quickcheck test run (1024 * -quickchecks)
|
func TestScalarFromBytesRoundTrip(t *testing.T) {
|
||||||
// times. The default value of -quickchecks is 100.
|
|
||||||
var quickCheckConfig = &quick.Config{MaxCountScale: 1 << 10}
|
|
||||||
|
|
||||||
func TestFromBytesRoundTrip(t *testing.T) {
|
|
||||||
f1 := func(in, out [32]byte, sc Scalar) bool {
|
f1 := func(in, out [32]byte, sc Scalar) bool {
|
||||||
in[len(in)-1] &= (1 << 4) - 1 // Mask out top 4 bits for 252-bit numbers
|
in[len(in)-1] &= (1 << 4) - 1 // Mask out top 4 bits for 252-bit numbers
|
||||||
if err := sc.FromCanonicalBytes(in[:]); err != nil {
|
if err := sc.FromCanonicalBytes(in[:]); err != nil {
|
||||||
|
@ -43,7 +39,7 @@ func TestFromBytesRoundTrip(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromUniformBytes(t *testing.T) {
|
func TestScalarFromUniformBytes(t *testing.T) {
|
||||||
mod, _ := new(big.Int).SetString("27742317777372353535851937790883648493", 10)
|
mod, _ := new(big.Int).SetString("27742317777372353535851937790883648493", 10)
|
||||||
mod.Add(mod, new(big.Int).Lsh(big.NewInt(1), 252))
|
mod.Add(mod, new(big.Int).Lsh(big.NewInt(1), 252))
|
||||||
f := func(in [64]byte, sc Scalar) bool {
|
f := func(in [64]byte, sc Scalar) bool {
|
||||||
|
@ -69,7 +65,7 @@ func byteSwap(b []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMulDistributesOverAdd(t *testing.T) {
|
func TestScalarMulDistributesOverScalarAdd(t *testing.T) {
|
||||||
mulDistributesOverAdd := func(x, y, z Scalar) bool {
|
mulDistributesOverAdd := func(x, y, z Scalar) bool {
|
||||||
// Compute t1 = (x+y)*z
|
// Compute t1 = (x+y)*z
|
||||||
var t1 Scalar
|
var t1 Scalar
|
||||||
|
@ -86,12 +82,12 @@ func TestMulDistributesOverAdd(t *testing.T) {
|
||||||
return t1.Equal(&t2) == 1 && scMinimal(t1[:]) && scMinimal(t2[:])
|
return t1.Equal(&t2) == 1 && scMinimal(t1[:]) && scMinimal(t2[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil {
|
if err := quick.Check(mulDistributesOverAdd, quickCheckConfig10); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNonAdjacentForm(t *testing.T) {
|
func TestScalarNonAdjacentForm(t *testing.T) {
|
||||||
s := Scalar([32]byte{
|
s := Scalar([32]byte{
|
||||||
0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d,
|
0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d,
|
||||||
0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d,
|
0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d,
|
||||||
|
@ -118,7 +114,7 @@ func TestNonAdjacentForm(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvert(t *testing.T) {
|
func TestScalarInvert(t *testing.T) {
|
||||||
invertWorks := func(x Scalar) bool {
|
invertWorks := func(x Scalar) bool {
|
||||||
var xInv, check Scalar
|
var xInv, check Scalar
|
||||||
xInv.Inv(&x)
|
xInv.Inv(&x)
|
||||||
|
@ -127,7 +123,7 @@ func TestInvert(t *testing.T) {
|
||||||
return check.Equal(&scOne) == 1
|
return check.Equal(&scOne) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(invertWorks, quickCheckConfig); err != nil {
|
if err := quick.Check(invertWorks, quickCheckConfig10); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,13 @@
|
||||||
// Copyright (c) 2019 Henry de Valence.
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package edwards25519
|
package edwards25519
|
||||||
|
|
||||||
import "filippo.io/edwards25519/scalar"
|
|
||||||
|
|
||||||
// Set v to x*B, where B is the Ed25519 basepoint, and return v.
|
// Set v to x*B, where B is the Ed25519 basepoint, and return v.
|
||||||
//
|
//
|
||||||
// The scalar multiplication is done in constant time.
|
// The scalar multiplication is done in constant time.
|
||||||
func (v *ProjP3) BasepointMul(x *scalar.Scalar) *ProjP3 {
|
func (v *ProjP3) BasepointMul(x *Scalar) *ProjP3 {
|
||||||
// Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i )
|
// Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i )
|
||||||
// as described in the Ed25519 paper
|
// as described in the Ed25519 paper
|
||||||
//
|
//
|
||||||
|
@ -59,7 +57,7 @@ func (v *ProjP3) BasepointMul(x *scalar.Scalar) *ProjP3 {
|
||||||
// Set v to x*Q, and return v. v and q may alias.
|
// Set v to x*Q, and return v. v and q may alias.
|
||||||
//
|
//
|
||||||
// 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, 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.
|
||||||
|
@ -102,7 +100,7 @@ func (v *ProjP3) ScalarMul(x *scalar.Scalar, q *ProjP3) *ProjP3 {
|
||||||
// The multiscalar multiplication is sum(scalars[i]*points[i]).
|
// The multiscalar multiplication is sum(scalars[i]*points[i]).
|
||||||
//
|
//
|
||||||
// The multiscalar multiplication is performed in constant time.
|
// The multiscalar multiplication is performed in constant time.
|
||||||
func (v *ProjP3) MultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *ProjP3 {
|
func (v *ProjP3) MultiscalarMul(scalars []Scalar, points []*ProjP3) *ProjP3 {
|
||||||
if len(scalars) != len(points) {
|
if len(scalars) != len(points) {
|
||||||
panic("called MultiscalarMul with different size inputs")
|
panic("called MultiscalarMul with different size inputs")
|
||||||
}
|
}
|
||||||
|
@ -155,7 +153,7 @@ func (v *ProjP3) MultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *Proj
|
||||||
// Set v to a*A + b*B, where B is the Ed25519 basepoint, and 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.
|
// The scalar multiplication is done in variable time.
|
||||||
func (v *ProjP3) VartimeDoubleBaseMul(a *scalar.Scalar, A *ProjP3, b *scalar.Scalar) *ProjP3 {
|
func (v *ProjP3) VartimeDoubleBaseMul(a *Scalar, A *ProjP3, b *Scalar) *ProjP3 {
|
||||||
// Similarly to the single variable-base approach, we compute
|
// Similarly to the single variable-base approach, we compute
|
||||||
// digits and use them with a lookup table. However, because
|
// digits and use them with a lookup table. However, because
|
||||||
// we are allowed to do variable-time operations, we don't
|
// we are allowed to do variable-time operations, we don't
|
||||||
|
@ -231,7 +229,7 @@ func (v *ProjP3) VartimeDoubleBaseMul(a *scalar.Scalar, A *ProjP3, b *scalar.Sca
|
||||||
// The multiscalar multiplication is sum(scalars[i]*points[i]).
|
// The multiscalar multiplication is sum(scalars[i]*points[i]).
|
||||||
//
|
//
|
||||||
// The multiscalar multiplication is performed in variable time.
|
// The multiscalar multiplication is performed in variable time.
|
||||||
func (v *ProjP3) VartimeMultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *ProjP3 {
|
func (v *ProjP3) VartimeMultiscalarMul(scalars []Scalar, points []*ProjP3) *ProjP3 {
|
||||||
if len(scalars) != len(points) {
|
if len(scalars) != len(points) {
|
||||||
panic("called MultiscalarMul with different size inputs")
|
panic("called MultiscalarMul with different size inputs")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2019 Henry de Valence. All rights reserved.
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,29 +7,26 @@ package edwards25519
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
|
|
||||||
"filippo.io/edwards25519/base"
|
|
||||||
"filippo.io/edwards25519/scalar"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// quickCheckConfig will make each quickcheck test run (2^6 * -quickchecks)
|
|
||||||
// times. The default value of -quickchecks is 100.
|
|
||||||
var (
|
var (
|
||||||
quickCheckConfig = &quick.Config{MaxCountScale: 1 << 6}
|
// quickCheckConfig6 will make each quickcheck test run (2^6 * -quickchecks)
|
||||||
|
// times. The default value of -quickchecks is 100.
|
||||||
|
quickCheckConfig6 = &quick.Config{MaxCountScale: 1 << 6}
|
||||||
|
|
||||||
// a random scalar generated using dalek.
|
// a random scalar generated using dalek.
|
||||||
dalekScalar = 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})
|
dalekScalar = 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})
|
||||||
// the above, times the Ed25519 basepoint.
|
// the above, times the Ed25519 basepoint.
|
||||||
dalekScalarBasepoint = ProjP3{
|
dalekScalarBasepoint = ProjP3{
|
||||||
X: base.FieldElement([5]uint64{778774234987948, 1589187156384239, 1213330452914652, 186161118421127, 2186284806803213}),
|
X: FieldElement{778774234987948, 1589187156384239, 1213330452914652, 186161118421127, 2186284806803213},
|
||||||
Y: base.FieldElement([5]uint64{1241255309069369, 1115278942994853, 1016511918109334, 1303231926552315, 1801448517689873}),
|
Y: FieldElement{1241255309069369, 1115278942994853, 1016511918109334, 1303231926552315, 1801448517689873},
|
||||||
Z: base.FieldElement([5]uint64{353337085654440, 1327844406437681, 2207296012811921, 707394926933424, 917408459573183}),
|
Z: FieldElement{353337085654440, 1327844406437681, 2207296012811921, 707394926933424, 917408459573183},
|
||||||
T: base.FieldElement([5]uint64{585487439439725, 1792815221887900, 946062846079052, 1954901232609667, 1418300670001780}),
|
T: FieldElement{585487439439725, 1792815221887900, 946062846079052, 1954901232609667, 1418300670001780},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestScalarMulSmallScalars(t *testing.T) {
|
func TestScalarMulSmallScalars(t *testing.T) {
|
||||||
var z scalar.Scalar
|
var z Scalar
|
||||||
var p, check ProjP3
|
var p, check ProjP3
|
||||||
p.ScalarMul(&z, &B)
|
p.ScalarMul(&z, &B)
|
||||||
check.Zero()
|
check.Zero()
|
||||||
|
@ -37,7 +34,7 @@ func TestScalarMulSmallScalars(t *testing.T) {
|
||||||
t.Error("0*B != 0")
|
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})
|
z = 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)
|
p.ScalarMul(&z, &B)
|
||||||
check.Set(&B)
|
check.Set(&B)
|
||||||
if check.Equal(&p) != 1 {
|
if check.Equal(&p) != 1 {
|
||||||
|
@ -63,7 +60,7 @@ func TestBasepointMulVsDalek(t *testing.T) {
|
||||||
|
|
||||||
func TestVartimeDoubleBaseMulVsDalek(t *testing.T) {
|
func TestVartimeDoubleBaseMulVsDalek(t *testing.T) {
|
||||||
var p ProjP3
|
var p ProjP3
|
||||||
var z scalar.Scalar
|
var z Scalar
|
||||||
p.VartimeDoubleBaseMul(&dalekScalar, &B, &z)
|
p.VartimeDoubleBaseMul(&dalekScalar, &B, &z)
|
||||||
if dalekScalarBasepoint.Equal(&p) != 1 {
|
if dalekScalarBasepoint.Equal(&p) != 1 {
|
||||||
t.Error("VartimeDoubleBaseMul fails with b=0")
|
t.Error("VartimeDoubleBaseMul fails with b=0")
|
||||||
|
@ -75,14 +72,14 @@ func TestVartimeDoubleBaseMulVsDalek(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestScalarMulDistributesOverAdd(t *testing.T) {
|
func TestScalarMulDistributesOverAdd(t *testing.T) {
|
||||||
scalarMulDistributesOverAdd := func(x, y scalar.Scalar) bool {
|
scalarMulDistributesOverAdd := func(x, y Scalar) bool {
|
||||||
// The quickcheck generation strategy chooses a random
|
// The quickcheck generation strategy chooses a random
|
||||||
// 32-byte array, but we require that the high bit is
|
// 32-byte array, but we require that the high bit is
|
||||||
// unset. FIXME: make Scalar opaque. Until then,
|
// unset. FIXME: make Scalar opaque. Until then,
|
||||||
// mask the high bits:
|
// mask the high bits:
|
||||||
x[31] &= 127
|
x[31] &= 127
|
||||||
y[31] &= 127
|
y[31] &= 127
|
||||||
var z scalar.Scalar
|
var z Scalar
|
||||||
z.Add(&x, &y)
|
z.Add(&x, &y)
|
||||||
var p, q, r, check ProjP3
|
var p, q, r, check ProjP3
|
||||||
p.ScalarMul(&x, &B)
|
p.ScalarMul(&x, &B)
|
||||||
|
@ -92,7 +89,7 @@ func TestScalarMulDistributesOverAdd(t *testing.T) {
|
||||||
return check.Equal(&r) == 1
|
return check.Equal(&r) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(scalarMulDistributesOverAdd, quickCheckConfig); err != nil {
|
if err := quick.Check(scalarMulDistributesOverAdd, quickCheckConfig6); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +123,7 @@ func TestBasepointTableGeneration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestScalarMulMatchesBasepointMul(t *testing.T) {
|
func TestScalarMulMatchesBasepointMul(t *testing.T) {
|
||||||
scalarMulMatchesBasepointMul := func(x scalar.Scalar) bool {
|
scalarMulMatchesBasepointMul := func(x Scalar) bool {
|
||||||
// FIXME opaque scalars
|
// FIXME opaque scalars
|
||||||
x[31] &= 127
|
x[31] &= 127
|
||||||
var p, q ProjP3
|
var p, q ProjP3
|
||||||
|
@ -135,20 +132,20 @@ func TestScalarMulMatchesBasepointMul(t *testing.T) {
|
||||||
return p.Equal(&q) == 1
|
return p.Equal(&q) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(scalarMulMatchesBasepointMul, quickCheckConfig); err != nil {
|
if err := quick.Check(scalarMulMatchesBasepointMul, quickCheckConfig6); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiScalarMulMatchesBasepointMul(t *testing.T) {
|
func TestMultiScalarMulMatchesBasepointMul(t *testing.T) {
|
||||||
multiScalarMulMatchesBasepointMul := func(x, y, z scalar.Scalar) bool {
|
multiScalarMulMatchesBasepointMul := func(x, y, z Scalar) bool {
|
||||||
// FIXME opaque scalars
|
// FIXME opaque scalars
|
||||||
x[31] &= 127
|
x[31] &= 127
|
||||||
y[31] &= 127
|
y[31] &= 127
|
||||||
z[31] &= 127
|
z[31] &= 127
|
||||||
var p, q1, q2, q3, check ProjP3
|
var p, q1, q2, q3, check ProjP3
|
||||||
|
|
||||||
p.MultiscalarMul([]scalar.Scalar{x, y, z}, []*ProjP3{&B, &B, &B})
|
p.MultiscalarMul([]Scalar{x, y, z}, []*ProjP3{&B, &B, &B})
|
||||||
|
|
||||||
q1.BasepointMul(&x)
|
q1.BasepointMul(&x)
|
||||||
q2.BasepointMul(&y)
|
q2.BasepointMul(&y)
|
||||||
|
@ -159,7 +156,7 @@ func TestMultiScalarMulMatchesBasepointMul(t *testing.T) {
|
||||||
return p.Equal(&check) == 1
|
return p.Equal(&check) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(multiScalarMulMatchesBasepointMul, quickCheckConfig); err != nil {
|
if err := quick.Check(multiScalarMulMatchesBasepointMul, quickCheckConfig6); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,7 +171,7 @@ func TestBasepointNafTableGeneration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVartimeDoubleBaseMulMatchesBasepointMul(t *testing.T) {
|
func TestVartimeDoubleBaseMulMatchesBasepointMul(t *testing.T) {
|
||||||
vartimeDoubleBaseMulMatchesBasepointMul := func(x, y scalar.Scalar) bool {
|
vartimeDoubleBaseMulMatchesBasepointMul := func(x, y Scalar) bool {
|
||||||
// FIXME opaque scalars
|
// FIXME opaque scalars
|
||||||
x[31] &= 127
|
x[31] &= 127
|
||||||
y[31] &= 127
|
y[31] &= 127
|
||||||
|
@ -190,20 +187,20 @@ func TestVartimeDoubleBaseMulMatchesBasepointMul(t *testing.T) {
|
||||||
return p.Equal(&check) == 1
|
return p.Equal(&check) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(vartimeDoubleBaseMulMatchesBasepointMul, quickCheckConfig); err != nil {
|
if err := quick.Check(vartimeDoubleBaseMulMatchesBasepointMul, quickCheckConfig6); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVartimeMultiScalarMulMatchesBasepointMul(t *testing.T) {
|
func TestVartimeMultiScalarMulMatchesBasepointMul(t *testing.T) {
|
||||||
vartimeMultiScalarMulMatchesBasepointMul := func(x, y, z scalar.Scalar) bool {
|
vartimeMultiScalarMulMatchesBasepointMul := func(x, y, z Scalar) bool {
|
||||||
// FIXME opaque scalars
|
// FIXME opaque scalars
|
||||||
x[31] &= 127
|
x[31] &= 127
|
||||||
y[31] &= 127
|
y[31] &= 127
|
||||||
z[31] &= 127
|
z[31] &= 127
|
||||||
var p, q1, q2, q3, check ProjP3
|
var p, q1, q2, q3, check ProjP3
|
||||||
|
|
||||||
p.VartimeMultiscalarMul([]scalar.Scalar{x, y, z}, []*ProjP3{&B, &B, &B})
|
p.VartimeMultiscalarMul([]Scalar{x, y, z}, []*ProjP3{&B, &B, &B})
|
||||||
|
|
||||||
q1.BasepointMul(&x)
|
q1.BasepointMul(&x)
|
||||||
q2.BasepointMul(&y)
|
q2.BasepointMul(&y)
|
||||||
|
@ -214,7 +211,7 @@ func TestVartimeMultiScalarMulMatchesBasepointMul(t *testing.T) {
|
||||||
return p.Equal(&check) == 1
|
return p.Equal(&check) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := quick.Check(vartimeMultiScalarMulMatchesBasepointMul, quickCheckConfig); err != nil {
|
if err := quick.Check(vartimeMultiScalarMulMatchesBasepointMul, quickCheckConfig6); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +247,7 @@ func BenchmarkMultiscalarMulSize8(t *testing.B) {
|
||||||
x := dalekScalar
|
x := dalekScalar
|
||||||
|
|
||||||
for i := 0; i < t.N; i++ {
|
for i := 0; i < t.N; i++ {
|
||||||
p.MultiscalarMul([]scalar.Scalar{x, x, x, x, x, x, x, x}, []*ProjP3{&B, &B, &B, &B, &B, &B, &B, &B})
|
p.MultiscalarMul([]Scalar{x, x, x, x, x, x, x, x}, []*ProjP3{&B, &B, &B, &B, &B, &B, &B, &B})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019 Henry de Valence.
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2019 Henry de Valence. All rights reserved.
|
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue