github.com/c2s/go-ethereum@v1.9.7/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 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 cneg := newTwistPoint(pool) 84 cneg.Mul(c, Order, pool) 85 return cneg.z.IsZero() 86 } 87 88 func (c *twistPoint) SetInfinity() { 89 c.z.SetZero() 90 } 91 92 func (c *twistPoint) IsInfinity() bool { 93 return c.z.IsZero() 94 } 95 96 func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { 97 // For additional comments, see the same function in curve.go. 98 99 if a.IsInfinity() { 100 c.Set(b) 101 return 102 } 103 if b.IsInfinity() { 104 c.Set(a) 105 return 106 } 107 108 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 109 z1z1 := newGFp2(pool).Square(a.z, pool) 110 z2z2 := newGFp2(pool).Square(b.z, pool) 111 u1 := newGFp2(pool).Mul(a.x, z2z2, pool) 112 u2 := newGFp2(pool).Mul(b.x, z1z1, pool) 113 114 t := newGFp2(pool).Mul(b.z, z2z2, pool) 115 s1 := newGFp2(pool).Mul(a.y, t, pool) 116 117 t.Mul(a.z, z1z1, pool) 118 s2 := newGFp2(pool).Mul(b.y, t, pool) 119 120 h := newGFp2(pool).Sub(u2, u1) 121 xEqual := h.IsZero() 122 123 t.Add(h, h) 124 i := newGFp2(pool).Square(t, pool) 125 j := newGFp2(pool).Mul(h, i, pool) 126 127 t.Sub(s2, s1) 128 yEqual := t.IsZero() 129 if xEqual && yEqual { 130 c.Double(a, pool) 131 return 132 } 133 r := newGFp2(pool).Add(t, t) 134 135 v := newGFp2(pool).Mul(u1, i, pool) 136 137 t4 := newGFp2(pool).Square(r, pool) 138 t.Add(v, v) 139 t6 := newGFp2(pool).Sub(t4, j) 140 c.x.Sub(t6, t) 141 142 t.Sub(v, c.x) // t7 143 t4.Mul(s1, j, pool) // t8 144 t6.Add(t4, t4) // t9 145 t4.Mul(r, t, pool) // t10 146 c.y.Sub(t4, t6) 147 148 t.Add(a.z, b.z) // t11 149 t4.Square(t, pool) // t12 150 t.Sub(t4, z1z1) // t13 151 t4.Sub(t, z2z2) // t14 152 c.z.Mul(t4, h, pool) 153 154 z1z1.Put(pool) 155 z2z2.Put(pool) 156 u1.Put(pool) 157 u2.Put(pool) 158 t.Put(pool) 159 s1.Put(pool) 160 s2.Put(pool) 161 h.Put(pool) 162 i.Put(pool) 163 j.Put(pool) 164 r.Put(pool) 165 v.Put(pool) 166 t4.Put(pool) 167 t6.Put(pool) 168 } 169 170 func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { 171 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 172 A := newGFp2(pool).Square(a.x, pool) 173 B := newGFp2(pool).Square(a.y, pool) 174 C_ := newGFp2(pool).Square(B, pool) 175 176 t := newGFp2(pool).Add(a.x, B) 177 t2 := newGFp2(pool).Square(t, pool) 178 t.Sub(t2, A) 179 t2.Sub(t, C_) 180 d := newGFp2(pool).Add(t2, t2) 181 t.Add(A, A) 182 e := newGFp2(pool).Add(t, A) 183 f := newGFp2(pool).Square(e, pool) 184 185 t.Add(d, d) 186 c.x.Sub(f, t) 187 188 t.Add(C_, C_) 189 t2.Add(t, t) 190 t.Add(t2, t2) 191 c.y.Sub(d, c.x) 192 t2.Mul(e, c.y, pool) 193 c.y.Sub(t2, t) 194 195 t.Mul(a.y, a.z, pool) 196 c.z.Add(t, t) 197 198 A.Put(pool) 199 B.Put(pool) 200 C_.Put(pool) 201 t.Put(pool) 202 t2.Put(pool) 203 d.Put(pool) 204 e.Put(pool) 205 f.Put(pool) 206 } 207 208 func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { 209 sum := newTwistPoint(pool) 210 sum.SetInfinity() 211 t := newTwistPoint(pool) 212 213 for i := scalar.BitLen(); i >= 0; i-- { 214 t.Double(sum, pool) 215 if scalar.Bit(i) != 0 { 216 sum.Add(t, a, pool) 217 } else { 218 sum.Set(t) 219 } 220 } 221 222 c.Set(sum) 223 sum.Put(pool) 224 t.Put(pool) 225 return c 226 } 227 228 // MakeAffine converts c to affine form and returns c. If c is ∞, then it sets 229 // c to 0 : 1 : 0. 230 func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { 231 if c.z.IsOne() { 232 return c 233 } 234 if c.IsInfinity() { 235 c.x.SetZero() 236 c.y.SetOne() 237 c.z.SetZero() 238 c.t.SetZero() 239 return c 240 } 241 zInv := newGFp2(pool).Invert(c.z, pool) 242 t := newGFp2(pool).Mul(c.y, zInv, pool) 243 zInv2 := newGFp2(pool).Square(zInv, pool) 244 c.y.Mul(t, zInv2, pool) 245 t.Mul(c.x, zInv2, pool) 246 c.x.Set(t) 247 c.z.SetOne() 248 c.t.SetOne() 249 250 zInv.Put(pool) 251 t.Put(pool) 252 zInv2.Put(pool) 253 254 return c 255 } 256 257 func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { 258 c.x.Set(a.x) 259 c.y.SetZero() 260 c.y.Sub(c.y, a.y) 261 c.z.Set(a.z) 262 c.t.SetZero() 263 }