Implement an elliptic.Curve for ed25519

This commit is contained in:
George Tankersley 2017-05-22 00:00:00 +00:00
commit 19d7f4d83d
6 changed files with 3903 additions and 0 deletions

22
const.go Normal file
View File

@ -0,0 +1,22 @@
package ed25519
import (
"math/big"
"github.com/gtank/ed25519/internal/edwards25519"
)
var (
// d2 is 2*d, a curve-specific constant used in our addition formula.
d2 = edwards25519.FieldElement{
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199,
}
// the number 2 as a field element
feTwo = edwards25519.FieldElement{
2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
bigZero = big.NewInt(0)
bigOne = big.NewInt(1)
)

242
ed25519.go Normal file
View File

@ -0,0 +1,242 @@
// Implements an elliptic.Curve interface over the ed25519 curve.
package ed25519
import (
"crypto/elliptic"
"math/big"
"sync"
"github.com/gtank/ed25519/internal/edwards25519"
)
type ed25519Curve struct {
*elliptic.CurveParams
}
var once sync.Once
var ed25519Params = &elliptic.CurveParams{Name: "ed25519"}
var ed25519 = ed25519Curve{ed25519Params}
// Ed25519 uses a twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2 with the following params:
// The field prime is 2^255 - 19.
// The order of the base point is 2^252 + 27742317777372353535851937790883648493.
// And since B is irrelevant here, we're going to pretend that B is d = -(121665/121666).
func initEd25519Params() {
ed25519Params.P, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
ed25519Params.N, _ = new(big.Int).SetString("7237005577332262213973186563042994240857116359379907606001950938285454250989", 10)
ed25519Params.B, _ = new(big.Int).SetString("37095705934669439343138083508754565189542113879843219016388785533085940283555", 10)
ed25519Params.Gx, _ = new(big.Int).SetString("15112221349535400772501151409588531511454012693041857206046113283949847762202", 10)
ed25519Params.Gy, _ = new(big.Int).SetString("46316835694926478169428394003475163141307993866256225615783033603165251855960", 10)
ed25519Params.BitSize = 256
}
func Ed25519() elliptic.Curve {
once.Do(initEd25519Params)
return ed25519
}
// Params returns the parameters for the curve.
func (curve ed25519Curve) Params() *elliptic.CurveParams {
return curve.CurveParams
}
// IsOnCurve reports whether the given (x,y) lies on the curve by checking that
// -x^2 + y^2 - 1 - dx^2y^2 = 0.
func (curve ed25519Curve) IsOnCurve(x, y *big.Int) bool {
lh := new(big.Int).Mul(x, x) // x^2
y2 := new(big.Int).Mul(y, y) // y^2
rh := new(big.Int).Mul(lh, y2) // x^2y^2
rh.Mul(rh, curve.B) // dx^2y^2 with B repurposed as d
rh.Add(rh, bigOne) // 1 + dx^2y^2
lh.Neg(lh) // -x^2
lh.Add(lh, y2) // -x^2 + y^2
lh.Sub(lh, rh) // -x^2 + y^2 - 1 - dx^2y^2
lh.Mod(lh, curve.P) // -x^2 + y^2 - 1 - dx^2y^2 mod p
return lh.Cmp(bigZero) == 0
}
// Add returns the sum of (x1, y1) and (x2, y2).
func (curve ed25519Curve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) {
var p1, p2, p3 edwards25519.ExtendedGroupElement
affineToExtended(&p1, x1, y1)
affineToExtended(&p2, x2, y2)
extendedAdd(&p3, &p1, &p2)
return extendedToAffine(&p3) // 1I + 2M
}
// The internal edwards25519 package optimizes for a particular sequence of
// operations, so we reimplement addition (add-2008-hwcd-3) here to avoid the
// cost of converting between intermediate representations.
// TODO We know Z1=1 and Z2=1 here, so mmadd-2008-hwcd-3 (6M + 1S + 1*k + 9add) could apply
func extendedAdd(out, p1, p2 *edwards25519.ExtendedGroupElement) {
var tmp1, tmp2, A, B, C, D, E, F, G, H edwards25519.FieldElement
edwards25519.FeSub(&tmp1, &p1.Y, &p1.X) // tmp1 <-- Y1-X1
edwards25519.FeSub(&tmp2, &p2.Y, &p2.X) // tmp2 <-- Y2-X2
edwards25519.FeMul(&A, &tmp1, &tmp2) // A <-- tmp1*tmp2 = (Y1-X1)*(Y2-X2)
edwards25519.FeAdd(&tmp1, &p1.Y, &p1.X) // tmp1 <-- Y1+X1
edwards25519.FeAdd(&tmp2, &p2.Y, &p2.X) // tmp2 <-- Y2+X2
edwards25519.FeMul(&B, &tmp1, &tmp2) // B <-- tmp1*tmp2 = (Y1+X1)*(Y2+X2)
edwards25519.FeMul(&tmp1, &p1.T, &p2.T) // tmp1 <-- T1*T2
edwards25519.FeMul(&C, &tmp1, &d2) // C <-- tmp1*2d = T1*2d*T2
edwards25519.FeMul(&tmp1, &p1.Z, &p2.Z) // tmp1 <-- Z1*Z2
edwards25519.FeAdd(&D, &tmp1, &tmp1) // D <-- tmp1 + tmp1 = 2*Z1*Z2
edwards25519.FeSub(&E, &B, &A) // E <-- B-A
edwards25519.FeSub(&F, &D, &C) // F <-- D-C
edwards25519.FeAdd(&G, &D, &C) // G <-- D+C
edwards25519.FeAdd(&H, &B, &A) // H <-- B+A
edwards25519.FeMul(&out.X, &E, &F) // X3 <-- E*F
edwards25519.FeMul(&out.Y, &G, &H) // Y3 <-- G*H
edwards25519.FeMul(&out.T, &E, &H) // T3 <-- E*H
edwards25519.FeMul(&out.Z, &F, &G) // Z3 <-- F*G
}
// Double returns 2*(x,y).
// TODO: cheaper to reimplement? the typed path is aff->proj->completed->proj->aff
func (curve ed25519Curve) Double(x1, y1 *big.Int) (x, y *big.Int) {
var p edwards25519.ProjectiveGroupElement
var r edwards25519.CompletedGroupElement
affineToProjective(&p, x1, y1)
p.Double(&r)
r.ToProjective(&p) // 3M
return projectiveToAffine(&p) // 1I + 2M
}
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
func (curve ed25519Curve) ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int) {
// if either coordinate is nil, return the point at infinity
if x1 == nil || y1 == nil {
x = new(big.Int).Set(bigZero)
y = new(big.Int).Set(bigOne)
return
}
var r0, r1 edwards25519.ExtendedGroupElement
var h edwards25519.CompletedGroupElement
var s [32]byte
curve.scalarFromBytes(&s, k)
// Montgomery ladder init:
// R_0 = O, R_1 = P
r0.Zero()
affineToExtended(&r1, x1, y1)
// Montgomery ladder step:
// R_{1-b} = R_{1-b} + R_{b}
// R_{b} = 2*R_{b}
for i := 255; i >= 0; i-- {
var b = int32((s[i/8] >> uint(i&7)) & 1)
if b == 0 {
extendedAdd(&r1, &r0, &r1)
r0.Double(&h)
h.ToExtended(&r0)
} else {
extendedAdd(&r0, &r0, &r1)
r1.Double(&h)
h.ToExtended(&r1)
}
}
return extendedToAffine(&r0)
}
// scalarFromBytes converts a big-endian value to a fixed-size little-endian
// representation. If the value is larger than the scalar group order, we
// reduce it before returning.
func (curve ed25519Curve) scalarFromBytes(out *[32]byte, in []byte) {
scalar := new(big.Int).SetBytes(in)
if scalar.Cmp(curve.N) >= 0 {
scalar.Mod(scalar, curve.N)
}
buf := make([]byte, 32)
scBytes := scalar.Bytes()
copy(buf[32-len(scBytes):], scBytes)
for i := 0; i < 32; i++ {
out[i] = buf[31-i]
}
}
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
// an integer in big-endian form.
func (curve ed25519Curve) ScalarBaseMult(k []byte) (x, y *big.Int) {
var p edwards25519.ExtendedGroupElement
var scBytes [32]byte
curve.scalarFromBytes(&scBytes, k)
edwards25519.GeScalarMultBase(&p, &scBytes)
return extendedToAffine(&p)
}
// Converts (x,y) to (X:Y:T:Z) extended coordinates, or "P3" in ref10. As
// described in "Twisted Edwards Curves Revisited", Hisil-Wong-Carter-Dawson
// 2008, Section 3.1 (https://eprint.iacr.org/2008/522.pdf)
// See also https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3
func affineToExtended(out *edwards25519.ExtendedGroupElement, x, y *big.Int) {
feFromBig(&out.X, x)
feFromBig(&out.Y, y)
edwards25519.FeMul(&out.T, &out.X, &out.Y)
edwards25519.FeOne(&out.Z)
}
// Extended coordinates are XYZT with x = X/Z, y = Y/Z, or the "P3"
// representation in ref10. Extended->affine is the same operation as moving
// from projective to affine. Per HWCD, it is safe to move from extended to
// projective by simply ignoring T.
func extendedToAffine(in *edwards25519.ExtendedGroupElement) (*big.Int, *big.Int) {
var x, y, zinv edwards25519.FieldElement
var bigX, bigY = new(big.Int), new(big.Int)
edwards25519.FeInvert(&zinv, &in.Z)
edwards25519.FeMul(&x, &in.X, &zinv)
edwards25519.FeMul(&y, &in.Y, &zinv)
feToBig(bigX, &x)
feToBig(bigY, &y)
return bigX, bigY
}
// Projective coordinates are XYZ with x = X/Z, y = Y/Z, or the "P2" representation in ref10.
func affineToProjective(out *edwards25519.ProjectiveGroupElement, x, y *big.Int) {
feFromBig(&out.X, x)
feFromBig(&out.Y, y)
edwards25519.FeOne(&out.Z)
}
func projectiveToAffine(in *edwards25519.ProjectiveGroupElement) (*big.Int, *big.Int) {
var x, y, zinv edwards25519.FieldElement
var bigX, bigY = new(big.Int), new(big.Int)
edwards25519.FeInvert(&zinv, &in.Z)
edwards25519.FeMul(&x, &in.X, &zinv)
edwards25519.FeMul(&y, &in.Y, &zinv)
feToBig(bigX, &x)
feToBig(bigY, &y)
return bigX, bigY
}
func feFromBig(h *edwards25519.FieldElement, in *big.Int) {
tmp := new(big.Int).Mod(in, ed25519.P)
tmpBytes := tmp.Bytes()
var buf, reverse [32]byte
copy(buf[32-len(tmpBytes):], tmpBytes)
for i := 0; i < 32; i++ {
reverse[i] = buf[31-i]
}
edwards25519.FeFromBytes(h, &reverse)
}
func feToBig(out *big.Int, h *edwards25519.FieldElement) {
var buf, reverse [32]byte
edwards25519.FeToBytes(&buf, h)
for i := 0; i < 32; i++ {
reverse[i] = buf[31-i]
}
out.SetBytes(reverse[:])
out.Mod(out, ed25519.P)
}

