github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp12_b6.go (about) 1 package bn256 2 3 import "math/big" 4 5 // gfP12b6 implements the field of size p¹² as a quadratic extension of gfP6 6 // where t²=s. 7 type gfP12b6 struct { 8 x, y gfP6 // value is xt + y 9 } 10 11 func gfP12b6Decode(in *gfP12b6) *gfP12b6 { 12 out := &gfP12b6{} 13 out.x = *gfP6Decode(&in.x) 14 out.y = *gfP6Decode(&in.y) 15 return out 16 } 17 18 var gfP12b6Gen *gfP12b6 = &gfP12b6{ 19 x: gfP6{ 20 x: gfP2{ 21 x: *fromBigInt(bigFromHex("256943fbdb2bf87ab91ae7fbeaff14e146cf7e2279b9d155d13461e09b22f523")), 22 y: *fromBigInt(bigFromHex("0167b0280051495c6af1ec23ba2cd2ff1cdcdeca461a5ab0b5449e9091308310")), 23 }, 24 y: gfP2{ 25 x: *fromBigInt(bigFromHex("8ffe1c0e9de45fd0fed790ac26be91f6b3f0a49c084fe29a3fb6ed288ad7994d")), 26 y: *fromBigInt(bigFromHex("1664a1366beb3196f0443e15f5f9042a947354a5678430d45ba031cff06db927")), 27 }, 28 z: gfP2{ 29 x: *fromBigInt(bigFromHex("7fc6eb2aa771d99c9234fddd31752edfd60723e05a4ebfdeb5c33fbd47e0cf06")), 30 y: *fromBigInt(bigFromHex("6fa6b6fa6dd6b6d3b19a959a110e748154eef796dc0fc2dd766ea414de786968")), 31 }, 32 }, 33 y: gfP6{ 34 x: gfP2{ 35 x: *fromBigInt(bigFromHex("082cde173022da8cd09b28a2d80a8cee53894436a52007f978dc37f36116d39b")), 36 y: *fromBigInt(bigFromHex("3fa7ed741eaed99a58f53e3df82df7ccd3407bcc7b1d44a9441920ced5fb824f")), 37 }, 38 y: gfP2{ 39 x: *fromBigInt(bigFromHex("5e7addaddf7fbfe16291b4e89af50b8217ddc47ba3cba833c6e77c3fb027685e")), 40 y: *fromBigInt(bigFromHex("79d0c8337072c93fef482bb055f44d6247ccac8e8e12525854b3566236337ebe")), 41 }, 42 z: gfP2{ 43 x: *fromBigInt(bigFromHex("7f7c6d52b475e6aaa827fdc5b4175ac6929320f782d998f86b6b57cda42a0426")), 44 y: *fromBigInt(bigFromHex("36a699de7c136f78eee2dbac4ca9727bff0cee02ee920f5822e65ea170aa9669")), 45 }, 46 }, 47 } 48 49 func (e *gfP12b6) String() string { 50 return "(" + e.x.String() + "," + e.y.String() + ")" 51 } 52 53 func (e *gfP12b6) ToGfP12() *gfP12 { 54 ret := &gfP12{} 55 56 ret.z.y.Set(&e.y.z) 57 ret.x.y.Set(&e.y.y) 58 ret.y.x.Set(&e.y.x) 59 ret.y.y.Set(&e.x.z) 60 ret.z.x.Set(&e.x.y) 61 ret.x.x.Set(&e.x.x) 62 63 return ret 64 } 65 66 func (e *gfP12b6) SetGfP12(a *gfP12) *gfP12b6 { 67 e.y.z.Set(&a.z.y) //a 68 e.y.y.Set(&a.x.y) //b 69 e.y.x.Set(&a.y.x) 70 e.x.z.Set(&a.y.y) 71 e.x.y.Set(&a.z.x) //c 72 e.x.x.Set(&a.x.x) 73 74 return e 75 } 76 77 func (e *gfP12b6) Set(a *gfP12b6) *gfP12b6 { 78 e.x.Set(&a.x) 79 e.y.Set(&a.y) 80 return e 81 } 82 83 func (e *gfP12b6) SetZero() *gfP12b6 { 84 e.x.SetZero() 85 e.y.SetZero() 86 return e 87 } 88 89 func (e *gfP12b6) SetOne() *gfP12b6 { 90 e.x.SetZero() 91 e.y.SetOne() 92 return e 93 } 94 95 func (e *gfP12b6) IsZero() bool { 96 return e.x.IsZero() && e.y.IsZero() 97 } 98 99 func (e *gfP12b6) IsOne() bool { 100 return e.x.IsZero() && e.y.IsOne() 101 } 102 103 func (e *gfP12b6) Neg(a *gfP12b6) *gfP12b6 { 104 e.x.Neg(&a.x) 105 e.y.Neg(&a.y) 106 return e 107 } 108 109 func (e *gfP12b6) Conjugate(a *gfP12b6) *gfP12b6 { 110 e.x.Neg(&a.x) 111 e.y.Set(&a.y) 112 return e 113 } 114 115 func (e *gfP12b6) Add(a, b *gfP12b6) *gfP12b6 { 116 e.x.Add(&a.x, &b.x) 117 e.y.Add(&a.y, &b.y) 118 return e 119 } 120 121 func (e *gfP12b6) Sub(a, b *gfP12b6) *gfP12b6 { 122 e.x.Sub(&a.x, &b.x) 123 e.y.Sub(&a.y, &b.y) 124 return e 125 } 126 127 func (e *gfP12b6) Mul(a, b *gfP12b6) *gfP12b6 { 128 tmp := &gfP12b6{} 129 tmp.MulNC(a, b) 130 e.x.Set(&tmp.x) 131 e.y.Set(&tmp.y) 132 return e 133 } 134 135 // Mul without value copy, will use e directly, so e can't be same as a and b. 136 func (e *gfP12b6) MulNC(a, b *gfP12b6) *gfP12b6 { 137 // "Multiplication and Squaring on Pairing-Friendly Fields" 138 // Section 4, Karatsuba method. 139 // http://eprint.iacr.org/2006/471.pdf 140 //(a0+a1*t)(b0+b1*t)=c0+c1*t, where 141 //c0 = a0*b0 +a1*b1*s 142 //c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 = a0*b1 + a1*b0 143 tx := &e.x 144 ty := &e.y 145 v0, v1 := &gfP6{}, &gfP6{} 146 v0.MulNC(&a.y, &b.y) 147 v1.MulNC(&a.x, &b.x) 148 149 tx.Add(&a.x, &a.y) 150 ty.Add(&b.x, &b.y) 151 tx.Mul(tx, ty) 152 tx.Sub(tx, v0) 153 tx.Sub(tx, v1) 154 155 ty.MulS(v1) 156 ty.Add(ty, v0) 157 158 return e 159 } 160 161 func (e *gfP12b6) MulScalar(a *gfP12b6, b *gfP6) *gfP12b6 { 162 e.x.Mul(&a.x, b) 163 e.y.Mul(&a.y, b) 164 return e 165 } 166 167 func (e *gfP12b6) MulGfP(a *gfP12b6, b *gfP) *gfP12b6 { 168 e.x.MulGfP(&a.x, b) 169 e.y.MulGfP(&a.y, b) 170 return e 171 } 172 173 func (e *gfP12b6) MulGfP2(a *gfP12b6, b *gfP2) *gfP12b6 { 174 e.x.MulScalar(&a.x, b) 175 e.y.MulScalar(&a.y, b) 176 return e 177 } 178 179 func (e *gfP12b6) Square(a *gfP12b6) *gfP12b6 { 180 tmp := &gfP12b6{} 181 tmp.SquareNC(a) 182 e.x.Set(&tmp.x) 183 e.y.Set(&tmp.y) 184 return e 185 } 186 187 // Square without value copy, will use e directly, so e can't be same as a. 188 func (e *gfP12b6) SquareNC(a *gfP12b6) *gfP12b6 { 189 // Complex squaring algorithm 190 // (xt+y)² = (x^2*s + y^2) + 2*x*y*t 191 tx := &e.x 192 ty := &e.y 193 194 tx.SquareNC(&a.x).MulS(tx) 195 ty.SquareNC(&a.y) 196 ty.Add(tx, ty) 197 198 tx.Mul(&a.x, &a.y) 199 tx.Add(tx, tx) 200 201 return e 202 } 203 204 // Cyclo6Square is used in final exponentiation after easy part(a ^ ((p^2 + 1)(p^6-1))). 205 // Note that after the easy part of the final exponentiation, 206 // the resulting element lies in cyclotomic subgroup. 207 // "New software speed records for cryptographic pairings" 208 // Section 3.3, Final exponentiation 209 // https://cryptojedi.org/papers/dclxvi-20100714.pdf 210 // The fomula reference: 211 // Granger/Scott (PKC2010). 212 // Section 3.2 213 // https://eprint.iacr.org/2009/565.pdf 214 func (e *gfP12b6) Cyclo6Square(a *gfP12b6) *gfP12b6 { 215 tmp := &gfP12b6{} 216 tmp.Cyclo6SquareNC(a) 217 e.x.Set(&tmp.x) 218 e.y.Set(&tmp.y) 219 return e 220 } 221 222 // Special Square without value copy, will use e directly, so e can't be same as a. 223 func (e *gfP12b6) Cyclo6SquareNC(a *gfP12b6) *gfP12b6 { 224 f02 := &e.y.x 225 f01 := &e.y.y 226 f00 := &e.y.z 227 f12 := &e.x.x 228 f11 := &e.x.y 229 f10 := &e.x.z 230 231 t00, t01, t02, t10, t11, t12 := &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{} 232 233 gfP4Square(t11, t00, &a.x.y, &a.y.z) 234 gfP4Square(t12, t01, &a.y.x, &a.x.z) 235 gfP4Square(t02, t10, &a.x.x, &a.y.y) 236 237 f00.MulU1(t02) 238 t02.Set(t10) 239 t10.Set(f00) 240 241 f00.Add(t00, t00) 242 t00.Add(f00, t00) 243 f00.Add(t01, t01) 244 t01.Add(f00, t01) 245 f00.Add(t02, t02) 246 t02.Add(f00, t02) 247 f00.Add(t10, t10) 248 t10.Add(f00, t10) 249 f00.Add(t11, t11) 250 t11.Add(f00, t11) 251 f00.Add(t12, t12) 252 t12.Add(f00, t12) 253 254 f00.Add(&a.y.z, &a.y.z) 255 f00.Neg(f00) 256 f01.Add(&a.y.y, &a.y.y) 257 f01.Neg(f01) 258 f02.Add(&a.y.x, &a.y.x) 259 f02.Neg(f02) 260 f10.Add(&a.x.z, &a.x.z) 261 f11.Add(&a.x.y, &a.x.y) 262 f12.Add(&a.x.x, &a.x.x) 263 264 f00.Add(f00, t00) 265 f01.Add(f01, t01) 266 f02.Add(f02, t02) 267 f10.Add(f10, t10) 268 f11.Add(f11, t11) 269 f12.Add(f12, t12) 270 271 return e 272 } 273 274 func (e *gfP12b6) Cyclo6Squares(a *gfP12b6, n int) *gfP12b6 { 275 // Square first round 276 in := &gfP12b6{} 277 f02 := &in.y.x 278 f01 := &in.y.y 279 f00 := &in.y.z 280 f12 := &in.x.x 281 f11 := &in.x.y 282 f10 := &in.x.z 283 284 t00, t01, t02, t10, t11, t12 := &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{} 285 gfP4Square(t11, t00, &a.x.y, &a.y.z) 286 gfP4Square(t12, t01, &a.y.x, &a.x.z) 287 gfP4Square(t02, t10, &a.x.x, &a.y.y) 288 289 f00.MulU1(t02) 290 t02.Set(t10) 291 t10.Set(f00) 292 293 f00.Add(t00, t00) 294 t00.Add(f00, t00) 295 f00.Add(t01, t01) 296 t01.Add(f00, t01) 297 f00.Add(t02, t02) 298 t02.Add(f00, t02) 299 f00.Add(t10, t10) 300 t10.Add(f00, t10) 301 f00.Add(t11, t11) 302 t11.Add(f00, t11) 303 f00.Add(t12, t12) 304 t12.Add(f00, t12) 305 306 f00.Add(&a.y.z, &a.y.z) 307 f00.Neg(f00) 308 f01.Add(&a.y.y, &a.y.y) 309 f01.Neg(f01) 310 f02.Add(&a.y.x, &a.y.x) 311 f02.Neg(f02) 312 f10.Add(&a.x.z, &a.x.z) 313 f11.Add(&a.x.y, &a.x.y) 314 f12.Add(&a.x.x, &a.x.x) 315 316 f00.Add(f00, t00) 317 f01.Add(f01, t01) 318 f02.Add(f02, t02) 319 f10.Add(f10, t10) 320 f11.Add(f11, t11) 321 f12.Add(f12, t12) 322 323 tmp := &gfP12b6{} 324 var tmp2 *gfP12b6 325 326 for i := 1; i < n; i++ { 327 f02 = &tmp.y.x 328 f01 = &tmp.y.y 329 f00 = &tmp.y.z 330 f12 = &tmp.x.x 331 f11 = &tmp.x.y 332 f10 = &tmp.x.z 333 334 gfP4Square(t11, t00, &in.x.y, &in.y.z) 335 gfP4Square(t12, t01, &in.y.x, &in.x.z) 336 gfP4Square(t02, t10, &in.x.x, &in.y.y) 337 338 f00.MulU1(t02) 339 t02.Set(t10) 340 t10.Set(f00) 341 342 f00.Add(t00, t00) 343 t00.Add(f00, t00) 344 f00.Add(t01, t01) 345 t01.Add(f00, t01) 346 f00.Add(t02, t02) 347 t02.Add(f00, t02) 348 f00.Add(t10, t10) 349 t10.Add(f00, t10) 350 f00.Add(t11, t11) 351 t11.Add(f00, t11) 352 f00.Add(t12, t12) 353 t12.Add(f00, t12) 354 355 f00.Add(&in.y.z, &in.y.z) 356 f00.Neg(f00) 357 f01.Add(&in.y.y, &in.y.y) 358 f01.Neg(f01) 359 f02.Add(&in.y.x, &in.y.x) 360 f02.Neg(f02) 361 f10.Add(&in.x.z, &in.x.z) 362 f11.Add(&in.x.y, &in.x.y) 363 f12.Add(&in.x.x, &in.x.x) 364 365 f00.Add(f00, t00) 366 f01.Add(f01, t01) 367 f02.Add(f02, t02) 368 f10.Add(f10, t10) 369 f11.Add(f11, t11) 370 f12.Add(f12, t12) 371 372 // Switch references 373 tmp2 = in 374 in = tmp 375 tmp = tmp2 376 } 377 e.x.Set(&in.x) 378 e.y.Set(&in.y) 379 return e 380 } 381 382 func gfP4Square(retX, retY, x, y *gfP2) { 383 retX.SquareU(x) 384 retY.Square(y) 385 retY.Add(retX, retY) 386 387 retX.Mul(x, y) 388 retX.Add(retX, retX) 389 } 390 391 func (c *gfP12b6) Exp(a *gfP12b6, power *big.Int) *gfP12b6 { 392 sum := (&gfP12b6{}).SetOne() 393 t := &gfP12b6{} 394 395 for i := power.BitLen() - 1; i >= 0; i-- { 396 t.Square(sum) 397 if power.Bit(i) != 0 { 398 sum.Mul(t, a) 399 } else { 400 sum.Set(t) 401 } 402 } 403 404 c.Set(sum) 405 return c 406 } 407 408 func (e *gfP12b6) Invert(a *gfP12b6) *gfP12b6 { 409 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 410 // ftp://136.206.11.249/pub/crypto/pairings.pdf 411 412 t0, t1 := &gfP6{}, &gfP6{} 413 414 t0.MulNC(&a.y, &a.y) 415 t1.MulNC(&a.x, &a.x).MulS(t1) 416 t0.Sub(t0, t1) 417 t0.Invert(t0) 418 419 e.x.Neg(&a.x) 420 e.y.Set(&a.y) 421 e.MulScalar(e, t0) 422 423 return e 424 } 425 426 // Frobenius computes (xt+y)^p 427 // = x^p t^p + y^p 428 // = x^p t^(p-1) t + y^p 429 // = x^p s^((p-1)/2) t + y^p 430 // sToPMinus1Over2 431 func (e *gfP12b6) Frobenius(a *gfP12b6) *gfP12b6 { 432 e.x.Frobenius(&a.x) 433 e.y.Frobenius(&a.y) 434 e.x.MulGfP(&e.x, sToPMinus1Over2) 435 return e 436 } 437 438 // FrobeniusP2 computes (xt+y)^p² = x^p² t ·s^((p²-1)/2) + y^p² 439 func (e *gfP12b6) FrobeniusP2(a *gfP12b6) *gfP12b6 { 440 e.x.FrobeniusP2(&a.x) 441 e.y.FrobeniusP2(&a.y) 442 e.x.MulGfP(&e.x, sToPSquaredMinus1Over2) 443 return e 444 } 445 446 func (e *gfP12b6) FrobeniusP4(a *gfP12b6) *gfP12b6 { 447 e.x.FrobeniusP4(&a.x) 448 e.y.FrobeniusP4(&a.y) 449 e.x.MulGfP(&e.x, sToPSquaredMinus1) 450 return e 451 } 452 453 func (e *gfP12b6) FrobeniusP6(a *gfP12b6) *gfP12b6 { 454 e.x.Neg(&a.x) 455 e.y.Set(&a.y) 456 return e 457 } 458 459 // Select sets q to p1 if cond == 1, and to p2 if cond == 0. 460 func (q *gfP12b6) Select(p1, p2 *gfP12b6, cond int) *gfP12b6 { 461 q.x.Select(&p1.x, &p2.x, cond) 462 q.y.Select(&p1.y, &p2.y, cond) 463 return q 464 }