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