cryptofun/ecc/ecc.go
ecc/ecc.goRaw
1package ecc
2
3import (
4 "bytes"
5 "errors"
6 "math/big"
7)
8
9// EC is the data structure for the elliptic curve parameters
10type EC struct {
11 A *big.Int
12 B *big.Int
13 Q *big.Int
14}
15
16// NewEC (y^2 = x^3 + ax + b) mod q, where q is a prime number
17func NewEC(a, b, q int) (ec EC) {
18 ec.A = big.NewInt(int64(a))
19 ec.B = big.NewInt(int64(b))
20 ec.Q = big.NewInt(int64(q))
21 return ec
22}
23
24// At gets a point x in the curve
25func (ec *EC) At(x *big.Int) (Point, Point, error) {
26 if x.Cmp(ec.Q) > 0 {
27 return Point{}, Point{}, errors.New("x<ec.Q")
28 }
29 // y^2 = (x^3 + ax + b) mod q
30 // y = sqrt (x^3 + ax + b) mod q
31 // x^3
32 x3 := new(big.Int).Exp(x, big.NewInt(int64(3)), nil)
33 // a^x
34 aX := new(big.Int).Mul(ec.A, x)
35 // x^3 + a^x
36 x3aX := new(big.Int).Add(x3, aX)
37 // x^3 + a^x + b
38 x3aXb := new(big.Int).Add(x3aX, ec.B)
39 // y = sqrt (x^3 + ax + b) mod q
40 y := new(big.Int).ModSqrt(x3aXb, ec.Q)
41 return Point{x, y}, Point{x, new(big.Int).Sub(ec.Q, y)}, nil
42}
43
44// TODO add valid checker point function Valid()
45
46// Neg returns the inverse of the P point on the elliptic curve
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// Order returns smallest n where nG = O (point at zero)
53func (ec *EC) Order(g Point) (int, error) {
54 for i := 1; i < int(ec.Q.Int64())+1; i++ {
55 mPoint, err := ec.Mul(g, i)
56 if err != nil {
57 return i, err
58 }
59 if mPoint.Equal(zeroPoint) {
60 return i, nil
61 }
62 }
63 return -1, errors.New("invalid order")
64}
65
66// Add adds two points p1 and p2 and gets q, returns the negate of q
67func (ec *EC) Add(p1, p2 Point) (Point, error) {
68 if p1.Equal(zeroPoint) {
69 return p2, nil
70 }
71 if p2.Equal(zeroPoint) {
72 return p1, nil
73 }
74
75 var numerator, denominator, sRaw, s *big.Int
76 if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) && (!bytes.Equal(p1.Y.Bytes(), p2.Y.Bytes()) || bytes.Equal(p1.Y.Bytes(), bigZero.Bytes())) {
77 return zeroPoint, nil
78 } else if bytes.Equal(p1.X.Bytes(), p2.X.Bytes()) {
79 // use tangent as slope
80 // x^2
81 x2 := new(big.Int).Mul(p1.X, p1.X)
82 // 3 * x^2
83 x23 := new(big.Int).Mul(big.NewInt(int64(3)), x2)
84 // 3 * x^2 + a
85 numerator = new(big.Int).Add(x23, ec.A)
86 // 2 * y
87 denominator = new(big.Int).Mul(big.NewInt(int64(2)), p1.Y)
88 // s = (3 * x^2 + a) / (2 * y) mod ec.Q
89 denInv := new(big.Int).ModInverse(denominator, ec.Q)
90 sRaw = new(big.Int).Mul(numerator, denInv)
91 s = new(big.Int).Mod(sRaw, ec.Q)
92 } else {
93 // slope
94 // y0-y1
95 numerator = new(big.Int).Sub(p1.Y, p2.Y)
96 // x0-x1
97 denominator = new(big.Int).Sub(p1.X, p2.X)
98 // s = (y0-y1) / (x0-x1) mod ec.Q
99 denInv := new(big.Int).ModInverse(denominator, ec.Q)
100 sRaw = new(big.Int).Mul(numerator, denInv)
101 s = new(big.Int).Mod(sRaw, ec.Q)
102 }
103
104 // q: new point
105 var q Point
106 // s^2
107 s2 := new(big.Int).Exp(s, big.NewInt(int64(2)), nil)
108 // s^2 - p1.X
109 x2Xo := new(big.Int).Sub(s2, p1.X)
110 // s^2 - p1.X - p2.X
111 x2XoX2 := new(big.Int).Sub(x2Xo, p2.X)
112 q.X = new(big.Int).Mod(x2XoX2, ec.Q)
113
114 // p1.X - q.X
115 xoX2 := new(big.Int).Sub(p1.X, q.X)
116 // s(p1.X - q.X)
117 sXoX2 := new(big.Int).Mul(s, xoX2)
118 // s(p1.X - q.X) - p1.Y
119 sXoX2Y := new(big.Int).Sub(sXoX2, p1.Y)
120 // q.Y = (s(p1.X - q.X) - p1.Y) mod ec.Q
121 q.Y = new(big.Int).Mod(sXoX2Y, ec.Q)
122
123 // negate q
124 // q = ec.Neg(q)
125 return q, nil
126}
127
128// Mul multiplies a point n times on the elliptic curve
129func (ec *EC) Mul(p Point, n int) (Point, error) {
130 var err error
131 p2 := p
132 r := zeroPoint
133 for 0 < n {
134 if n&1 == 1 {
135 r, err = ec.Add(r, p2)
136 if err != nil {
137 return p, err
138 }
139 }
140 n = n >> 1
141 p2, err = ec.Add(p2, p2)
142 if err != nil {
143 return p, err
144 }
145
146 }
147 return r, nil
148}