1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 // curvePoint implements the elliptic curve y²=x³+3. Points are kept in
12 // Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
14 type curvePoint struct {
18 var curveB = new(big.Int).SetInt64(3)
20 // curveGen is the generator of G₁.
21 var curveGen = &curvePoint{
22 new(big.Int).SetInt64(1),
23 new(big.Int).SetInt64(-2),
24 new(big.Int).SetInt64(1),
25 new(big.Int).SetInt64(1),
28 func newCurvePoint(pool *bnPool) *curvePoint {
37 func (c *curvePoint) String() string {
38 c.MakeAffine(new(bnPool))
39 return "(" + c.x.String() + ", " + c.y.String() + ")"
42 func (c *curvePoint) Put(pool *bnPool) {
49 func (c *curvePoint) Set(a *curvePoint) {
56 // IsOnCurve returns true iff c is on the curve where c must be in affine form.
57 func (c *curvePoint) IsOnCurve() bool {
58 yy := new(big.Int).Mul(c.y, c.y)
59 xxx := new(big.Int).Mul(c.x, c.x)
63 if yy.Sign() < 0 || yy.Cmp(p) >= 0 {
69 func (c *curvePoint) SetInfinity() {
73 func (c *curvePoint) IsInfinity() bool {
74 return c.z.Sign() == 0
77 func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
87 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
89 // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
90 // by [u1:s1:z1·z2] and [u2:s2:z1·z2]
91 // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
92 z1z1 := pool.Get().Mul(a.z, a.z)
94 z2z2 := pool.Get().Mul(b.z, b.z)
96 u1 := pool.Get().Mul(a.x, z2z2)
98 u2 := pool.Get().Mul(b.x, z1z1)
101 t := pool.Get().Mul(b.z, z2z2)
103 s1 := pool.Get().Mul(a.y, t)
108 s2 := pool.Get().Mul(b.y, t)
111 // Compute x = (2h)²(s²-u1-u2)
112 // where s = (s2-s1)/(u2-u1) is the slope of the line through
113 // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
115 // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
117 // with the notations below.
118 h := pool.Get().Sub(u2, u1)
119 xEqual := h.Sign() == 0
123 i := pool.Get().Mul(t, t)
126 j := pool.Get().Mul(h, i)
130 yEqual := t.Sign() == 0
131 if xEqual && yEqual {
135 r := pool.Get().Add(t, t)
137 v := pool.Get().Mul(u1, i)
141 t4 := pool.Get().Mul(r, r)
144 t6 := pool.Get().Sub(t4, j)
147 // Set y = -(2h)³(s1 + s*(x/4h²-u1))
149 // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
158 // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
159 t.Add(a.z, b.z) // t11
162 t.Sub(t4, z1z1) // t13
163 t4.Sub(t, z2z2) // t14
183 func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
184 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
185 A := pool.Get().Mul(a.x, a.x)
187 B := pool.Get().Mul(a.y, a.y)
189 C := pool.Get().Mul(B, B)
192 t := pool.Get().Add(a.x, B)
193 t2 := pool.Get().Mul(t, t)
197 d := pool.Get().Add(t2, t2)
199 e := pool.Get().Add(t, A)
200 f := pool.Get().Mul(e, e)
228 func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
229 sum := newCurvePoint(pool)
231 t := newCurvePoint(pool)
233 for i := scalar.BitLen(); i >= 0; i-- {
235 if scalar.Bit(i) != 0 {
248 func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
249 if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
253 zInv := pool.Get().ModInverse(c.z, p)
254 t := pool.Get().Mul(c.y, zInv)
256 zInv2 := pool.Get().Mul(zInv, zInv)
273 func (c *curvePoint) Negative(a *curvePoint) {