arnaucube
arnaucube/cryptofunPublic Self-hosted repository
cryptofun/ecc/ecc.go
ecc/ecc.goRaw
 1package ecc
 2
 3import (
 4	"errors"
 5	"math/big"
 6)
 7
 8type EC struct {
 9	A *big.Int
10	B *big.Int
11	Q *big.Int
12}
13
14/*
15	(y^2 = x^3 + Ax + B ) mod Q
16	Q: prime number
17*/
18func NewEC(a, b, q int) (ec EC) {
19	ec.A = big.NewInt(int64(a))
20	ec.B = big.NewInt(int64(b))
21	ec.Q = big.NewInt(int64(q))
22	return ec
23}
24
25// At gets a point x in the curve
26func (ec *EC) At(x *big.Int) (Point, Point, error) {
27	if x.Cmp(ec.Q) > 0 {
28		return Point{}, Point{}, errors.New("x<ec.Q")
29	}
30	// y^2 = (x^3 + ax + b) mod q
31	// y = sqrt (x^3 + ax + b) mod q
32	// x^3
33	x3 := new(big.Int).Exp(x, big.NewInt(int64(3)), nil)
34	// a^x
35	aX := new(big.Int).Mul(ec.A, x)
36	// x^3 + a^x
37	x3aX := new(big.Int).Add(x3, aX)
38	// x^3 + a^x + b
39	x3aXb := new(big.Int).Add(x3aX, ec.B)
40	// y = sqrt (x^3 + ax + b) mod q
41	y := new(big.Int).ModSqrt(x3aXb, ec.Q)
42	return Point{x, y}, Point{x, new(big.Int).Sub(ec.Q, y)}, nil
43}
44
45// TODO add valid checker point function
46
47func (ec *EC) Neg(p Point) Point {
48	// TODO get error when point not found on the ec
49	return Point{p.X, new(big.Int).Sub(ec.Q, p.Y)}
50}
51
52// Add adds two points p1 and p2 and gets q
53func (ec *EC) Add(p1, p2 Point) (Point, error) {
54	if p1.Equal(zeroPoint) {
55		return p2, errors.New("p1==(0, 0)")
56	}
57	if p2.Equal(zeroPoint) {
58		return p1, errors.New("p1==(0, 0)")
59	}
60	// slope
61	numerator := new(big.Int).Sub(p1.Y, p2.Y)
62	denominator := new(big.Int).Sub(p1.X, p2.X)
63	s := new(big.Int).Div(numerator, denominator)
64	// q: new point
65	var q Point
66	// s^2
67	s2 := new(big.Int).Exp(s, big.NewInt(int64(2)), nil)
68	// s^2 - p1.X
69	x2Xo := new(big.Int).Sub(s2, p1.X)
70	// s^2 - p1.X - p2.X
71	x2XoX2 := new(big.Int).Sub(x2Xo, p2.X)
72	q.X = new(big.Int).Mod(x2XoX2, ec.Q)
73
74	// p1.X - q.X
75	xoX2 := new(big.Int).Sub(p1.X, q.X)
76	// s(p1.X - q.X)
77	sXoX2 := new(big.Int).Mul(s, xoX2)
78	// s(p1.X - q.X) - p1.Y
79	sXoX2Y := new(big.Int).Sub(sXoX2, p1.Y)
80	q.Y = new(big.Int).Mod(sXoX2Y, ec.Q)
81
82	return q, nil
83}