github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/google/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 bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"), 33 bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"), 34 } 35 36 // twistGen is the generator of group G₂. 37 var twistGen = &twistPoint{ 38 &gfP2{ 39 bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"), 40 bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"), 41 }, 42 &gfP2{ 43 bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"), 44 bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"), 45 }, 46 &gfP2{ 47 bigFromBase10("0"), 48 bigFromBase10("1"), 49 }, 50 &gfP2{ 51 bigFromBase10("0"), 52 bigFromBase10("1"), 53 }, 54 } 55 56 func newTwistPoint(pool *bnPool) *twistPoint { 57 return &twistPoint{ 58 newGFp2(pool), 59 newGFp2(pool), 60 newGFp2(pool), 61 newGFp2(pool), 62 } 63 } 64 65 func (c *twistPoint) String() string { 66 return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" 67 } 68 69 func (c *twistPoint) Put(pool *bnPool) { 70 c.x.Put(pool) 71 c.y.Put(pool) 72 c.z.Put(pool) 73 c.t.Put(pool) 74 } 75 76 func (c *twistPoint) Set(a *twistPoint) { 77 c.x.Set(a.x) 78 c.y.Set(a.y) 79 c.z.Set(a.z) 80 c.t.Set(a.t) 81 } 82 83 // IsOnCurve returns true iff c is on the curve where c must be in affine form. 84 func (c *twistPoint) IsOnCurve() bool { 85 pool := new(bnPool) 86 yy := newGFp2(pool).Square(c.y, pool) 87 xxx := newGFp2(pool).Square(c.x, pool) 88 xxx.Mul(xxx, c.x, pool) 89 yy.Sub(yy, xxx) 90 yy.Sub(yy, twistB) 91 yy.Minimal() 92 93 if yy.x.Sign() != 0 || yy.y.Sign() != 0 { 94 return false 95 } 96 cneg := newTwistPoint(pool) 97 cneg.Mul(c, Order, pool) 98 return cneg.z.IsZero() 99 } 100 101 func (c *twistPoint) SetInfinity() { 102 c.z.SetZero() 103 } 104 105 func (c *twistPoint) IsInfinity() bool { 106 return c.z.IsZero() 107 } 108 109 func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { 110 // For additional comments, see the same function in curve.go. 111 112 if a.IsInfinity() { 113 c.Set(b) 114 return 115 } 116 if b.IsInfinity() { 117 c.Set(a) 118 return 119 } 120 121 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 122 z1z1 := newGFp2(pool).Square(a.z, pool) 123 z2z2 := newGFp2(pool).Square(b.z, pool) 124 u1 := newGFp2(pool).Mul(a.x, z2z2, pool) 125 u2 := newGFp2(pool).Mul(b.x, z1z1, pool) 126 127 t := newGFp2(pool).Mul(b.z, z2z2, pool) 128 s1 := newGFp2(pool).Mul(a.y, t, pool) 129 130 t.Mul(a.z, z1z1, pool) 131 s2 := newGFp2(pool).Mul(b.y, t, pool) 132 133 h := newGFp2(pool).Sub(u2, u1) 134 xEqual := h.IsZero() 135 136 t.Add(h, h) 137 i := newGFp2(pool).Square(t, pool) 138 j := newGFp2(pool).Mul(h, i, pool) 139 140 t.Sub(s2, s1) 141 yEqual := t.IsZero() 142 if xEqual && yEqual { 143 c.Double(a, pool) 144 return 145 } 146 r := newGFp2(pool).Add(t, t) 147 148 v := newGFp2(pool).Mul(u1, i, pool) 149 150 t4 := newGFp2(pool).Square(r, pool) 151 t.Add(v, v) 152 t6 := newGFp2(pool).Sub(t4, j) 153 c.x.Sub(t6, t) 154 155 t.Sub(v, c.x) // t7 156 t4.Mul(s1, j, pool) // t8 157 t6.Add(t4, t4) // t9 158 t4.Mul(r, t, pool) // t10 159 c.y.Sub(t4, t6) 160 161 t.Add(a.z, b.z) // t11 162 t4.Square(t, pool) // t12 163 t.Sub(t4, z1z1) // t13 164 t4.Sub(t, z2z2) // t14 165 c.z.Mul(t4, h, pool) 166 167 z1z1.Put(pool) 168 z2z2.Put(pool) 169 u1.Put(pool) 170 u2.Put(pool) 171 t.Put(pool) 172 s1.Put(pool) 173 s2.Put(pool) 174 h.Put(pool) 175 i.Put(pool) 176 j.Put(pool) 177 r.Put(pool) 178 v.Put(pool) 179 t4.Put(pool) 180 t6.Put(pool) 181 } 182 183 func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { 184 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 185 A := newGFp2(pool).Square(a.x, pool) 186 B := newGFp2(pool).Square(a.y, pool) 187 C_ := newGFp2(pool).Square(B, pool) 188 189 t := newGFp2(pool).Add(a.x, B) 190 t2 := newGFp2(pool).Square(t, pool) 191 t.Sub(t2, A) 192 t2.Sub(t, C_) 193 d := newGFp2(pool).Add(t2, t2) 194 t.Add(A, A) 195 e := newGFp2(pool).Add(t, A) 196 f := newGFp2(pool).Square(e, pool) 197 198 t.Add(d, d) 199 c.x.Sub(f, t) 200 201 t.Add(C_, C_) 202 t2.Add(t, t) 203 t.Add(t2, t2) 204 c.y.Sub(d, c.x) 205 t2.Mul(e, c.y, pool) 206 c.y.Sub(t2, t) 207 208 t.Mul(a.y, a.z, pool) 209 c.z.Add(t, t) 210 211 A.Put(pool) 212 B.Put(pool) 213 C_.Put(pool) 214 t.Put(pool) 215 t2.Put(pool) 216 d.Put(pool) 217 e.Put(pool) 218 f.Put(pool) 219 } 220 221 func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { 222 sum := newTwistPoint(pool) 223 sum.SetInfinity() 224 t := newTwistPoint(pool) 225 226 for i := scalar.BitLen(); i >= 0; i-- { 227 t.Double(sum, pool) 228 if scalar.Bit(i) != 0 { 229 sum.Add(t, a, pool) 230 } else { 231 sum.Set(t) 232 } 233 } 234 235 c.Set(sum) 236 sum.Put(pool) 237 t.Put(pool) 238 return c 239 } 240 241 // MakeAffine converts c to affine form and returns c. If c is ∞, then it sets 242 // c to 0 : 1 : 0. 243 func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { 244 if c.z.IsOne() { 245 return c 246 } 247 if c.IsInfinity() { 248 c.x.SetZero() 249 c.y.SetOne() 250 c.z.SetZero() 251 c.t.SetZero() 252 return c 253 } 254 zInv := newGFp2(pool).Invert(c.z, pool) 255 t := newGFp2(pool).Mul(c.y, zInv, pool) 256 zInv2 := newGFp2(pool).Square(zInv, pool) 257 c.y.Mul(t, zInv2, pool) 258 t.Mul(c.x, zInv2, pool) 259 c.x.Set(t) 260 c.z.SetOne() 261 c.t.SetOne() 262 263 zInv.Put(pool) 264 t.Put(pool) 265 zInv2.Put(pool) 266 267 return c 268 } 269 270 func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { 271 c.x.Set(a.x) 272 c.y.SetZero() 273 c.y.Sub(c.y, a.y) 274 c.z.Set(a.z) 275 c.t.SetZero() 276 }