arnaucube
arnaucube/cryptofunPublic Self-hosted repository
cryptofun/ecc/ecc.go
ecc/ecc.goRaw
  1package ecc
  2
  3import (
  4	"bytes"
  5	"errors"
  6	"math/big"
  7)
  8
  9type EC struct {
 10	A *big.Int
 11	B *big.Int
 12	Q *big.Int
 13}
 14
 15// NewEC (y^2 = x^3 + ax + b) mod q, where q is a prime number
 16func NewEC(a, b, q int) (ec EC) {
 17	ec.A = big.NewInt(int64(a))
 18	ec.B = big.NewInt(int64(b))
 19	ec.Q = big.NewInt(int64(q))
 20	return ec
 21}
 22
 23// At gets a point x in the curve
 24func (ec *EC) At(x *big.Int) (Point, Point, error) {
 25	if x.Cmp(ec.Q) > 0 {
 26		return Point{}, Point{}, errors.New("x<ec.Q")
 27	}
 28	// y^2 = (x^3 + ax + b) mod q
 29	// y = sqrt (x^3 + ax + b) mod q
 30	// x^3
 31	x3 := new(big.Int).Exp(x, big.NewInt(int64(3)), nil)
 32	// a^x
 33	aX := new(big.Int).Mul(ec.A, x)
 34	// x^3 + a^x
 35	x3aX := new(big.Int).Add(x3, aX)
 36	// x^3 + a^x + b
 37	x3aXb := new(big.Int).Add(x3aX, ec.B)
 38	// y = sqrt (x^3 + ax + b) mod q
 39	y := new(big.Int).ModSqrt(x3aXb, ec.Q)
 40	return Point{x, y}, Point{x, new(big.Int).Sub(ec.Q, y)}, nil
 41}
 42
 43// TODO add valid checker point function
 44
 45func (ec *EC) Neg(p Point) Point {
 46	// TODO get error when point not found on the ec
 47	return Point{p.X, new(big.Int).Sub(ec.Q, p.Y)}
 48}
 49
 50// Add adds two points p1 and p2 and gets q
 51func (ec *EC) Add(p1, p2 Point) (Point, error) {
 52	if p1.Equal(zeroPoint) {
 53		return p2, nil
 54	}
 55	if p2.Equal(zeroPoint) {
 56		return p1, nil
 57	}
 58
 59	var numerator, denominator, sRaw, s *big.Int
 60	if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) && (!bytes.Equal(p1.Y.Bytes(), p2.Y.Bytes()) || bytes.Equal(p1.Y.Bytes(), bigZero.Bytes())) {
 61		return zeroPoint, nil
 62	} else if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) {
 63		// use tangent as slope
 64		// x^2
 65		x2 := new(big.Int).Mul(p1.X, p1.X)
 66		// 3 * x^2
 67		x23 := new(big.Int).Mul(big.NewInt(int64(3)), x2)
 68		// 3 * x^2 + a
 69		numerator = new(big.Int).Add(x23, ec.A)
 70		// 2 * y
 71		denominator = new(big.Int).Mul(big.NewInt(int64(2)), p1.Y)
 72		// (3 * x^2 + a) / (2 * y) mod ec.Q
 73		denInv := new(big.Int).ModInverse(denominator, ec.Q)
 74		sRaw = new(big.Int).Mul(numerator, denInv)
 75		s = new(big.Int).Mod(sRaw, ec.Q)
 76	} else {
 77		// slope
 78		// y0-y1
 79		numerator = new(big.Int).Sub(p1.Y, p2.Y)
 80		// x0-x1
 81		denominator = new(big.Int).Sub(p1.X, p2.X)
 82		// (y0-y1) / (x0-x1) mod ec.Q
 83		denInv := new(big.Int).ModInverse(denominator, ec.Q)
 84		sRaw = new(big.Int).Mul(numerator, denInv)
 85		s = new(big.Int).Mod(sRaw, ec.Q)
 86	}
 87
 88	// q: new point
 89	var q Point
 90	// s^2
 91	s2 := new(big.Int).Exp(s, big.NewInt(int64(2)), nil)
 92	// s^2 - p1.X
 93	x2Xo := new(big.Int).Sub(s2, p1.X)
 94	// s^2 - p1.X - p2.X
 95	x2XoX2 := new(big.Int).Sub(x2Xo, p2.X)
 96	q.X = new(big.Int).Mod(x2XoX2, ec.Q)
 97
 98	// p1.X - q.X
 99	xoX2 := new(big.Int).Sub(p1.X, q.X)
100	// s(p1.X - q.X)
101	sXoX2 := new(big.Int).Mul(s, xoX2)
102	// s(p1.X - q.X) - p1.Y
103	sXoX2Y := new(big.Int).Sub(sXoX2, p1.Y)
104	// q.Y = (s(p1.X - q.X) - p1.Y) mod ec.Q
105	q.Y = new(big.Int).Mod(sXoX2Y, ec.Q)
106
107	return q, nil
108}
109
110// Mul multiplies a point n times on the elliptic curve
111func (ec *EC) Mul(p Point, n int) (Point, error) {
112	var err error
113	for i := 0; i < n; i++ {
114		p, err = ec.Add(p, p)
115		if err != nil {
116			return zeroPoint, err
117		}
118	}
119	return p, nil
120}