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