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