419
ed25519_test.go Normal file
View File

@ -0,0 +1,419 @@
package ed25519
import (
"bytes"
"crypto/elliptic"
"crypto/rand"
"crypto/sha512"
"encoding/hex"
"io"
"math/big"
"testing"
"github.com/gtank/ed25519/internal/edwards25519"
)
// TEST MATH
// d is a constant from the curve equation. it's easy to find the value in multiple formats.
var d_fe = edwards25519.FieldElement{
-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116,
}
var d_bn, _ = new(big.Int).SetString("37095705934669439343138083508754565189542113879843219016388785533085940283555", 10)
// 2*d
var d2_fe = edwards25519.FieldElement{
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199,
}
var d2_bn = new(big.Int).Mul(big.NewInt(2), d_bn)
// A is a constant from the Montgomery form of curve25519.
var A_fe = edwards25519.FieldElement{
486662, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
var A_bn, _ = new(big.Int).SetString("486662", 10)
var feConvTable = []struct {
name string
fe edwards25519.FieldElement
bn *big.Int
}{
{
name: "d",
fe: d_fe,
bn: d_bn,
},
{
name: "d2",
fe: d2_fe,
bn: d2_bn,
},
{
name: "A",
fe: A_fe,
bn: A_bn,
},
}
func TestFeFromBig(t *testing.T) {
var _ = Ed25519().(ed25519Curve)
var fe edwards25519.FieldElement
for _, c := range feConvTable {
feFromBig(&fe, c.bn)
for i := 0; i < len(fe); i++ {
if fe[i] != c.fe[i] {
t.Error("bn->fe radix conversion failed")
}
}
}
}
func TestFeToBig(t *testing.T) {
var curve = Ed25519().(ed25519Curve)
var bn, expectedBN = new(big.Int), new(big.Int)
for _, c := range feConvTable {
expectedBN.Mod(c.bn, curve.P)
feToBig(bn, &c.fe)
if bn.Cmp(expectedBN) != 0 {
t.Errorf("fe->bn radix conversion failed: %s", c.name)
}
}
}
func TestRadixRoundTrip(t *testing.T) {
if testing.Short() {
t.Skip()
}
var curve = Ed25519().(ed25519Curve)
var fe edwards25519.FieldElement
var out = new(big.Int)
for i := 0; i < 1000; i++ {
n, err := rand.Int(rand.Reader, curve.P)
if err != nil {
t.Fatal(err)
}
feFromBig(&fe, n)
feToBig(out, &fe)
if n.Cmp(out) != 0 {
t.Errorf("fe<>bn failed for %x", n.Bytes())
}
}
}
func TestIsOnCurve(t *testing.T) {
ed := Ed25519()
if !ed.IsOnCurve(ed.Params().Gx, ed.Params().Gy) {
t.Error("ed25519 base point not on curve")
}
x, y := new(big.Int), new(big.Int)
if ed.IsOnCurve(x, y) {
t.Error("(0,0) is not on the curve")
}
}
func TestAdd(t *testing.T) {
c := Ed25519().(ed25519Curve)
Bx, By := c.Params().Gx, c.Params().Gy
B2x, B2y := c.Add(Bx, By, Bx, By)
if !c.IsOnCurve(B2x, B2y) {
t.Error("B+B is not on the curve")
}
}
func TestDouble(t *testing.T) {
c := Ed25519().(ed25519Curve)
Gx, Gy := c.Params().Gx, c.Params().Gy
G2x, G2y := c.Double(Gx, Gy)
Ax, Ay := c.Add(Gx, Gy, Gx, Gy)
if Ax.Cmp(G2x) != 0 || Ay.Cmp(G2y) != 0 {
t.Errorf("double(B) != B+B")
}
}
// Test vector generated by instrumenting x/crypto/ed25519 GenerateKey
// seed: c240344fcc6615dda52da98149377ad2b13fdba2bc39a50ba9f3afb2cbd4abaa
// expanded: f04154b9d80963bb4c76214ece8a1049bdd16fbfc5003aff9835a59643ace276
// public: 65a8343a83ec15e55050f12fc22f2c81a4fe7327c8da1524441f9ce5e5bc27dd
func TestScalarMultBase(t *testing.T) {
c := Ed25519()
// endian-swapped because x/crypto assumes this is always little endian from raw bytes
// and scalarFromBytes assumes it's coming from big.Int Bytes()
a, _ := hex.DecodeString("76e2ac4396a53598ff3a00c5bf6fd1bd49108ace4e21764cbb6309d8b95441f0")
if len(a) != 32 {
t.Errorf("failed decoding")
}
Ax, Ay := c.ScalarBaseMult(a)
if !c.IsOnCurve(Ax, Ay) {
t.Error("scalarmultbase result was off-curve")
}
var A edwards25519.ExtendedGroupElement
pub, _ := hex.DecodeString("65a8343a83ec15e55050f12fc22f2c81a4fe7327c8da1524441f9ce5e5bc27dd")
var pubBytes [32]byte
copy(pubBytes[:], pub)
A.FromBytes(&pubBytes)
Bx, By := extendedToAffine(&A)
if Ax.Cmp(Bx) != 0 || Ay.Cmp(By) != 0 {
t.Error("scalarmultbase disagrees with x/crypto/ed25519")
}
}
func TestScalarMultBaseIdentity(t *testing.T) {
var c = Ed25519()
var one = new(big.Int).Set(bigOne)
Ax, Ay := c.ScalarBaseMult(one.Bytes())
if Ax.Cmp(c.Params().Gx) != 0 || Ay.Cmp(c.Params().Gy) != 0 {
t.Errorf("precomputed 1*B != B")
}
Ax, Ay = c.ScalarMult(Ax, Ay, one.Bytes())
if Ax.Cmp(c.Params().Gx) != 0 || Ay.Cmp(c.Params().Gy) != 0 {
t.Errorf("arbitrary 1*B != B")
}
}
func TestScalarMultBaseInfinity(t *testing.T) {
c := Ed25519()
a, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000")
if len(a) != 32 {
t.Errorf("failed decoding")
}
Ax, Ay := c.ScalarBaseMult(a)
if !c.IsOnCurve(Ax, Ay) {
t.Error("scalarmultbase result was off-curve")
}
if Ax.Cmp(bigZero) != 0 || Ay.Cmp(bigOne) != 0 {
t.Error("scalarmultbase by 0 was not point at infinity")
}
}
func TestScalarMultsAgreeAtInfinity(t *testing.T) {
c := Ed25519()
a, _ := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000")
if len(a) != 32 {
t.Errorf("failed decoding")
}
Ax, Ay := c.ScalarBaseMult(a)
Bx, By := c.ScalarMult(c.Params().Gx, c.Params().Gy, a)
if Ax.Cmp(Bx) != 0 || Ay.Cmp(By) != 0 {
t.Error("scalarmultbase disagrees with scalarmult")
}
}
func TestScalarMultsAgreeElsewhere(t *testing.T) {
c := Ed25519()
// head -c 32 /dev/urandom | sha256sum
a, _ := hex.DecodeString("c07eea55b3322f15099b6cf4d2b7e99d3d0fa6807f6fc7a46b5f7cb78daad4e0")
Ax, Ay := c.ScalarBaseMult(a)
Bx, By := c.ScalarMult(c.Params().Gx, c.Params().Gy, a)
if Ax.Cmp(Bx) != 0 || Ay.Cmp(By) != 0 {
t.Error("scalarmultbase disagrees with scalarmult")
}
if !c.IsOnCurve(Bx, By) {
t.Error("scalarmult is returning off-curve points")
}
}
// TEST INTERFACE
func TestMarshalingRoundTrip(t *testing.T) {
ed := Ed25519()
a, _ := hex.DecodeString("c07eea55b3322f15099b6cf4d2b7e99d3d0fa6807f6fc7a46b5f7cb78daad4e0")
Ax, Ay := ed.ScalarBaseMult(a)
if !ed.IsOnCurve(Ax, Ay) {
t.Error("scalarBaseMult is returning off-curve points")
}
sec1A := elliptic.Marshal(ed, Ax, Ay)
Bx, By := elliptic.Unmarshal(ed, sec1A)
if Ax.Cmp(Bx) != 0 || Ay.Cmp(By) != 0 {
t.Error("point did not survive elliptic.Marshal roundtrip")
}
if !testing.Short() {
for i := 0; i < 100; i++ {
_, err := io.ReadFull(rand.Reader, a)
if err != nil {
t.Fatal(err)
}
Ax, Ay := ed.ScalarBaseMult(a)
if !ed.IsOnCurve(Ax, Ay) {
t.Error("scalarBaseMult is returning off-curve points")
}
sec1A := elliptic.Marshal(ed, Ax, Ay)
Bx, By := elliptic.Unmarshal(ed, sec1A)
if Ax.Cmp(Bx) != 0 || Ay.Cmp(By) != 0 {
t.Error("point did not survive elliptic.Marshal roundtrip")
}
}
}
}
// TEST APPLICATION
func generateKey(r io.Reader) (sk *[32]byte, pk []byte, err error) {
if r == nil {
r = rand.Reader
}
ed := Ed25519()
sk = new([32]byte)
_, err = io.ReadFull(r, sk[:])
if err != nil {
return nil, nil, err
}
digest := sha512.Sum512(sk[:])
digest[0] &= 248
digest[31] &= 127
digest[31] |= 64
// take the first half of expanded bytes & reverse; big.Int expects big-endian
reverseDigest := reverse32(digest[:32])
scalar := new(big.Int).SetBytes(reverseDigest)
// A = a*B
Ax, Ay := ed.ScalarBaseMult(scalar.Bytes())
// This works with the standard elliptic package marshaling
publicKey := elliptic.Marshal(ed, Ax, Ay)
// but we can also render the compressed Edwards format
compressedEdwardsY := make([]byte, 32)
// x, y here will be big-endian byte strings
x, y := publicKey[1:33], publicKey[33:]
// RFC 8032: To form the encoding of the point, copy the least significant
// bit of the x-coordinate to the most significant bit of the final octet.
copy(compressedEdwardsY[:], y)
compressedEdwardsY[0] |= x[31] << 7
compressedEdwardsY = reverse32(compressedEdwardsY)
return sk, compressedEdwardsY, err
}
func reverse32(b []byte) []byte {
var tmp = make([]byte, 32)
for i := 0; i <= 31; i++ {
tmp[i] = b[31-i]
}
return tmp
}
// Test vector generated by instrumenting x/crypto/ed25519 GenerateKey(). These
// are raw values. The edwards code interprets them as little-endian, so they
// need to be reversed before use with big.Int.
var genKeyTest = struct {
seed, expanded, public string
}{
seed: "c240344fcc6615dda52da98149377ad2b13fdba2bc39a50ba9f3afb2cbd4abaa",
expanded: "f04154b9d80963bb4c76214ece8a1049bdd16fbfc5003aff9835a59643ace276",
public: "65a8343a83ec15e55050f12fc22f2c81a4fe7327c8da1524441f9ce5e5bc27dd",
}
func TestEdDSAGenerateKey(t *testing.T) {
fakeRandom, _ := hex.DecodeString(genKeyTest.seed)
fakeReader := bytes.NewBuffer(fakeRandom)
sk, pk, err := generateKey(fakeReader)
if err != nil {
t.Fatal(err)
}
expectedPK, _ := hex.DecodeString(genKeyTest.public)
if !bytes.Equal(sk[:], fakeRandom) || !bytes.Equal(pk, expectedPK) {
t.Error("generateKey output did not match test vector")
}
}
// BENCHMARKS
func BenchmarkIsOnCurve(b *testing.B) {
ed := Ed25519()
Gx, Gy := ed.Params().Gx, ed.Params().Gy
for i := 0; i < b.N; i++ {
if !ed.IsOnCurve(Gx, Gy) {
b.Error("ed25519 base point not on curve")
}
}
}
func BenchmarkAdd(b *testing.B) {
ed := Ed25519()
Gx, Gy := ed.Params().Gx, ed.Params().Gy
for i := 0; i < b.N; i++ {
Gx, Gy = ed.Add(Gx, Gy, Gx, Gy)
}
}
func BenchmarkDouble(b *testing.B) {
ed := Ed25519()
Gx, Gy := ed.Params().Gx, ed.Params().Gy
for i := 0; i < b.N; i++ {
Gx, Gy = ed.Double(Gx, Gy)
}
}
func BenchmarkScalarBaseMult(b *testing.B) {
ed := Ed25519()
var k [32]byte
_, err := io.ReadFull(rand.Reader, k[:])
if err != nil {
b.Fatal(err)
}
k[0] &= 248
k[31] &= 127
k[31] |= 64
for i := 0; i < b.N; i++ {
_, _ = ed.ScalarBaseMult(k[:])
}
}
func BenchmarkScalarMult(b *testing.B) {
ed := Ed25519()
Bx, By := ed.Params().Gx, ed.Params().Gy
var k [32]byte
_, err := io.ReadFull(rand.Reader, k[:])
if err != nil {
b.Fatal(err)
}
k[0] &= 248
k[31] &= 127
k[31] |= 64
for i := 0; i < b.N; i++ {
_, _ = ed.ScalarMult(Bx, By, k[:])
}
}

27
internal/LICENSE Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff