mirror of https://github.com/gtank/ristretto255
154 lines
4.7 KiB
Go
154 lines
4.7 KiB
Go
// Copyright (c) 2017 George Tankersley. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package ed25519
|
|
|
|
import (
|
|
"crypto/elliptic"
|
|
"math/big"
|
|
"sync"
|
|
|
|
"github.com/gtank/ed25519/internal/group"
|
|
field "github.com/gtank/ed25519/internal/radix51"
|
|
)
|
|
|
|
var bigZero *big.Int
|
|
var bigOne *big.Int
|
|
|
|
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
|
|
bigZero = big.NewInt(0)
|
|
bigOne = big.NewInt(1)
|
|
}
|
|
|
|
// Ed25519 returns a Curve that implements Ed25519.
|
|
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 (mod p). This function uses a hardcoded value
|
|
// of d.
|
|
func (curve ed25519Curve) IsOnCurve(x, y *big.Int) bool {
|
|
var feX, feY field.FieldElement
|
|
field.FeFromBig(&feX, x)
|
|
field.FeFromBig(&feY, y)
|
|
|
|
var lh, y2, rh field.FieldElement
|
|
field.FeSquare(&lh, &feX) // x^2
|
|
field.FeSquare(&y2, &feY) // y^2
|
|
field.FeMul(&rh, &lh, &y2) // x^2*y^2
|
|
field.FeMul(&rh, &rh, &group.D) // d*x^2*y^2
|
|
field.FeAdd(&rh, &rh, &field.FieldOne) // 1 + d*x^2*y^2
|
|
field.FeNeg(&lh, &lh) // -x^2
|
|
field.FeAdd(&lh, &lh, &y2) // -x^2 + y^2
|
|
field.FeSub(&lh, &lh, &rh) // -x^2 + y^2 - 1 - dx^2y^2
|
|
field.FeReduce(&lh, &lh) // mod p
|
|
|
|
return field.FeEqual(&lh, &field.FieldZero)
|
|
}
|
|
|
|
// 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 group.ExtendedGroupElement
|
|
|
|
p1.FromAffine(x1, y1)
|
|
p2.FromAffine(x2, y2)
|
|
|
|
return p2.Add(&p1, &p2).ToAffine()
|
|
}
|
|
|
|
// Double returns 2*(x,y).
|
|
func (curve ed25519Curve) Double(x1, y1 *big.Int) (x, y *big.Int) {
|
|
var p group.ProjectiveGroupElement
|
|
|
|
p.FromAffine(x1, y1)
|
|
|
|
// Use the special-case DoubleZ1 here because we know Z will be 1.
|
|
return p.DoubleZ1().ToAffine()
|
|
}
|
|
|
|
// 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 identity point
|
|
if x1 == nil || y1 == nil {
|
|
x = new(big.Int).Set(bigZero)
|
|
y = new(big.Int).Set(bigOne)
|
|
return
|
|
}
|
|
|
|
var r0, r1 group.ExtendedGroupElement
|
|
var s [32]byte
|
|
|
|
curve.scalarFromBytes(&s, k)
|
|
|
|
// Montgomery ladder init:
|
|
// R_0 = O, R_1 = P
|
|
r0.Zero()
|
|
r1.FromAffine(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 {
|
|
r1.Add(&r0, &r1)
|
|
r0.Double()
|
|
} else {
|
|
r0.Add(&r0, &r1)
|
|
r1.Double()
|
|
}
|
|
}
|
|
|
|
return r0.ToAffine()
|
|
}
|
|
|
|
// 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 curve and k is
|
|
// an integer in big-endian form. The difference between this and
|
|
// arbitrary-point ScalarMult is the availability of precomputed multiples of
|
|
// the base point.
|
|
func (curve ed25519Curve) ScalarBaseMult(k []byte) (x, y *big.Int) {
|
|
panic("not yet implemented")
|
|
}
|