github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/cloudflare/twist.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package bn256 19 20 import ( 21 "math/big" 22 ) 23 24 // twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are 25 // kept in Jacobian form and t=z² when valid. The group G₂ is the set of 26 // n-torsion points of this curve over GF(p²) (where n = Order) 27 type twistPoint struct { 28 x, y, z, t gfP2 29 } 30 31 var twistB = &gfP2{ 32 gfP{0x38e7ecccd1dcff67, 0x65f0b37d93ce0d3e, 0xd749d0dd22ac00aa, 0x0141b9ce4a688d4d}, 33 gfP{0x3bf938e377b802a8, 0x020b1b273633535d, 0x26b7edf049755260, 0x2514c6324384a86d}, 34 } 35 36 // twistGen is the generator of group G₂. 37 var twistGen = &twistPoint{ 38 gfP2{ 39 gfP{0xafb4737da84c6140, 0x6043dd5a5802d8c4, 0x09e950fc52a02f86, 0x14fef0833aea7b6b}, 40 gfP{0x8e83b5d102bc2026, 0xdceb1935497b0172, 0xfbb8264797811adf, 0x19573841af96503b}, 41 }, 42 gfP2{ 43 gfP{0x64095b56c71856ee, 0xdc57f922327d3cbb, 0x55f935be33351076, 0x0da4a0e693fd6482}, 44 gfP{0x619dfa9d886be9f6, 0xfe7fd297f59e9b78, 0xff9e1a62231b7dfe, 0x28fd7eebae9e4206}, 45 }, 46 gfP2{*newGFp(0), *newGFp(1)}, 47 gfP2{*newGFp(0), *newGFp(1)}, 48 } 49 50 func (c *twistPoint) String() string { 51 c.MakeAffine() 52 x, y := gfP2Decode(&c.x), gfP2Decode(&c.y) 53 return "(" + x.String() + ", " + y.String() + ")" 54 } 55 56 func (c *twistPoint) Set(a *twistPoint) { 57 c.x.Set(&a.x) 58 c.y.Set(&a.y) 59 c.z.Set(&a.z) 60 c.t.Set(&a.t) 61 } 62 63 // IsOnCurve returns true iff c is on the curve. 64 func (c *twistPoint) IsOnCurve() bool { 65 c.MakeAffine() 66 if c.IsInfinity() { 67 return true 68 } 69 70 y2, x3 := &gfP2{}, &gfP2{} 71 y2.Square(&c.y) 72 x3.Square(&c.x).Mul(x3, &c.x).Add(x3, twistB) 73 74 if *y2 != *x3 { 75 return false 76 } 77 cneg := &twistPoint{} 78 cneg.Mul(c, Order) 79 return cneg.z.IsZero() 80 } 81 82 func (c *twistPoint) SetInfinity() { 83 c.x.SetZero() 84 c.y.SetOne() 85 c.z.SetZero() 86 c.t.SetZero() 87 } 88 89 func (c *twistPoint) IsInfinity() bool { 90 return c.z.IsZero() 91 } 92 93 func (c *twistPoint) Add(a, b *twistPoint) { 94 // For additional comments, see the same function in curve.go. 95 96 if a.IsInfinity() { 97 c.Set(b) 98 return 99 } 100 if b.IsInfinity() { 101 c.Set(a) 102 return 103 } 104 105 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 106 z12 := (&gfP2{}).Square(&a.z) 107 z22 := (&gfP2{}).Square(&b.z) 108 u1 := (&gfP2{}).Mul(&a.x, z22) 109 u2 := (&gfP2{}).Mul(&b.x, z12) 110 111 t := (&gfP2{}).Mul(&b.z, z22) 112 s1 := (&gfP2{}).Mul(&a.y, t) 113 114 t.Mul(&a.z, z12) 115 s2 := (&gfP2{}).Mul(&b.y, t) 116 117 h := (&gfP2{}).Sub(u2, u1) 118 xEqual := h.IsZero() 119 120 t.Add(h, h) 121 i := (&gfP2{}).Square(t) 122 j := (&gfP2{}).Mul(h, i) 123 124 t.Sub(s2, s1) 125 yEqual := t.IsZero() 126 if xEqual && yEqual { 127 c.Double(a) 128 return 129 } 130 r := (&gfP2{}).Add(t, t) 131 132 v := (&gfP2{}).Mul(u1, i) 133 134 t4 := (&gfP2{}).Square(r) 135 t.Add(v, v) 136 t6 := (&gfP2{}).Sub(t4, j) 137 c.x.Sub(t6, t) 138 139 t.Sub(v, &c.x) // t7 140 t4.Mul(s1, j) // t8 141 t6.Add(t4, t4) // t9 142 t4.Mul(r, t) // t10 143 c.y.Sub(t4, t6) 144 145 t.Add(&a.z, &b.z) // t11 146 t4.Square(t) // t12 147 t.Sub(t4, z12) // t13 148 t4.Sub(t, z22) // t14 149 c.z.Mul(t4, h) 150 } 151 152 func (c *twistPoint) Double(a *twistPoint) { 153 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 154 A := (&gfP2{}).Square(&a.x) 155 B := (&gfP2{}).Square(&a.y) 156 C := (&gfP2{}).Square(B) 157 158 t := (&gfP2{}).Add(&a.x, B) 159 t2 := (&gfP2{}).Square(t) 160 t.Sub(t2, A) 161 t2.Sub(t, C) 162 d := (&gfP2{}).Add(t2, t2) 163 t.Add(A, A) 164 e := (&gfP2{}).Add(t, A) 165 f := (&gfP2{}).Square(e) 166 167 t.Add(d, d) 168 c.x.Sub(f, t) 169 170 t.Add(C, C) 171 t2.Add(t, t) 172 t.Add(t2, t2) 173 c.y.Sub(d, &c.x) 174 t2.Mul(e, &c.y) 175 c.y.Sub(t2, t) 176 177 t.Mul(&a.y, &a.z) 178 c.z.Add(t, t) 179 } 180 181 func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int) { 182 sum, t := &twistPoint{}, &twistPoint{} 183 184 for i := scalar.BitLen(); i >= 0; i-- { 185 t.Double(sum) 186 if scalar.Bit(i) != 0 { 187 sum.Add(t, a) 188 } else { 189 sum.Set(t) 190 } 191 } 192 193 c.Set(sum) 194 } 195 196 func (c *twistPoint) MakeAffine() { 197 if c.z.IsOne() { 198 return 199 } else if c.z.IsZero() { 200 c.x.SetZero() 201 c.y.SetOne() 202 c.t.SetZero() 203 return 204 } 205 206 zInv := (&gfP2{}).Invert(&c.z) 207 t := (&gfP2{}).Mul(&c.y, zInv) 208 zInv2 := (&gfP2{}).Square(zInv) 209 c.y.Mul(t, zInv2) 210 t.Mul(&c.x, zInv2) 211 c.x.Set(t) 212 c.z.SetOne() 213 c.t.SetOne() 214 } 215 216 func (c *twistPoint) Neg(a *twistPoint) { 217 c.x.Set(&a.x) 218 c.y.Neg(&a.y) 219 c.z.Set(&a.z) 220 c.t.SetZero() 221 }