github.com/emmansun/gmsm@v0.29.1/sm9/bn256/twist.go (about) 1 package bn256 2 3 import ( 4 "crypto/subtle" 5 "math/big" 6 ) 7 8 // twistPoint implements the elliptic curve y²=x³+5/ξ (y²=x³+5i) over GF(p²). Points are 9 // kept in Jacobian form and t=z² when valid. The group G₂ is the set of 10 // n-torsion points of this curve over GF(p²) (where n = Order) 11 type twistPoint struct { 12 x, y, z, t gfP2 13 } 14 15 var twistB = &gfP2{ 16 *newGFp(5), 17 *zero, 18 } 19 20 var threeTwistB = &gfP2{ 21 *newGFp(3 * 5), 22 *zero, 23 } 24 25 // twistGen is the generator of group G₂. 26 var twistGen = &twistPoint{ 27 gfP2{ 28 *fromBigInt(bigFromHex("85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141")), 29 *fromBigInt(bigFromHex("3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B")), 30 }, 31 gfP2{ 32 *fromBigInt(bigFromHex("17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96")), 33 *fromBigInt(bigFromHex("A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7")), 34 }, 35 gfP2{*newGFp(0), *newGFp(1)}, 36 gfP2{*newGFp(0), *newGFp(1)}, 37 } 38 39 func (c *twistPoint) String() string { 40 c.MakeAffine() 41 x, y := gfP2Decode(&c.x), gfP2Decode(&c.y) 42 return "(" + x.String() + ", " + y.String() + ")" 43 } 44 45 func (c *twistPoint) Set(a *twistPoint) { 46 c.x.Set(&a.x) 47 c.y.Set(&a.y) 48 c.z.Set(&a.z) 49 c.t.Set(&a.t) 50 } 51 52 func NewTwistPoint() *twistPoint { 53 c := &twistPoint{} 54 c.SetInfinity() 55 return c 56 } 57 58 func NewTwistGenerator() *twistPoint { 59 c := &twistPoint{} 60 c.Set(twistGen) 61 return c 62 } 63 64 func (c *twistPoint) polynomial(x *gfP2) *gfP2 { 65 x3 := &gfP2{} 66 x3.Square(x).Mul(x3, x).Add(x3, twistB) 67 return x3 68 } 69 70 // IsOnCurve returns true iff c is on the curve. 71 func (c *twistPoint) IsOnCurve() bool { 72 c.MakeAffine() 73 if c.IsInfinity() { 74 return true 75 } 76 77 y2 := &gfP2{} 78 y2.Square(&c.y) 79 x3 := c.polynomial(&c.x) 80 81 return y2.Equal(x3) == 1 82 } 83 84 func (c *twistPoint) SetInfinity() { 85 c.x.SetZero() 86 c.y.SetOne() 87 c.z.SetZero() 88 c.t.SetZero() 89 } 90 91 func (c *twistPoint) IsInfinity() bool { 92 return c.z.IsZero() 93 } 94 95 func (c *twistPoint) Add(p1, p2 *twistPoint) { 96 // Complete addition formula for a = 0 from "Complete addition formulas for 97 // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §3.2. 98 // Algorithm 7: Complete, projective point addition for prime order j-invariant 0 short Weierstrass curves. 99 100 t0, t1, t2, t3, t4 := new(gfP2), new(gfP2), new(gfP2), new(gfP2), new(gfP2) 101 x3, y3, z3 := new(gfP2), new(gfP2), new(gfP2) 102 t0.Mul(&p1.x, &p2.x) // t0 := X1X2 103 t1.Mul(&p1.y, &p2.y) // t1 := Y1Y2 104 t2.Mul(&p1.z, &p2.z) // t2 := Z1Z2 105 t3.Add(&p1.x, &p1.y) // t3 := X1 + Y1 106 t4.Add(&p2.x, &p2.y) // t4 := X2 + Y2 107 t3.Mul(t3, t4) // t3 := t3 * t4 = (X1 + Y1) * (X2 + Y2) 108 t4.Add(t0, t1) // t4 := t0 + t1 109 t3.Sub(t3, t4) // t3 := t3 - t4 = X1Y2 + X2Y1 110 t4.Add(&p1.y, &p1.z) // t4 := Y1 + Z1 111 x3.Add(&p2.y, &p2.z) // X3 := Y2 + Z2 112 t4.Mul(t4, x3) // t4 := t4 * X3 = (Y1 + Z1)(Y2 + Z2) 113 x3.Add(t1, t2) // X3 := t1 + t2 114 t4.Sub(t4, x3) // t4 := t4 - X3 = Y1Z2 + Y2Z1 115 x3.Add(&p1.x, &p1.z) // X3 := X1 + Z1 116 y3.Add(&p2.x, &p2.z) // Y3 := X2 + Z2 117 x3.Mul(x3, y3) // X3 := X3 * Y3 118 y3.Add(t0, t2) // Y3 := t0 + t2 119 y3.Sub(x3, y3) // Y3 := X3 - Y3 = X1Z2 + X2Z1 120 t0.Triple(t0) // t0 := t0 + t0 + t0 = 3X1X2 121 t2.Mul(threeTwistB, t2) // t2 := 3b * t2 = 3bZ1Z2 122 z3.Add(t1, t2) // Z3 := t1 + t2 = Y1Y2 + 3bZ1Z2 123 t1.Sub(t1, t2) // t1 := t1 - t2 = Y1Y2 - 3bZ1Z2 124 y3.Mul(threeTwistB, y3) // Y3 = 3b * Y3 = 3b(X1Z2 + X2Z1) 125 x3.Mul(t4, y3) // X3 := t4 * Y3 = 3b(X1Z2 + X2Z1)(Y1Z2 + Y2Z1) 126 t2.Mul(t3, t1) // t2 := t3 * t1 = (X1Y2 + X2Y1)(Y1Y2 - 3bZ1Z2) 127 x3.Sub(t2, x3) // X3 := t2 - X3 = (X1Y2 + X2Y1)(Y1Y2 - 3bZ1Z2) - 3b(Y1Z2 + Y2Z1)(X1Z2 + X2Z1) 128 y3.Mul(y3, t0) // Y3 := Y3 * t0 = 9bX1X2(X1Z2 + X2Z1) 129 t1.Mul(t1, z3) // t1 := t1 * Z3 = (Y1Y2 + 3bZ1Z2)(Y1Y2 - 3bZ1Z2) 130 y3.Add(t1, y3) // Y3 := t1 + Y3 = (Y1Y2 + 3bZ1Z2)(Y1Y2 - 3bZ1Z2) + 9bX1X2(X1Z2 + X2Z1) 131 t0.Mul(t0, t3) // t0 := t0 * t3 = 3X1X2(X1Y2 + X2Y1) 132 z3.Mul(z3, t4) // Z3 := Z3 * t4 = (Y1Z2 + Y2Z1)(Y1Y2 + 3bZ1Z2) 133 z3.Add(z3, t0) // Z3 := Z3 + t0 = (Y1Z2 + Y2Z1)(Y1Y2 + 3bZ1Z2) + 3X1X2(X1Y2 + X2Y1) 134 135 c.x.Set(x3) 136 c.y.Set(y3) 137 c.z.Set(z3) 138 } 139 140 func (c *twistPoint) Double(p *twistPoint) { 141 // Complete addition formula for a = 0 from "Complete addition formulas for 142 // prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §3.2. 143 // Algorithm 9: Exception-free point doubling for prime order j-invariant 0 short Weierstrass curves. 144 t0, t1, t2 := new(gfP2), new(gfP2), new(gfP2) 145 x3, y3, z3 := new(gfP2), new(gfP2), new(gfP2) 146 147 t0.Square(&p.y) // t0 := Y^2 148 z3.Double(t0) // Z3 := t0 + t0 149 z3.Double(z3) // Z3 := Z3 + Z3 150 z3.Double(z3) // Z3 := Z3 + Z3 151 t1.Mul(&p.y, &p.z) // t1 := YZ 152 t2.Square(&p.z) // t2 := Z^2 153 t2.Mul(threeTwistB, t2) // t2 := 3b * t2 = 3bZ^2 154 x3.Mul(t2, z3) // X3 := t2 * Z3 155 y3.Add(t0, t2) // Y3 := t0 + t2 156 z3.Mul(t1, z3) // Z3 := t1 * Z3 157 t2.Triple(t2) // t2 := t2 + t2 + t2 158 t0.Sub(t0, t2) // t0 := t0 - t2 159 y3.Mul(t0, y3) // Y3 := t0 * Y3 160 y3.Add(x3, y3) // Y3 := X3 + Y3 161 t1.Mul(&p.x, &p.y) // t1 := XY 162 x3.Mul(t0, t1) // X3 := t0 * t1 163 x3.Double(x3) // X3 := X3 + X3 164 165 c.x.Set(x3) 166 c.y.Set(y3) 167 c.z.Set(z3) 168 } 169 170 func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int) { 171 sum, t := &twistPoint{}, &twistPoint{} 172 173 for i := scalar.BitLen(); i >= 0; i-- { 174 t.Double(sum) 175 if scalar.Bit(i) != 0 { 176 sum.Add(t, a) 177 } else { 178 sum.Set(t) 179 } 180 } 181 182 c.Set(sum) 183 } 184 185 // MakeAffine reverses the Projective transform. 186 // A = 1/Z1 187 // X3 = A*X1 188 // Y3 = A*Y1 189 // Z3 = 1 190 func (c *twistPoint) MakeAffine() { 191 // TODO: do we need to change it to constant-time implementation? 192 if c.z.IsOne() { 193 return 194 } else if c.z.IsZero() { 195 c.x.SetZero() 196 c.y.SetOne() 197 c.t.SetZero() 198 return 199 } 200 201 zInv := &gfP2{} 202 zInv.Invert(&c.z) 203 204 c.x.Mul(&c.x, zInv) 205 c.y.Mul(&c.y, zInv) 206 207 c.z.SetOne() 208 c.t.SetOne() 209 } 210 211 // MakeAffine reverses the Jacobian transform. 212 // the Jacobian coordinates are (x1, y1, z1) 213 // where x = x1/z1² and y = y1/z1³. 214 func (c *twistPoint) AffineFromJacobian() { 215 if c.z.IsOne() { 216 return 217 } else if c.z.IsZero() { 218 c.x.SetZero() 219 c.y.SetOne() 220 c.t.SetZero() 221 return 222 } 223 224 zInv := (&gfP2{}).Invert(&c.z) 225 t := (&gfP2{}).Mul(&c.y, zInv) 226 zInv2 := (&gfP2{}).Square(zInv) 227 c.y.Mul(t, zInv2) 228 t.Mul(&c.x, zInv2) 229 c.x.Set(t) 230 c.z.SetOne() 231 c.t.SetOne() 232 } 233 234 func (c *twistPoint) Neg(a *twistPoint) { 235 c.x.Set(&a.x) 236 c.y.Neg(&a.y) 237 c.z.Set(&a.z) 238 c.t.SetZero() 239 } 240 241 // code logic is form https://github.com/guanzhi/GmSSL/blob/develop/src/sm9_alg.c 242 // the value is not same as [p]a 243 func (c *twistPoint) Frobenius(a *twistPoint) { 244 c.x.Conjugate(&a.x) 245 c.y.Conjugate(&a.y) 246 c.z.Conjugate(&a.z) 247 c.z.MulScalar(&a.z, frobConstant) 248 c.t.Square(&a.z) 249 } 250 251 func (c *twistPoint) FrobeniusP2(a *twistPoint) { 252 c.x.Set(&a.x) 253 c.y.Set(&a.y) 254 c.z.MulScalar(&a.z, wToP2Minus1) 255 c.t.Square(&a.z) 256 } 257 258 func (c *twistPoint) NegFrobeniusP2(a *twistPoint) { 259 c.x.Set(&a.x) 260 c.y.Neg(&a.y) 261 c.z.MulScalar(&a.z, wToP2Minus1) 262 c.t.Square(&a.z) 263 } 264 265 // A twistPointTable holds the first 15 multiples of a point at offset -1, so [1]P 266 // is at table[0], [15]P is at table[14], and [0]P is implicitly the identity 267 // point. 268 type twistPointTable [15]*twistPoint 269 270 // Select selects the n-th multiple of the table base point into p. It works in 271 // constant time by iterating over every entry of the table. n must be in [0, 15]. 272 func (table *twistPointTable) Select(p *twistPoint, n uint8) { 273 if n >= 16 { 274 panic("sm9: internal error: twistPointTable called with out-of-bounds value") 275 } 276 p.SetInfinity() 277 for i, f := range table { 278 cond := subtle.ConstantTimeByteEq(uint8(i+1), n) 279 twistPointMovCond(p, f, p, cond) 280 } 281 } 282 283 /* 284 //code logic is from https://github.com/miracl/MIRACL/blob/master/source/curve/pairing/bn_pair.cpp 285 func (c *twistPoint) Frobenius(a *twistPoint) { 286 w, r, frob := &gfP2{}, &gfP2{}, &gfP2{} 287 frob.SetFrobConstant() 288 w.Square(frob) 289 290 r.Conjugate(&twistGen.x) 291 r.Mul(r, w) 292 c.x.Set(r) 293 294 r.Conjugate(&twistGen.y) 295 r.Mul(r, frob) 296 r.Mul(r, w) 297 c.y.Set(r) 298 299 r.Conjugate(&twistGen.z) 300 c.z.Set(r) 301 302 r.Square(&c.z) 303 c.t.Set(r) 304 } 305 306 func (c *twistPoint) FrobeniusP2(a *twistPoint) { 307 ret := &twistPoint{} 308 ret.Frobenius(a) 309 c.Frobenius(ret) 310 } 311 312 */ 313 /* 314 // code logic from https://github.com/cloudflare/bn256/blob/master/optate.go 315 func (c *twistPoint) Frobenius(a *twistPoint) { 316 r := &gfP2{} 317 r.Conjugate(&a.x) 318 r.MulScalar(r, xiToPMinus1Over3) 319 c.x.Set(r) 320 r.Conjugate(&a.y) 321 r.MulScalar(r, xiToPMinus1Over2) 322 c.y.Set(r) 323 c.z.SetOne() 324 c.t.SetOne() 325 } 326 327 func (c *twistPoint) FrobeniusP2(a *twistPoint) { 328 c.x.MulScalar(&a.x, xiToPSquaredMinus1Over3) 329 c.y.Neg(&a.y) 330 c.z.SetOne() 331 c.t.SetOne() 332 } 333 334 func (c *twistPoint) NegFrobeniusP2(a *twistPoint) { 335 c.x.MulScalar(&a.x, xiToPSquaredMinus1Over3) 336 c.y.Set(&a.y) 337 c.z.SetOne() 338 c.t.SetOne() 339 } 340 */