github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp12.go (about) 1 package bn256 2 3 import "math/big" 4 5 // For details of the algorithms used, see "Multiplication and Squaring on 6 // Pairing-Friendly Fields, Devegili et al. 7 // http://eprint.iacr.org/2006/471.pdf. 8 // 9 10 // gfP12 implements the field of size p¹² as a cubic extension of gfP4 where v³=u 11 type gfP12 struct { 12 x, y, z gfP4 // value is xw² + yw + z 13 } 14 15 func gfP12Decode(in *gfP12) *gfP12 { 16 out := &gfP12{} 17 out.x = *gfP4Decode(&in.x) 18 out.y = *gfP4Decode(&in.y) 19 out.z = *gfP4Decode(&in.z) 20 return out 21 } 22 23 var gfP12Gen *gfP12 = &gfP12{ 24 x: gfP4{ 25 x: gfP2{ 26 x: *fromBigInt(bigFromHex("256943fbdb2bf87ab91ae7fbeaff14e146cf7e2279b9d155d13461e09b22f523")), 27 y: *fromBigInt(bigFromHex("0167b0280051495c6af1ec23ba2cd2ff1cdcdeca461a5ab0b5449e9091308310")), 28 }, 29 y: gfP2{ 30 x: *fromBigInt(bigFromHex("5e7addaddf7fbfe16291b4e89af50b8217ddc47ba3cba833c6e77c3fb027685e")), 31 y: *fromBigInt(bigFromHex("79d0c8337072c93fef482bb055f44d6247ccac8e8e12525854b3566236337ebe")), 32 }, 33 }, 34 y: gfP4{ 35 x: gfP2{ 36 x: *fromBigInt(bigFromHex("082cde173022da8cd09b28a2d80a8cee53894436a52007f978dc37f36116d39b")), 37 y: *fromBigInt(bigFromHex("3fa7ed741eaed99a58f53e3df82df7ccd3407bcc7b1d44a9441920ced5fb824f")), 38 }, 39 y: gfP2{ 40 x: *fromBigInt(bigFromHex("7fc6eb2aa771d99c9234fddd31752edfd60723e05a4ebfdeb5c33fbd47e0cf06")), 41 y: *fromBigInt(bigFromHex("6fa6b6fa6dd6b6d3b19a959a110e748154eef796dc0fc2dd766ea414de786968")), 42 }, 43 }, 44 z: gfP4{ 45 x: gfP2{ 46 x: *fromBigInt(bigFromHex("8ffe1c0e9de45fd0fed790ac26be91f6b3f0a49c084fe29a3fb6ed288ad7994d")), 47 y: *fromBigInt(bigFromHex("1664a1366beb3196f0443e15f5f9042a947354a5678430d45ba031cff06db927")), 48 }, 49 y: gfP2{ 50 x: *fromBigInt(bigFromHex("7f7c6d52b475e6aaa827fdc5b4175ac6929320f782d998f86b6b57cda42a0426")), 51 y: *fromBigInt(bigFromHex("36a699de7c136f78eee2dbac4ca9727bff0cee02ee920f5822e65ea170aa9669")), 52 }, 53 }, 54 } 55 56 func (e *gfP12) String() string { 57 return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")" 58 } 59 60 func (e *gfP12) Set(a *gfP12) *gfP12 { 61 gfp12Copy(e, a) 62 return e 63 } 64 65 func (e *gfP12) SetZero() *gfP12 { 66 e.x.SetZero() 67 e.y.SetZero() 68 e.z.SetZero() 69 return e 70 } 71 72 func (e *gfP12) SetOne() *gfP12 { 73 e.x.SetZero() 74 e.y.SetZero() 75 e.z.SetOne() 76 return e 77 } 78 79 func (e *gfP12) SetW() *gfP12 { 80 e.x.SetZero() 81 e.y.SetOne() 82 e.z.SetZero() 83 return e 84 } 85 86 func (e *gfP12) SetW2() *gfP12 { 87 e.x.SetOne() 88 e.y.SetZero() 89 e.z.SetZero() 90 return e 91 } 92 93 func (e *gfP12) IsZero() bool { 94 return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() 95 } 96 97 func (e *gfP12) IsOne() bool { 98 return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() 99 } 100 101 func (e *gfP12) Add(a, b *gfP12) *gfP12 { 102 e.x.Add(&a.x, &b.x) 103 e.y.Add(&a.y, &b.y) 104 e.z.Add(&a.z, &b.z) 105 return e 106 } 107 108 func (e *gfP12) Sub(a, b *gfP12) *gfP12 { 109 e.x.Sub(&a.x, &b.x) 110 e.y.Sub(&a.y, &b.y) 111 e.z.Sub(&a.z, &b.z) 112 return e 113 } 114 115 func (e *gfP12) MulScalar(a *gfP12, b *gfP4) *gfP12 { 116 e.x.Mul(&a.x, b) 117 e.y.Mul(&a.y, b) 118 e.z.Mul(&a.z, b) 119 return e 120 } 121 122 func (e *gfP12) MulGFP2(a *gfP12, b *gfP2) *gfP12 { 123 e.x.MulScalar(&a.x, b) 124 e.y.MulScalar(&a.y, b) 125 e.z.MulScalar(&a.z, b) 126 return e 127 } 128 129 func (e *gfP12) MulGFP(a *gfP12, b *gfP) *gfP12 { 130 e.x.MulGFP(&a.x, b) 131 e.y.MulGFP(&a.y, b) 132 e.z.MulGFP(&a.z, b) 133 return e 134 } 135 136 func (e *gfP12) Mul(a, b *gfP12) *gfP12 { 137 tmp := &gfP12{} 138 tmp.MulNC(a, b) 139 gfp12Copy(e, tmp) 140 return e 141 } 142 143 // Mul without value copy, will use e directly, so e can't be same as a and b. 144 func (e *gfP12) MulNC(a, b *gfP12) *gfP12 { 145 // (z0 + y0*w + x0*w^2)* (z1 + y1*w + x1*w^2) 146 // z0*z1 + z0*y1*w + z0*x1*w^2 147 // +y0*z1*w + y0*y1*w^2 + y0*x1*v 148 // +x0*z1*w^2 + x0*y1*v + x0*x1*v*w 149 //=(z0*z1+y0*x1*v+x0*y1*v) + (z0*y1+y0*z1+x0*x1*v)w + (z0*x1 + y0*y1 + x0*z1)*w^2 150 // Karatsuba method 151 tx := &e.x 152 ty := &e.y 153 tz := &e.z 154 t, v0, v1, v2 := &gfP4{}, &gfP4{}, &gfP4{}, &gfP4{} 155 v0.MulNC(&a.z, &b.z) 156 v1.MulNC(&a.y, &b.y) 157 v2.MulNC(&a.x, &b.x) 158 159 t.Add(&a.y, &a.x) 160 tz.Add(&b.y, &b.x) 161 t.Mul(t, tz) 162 t.Sub(t, v1) 163 t.Sub(t, v2) 164 t.MulV1(t) 165 tz.Add(t, v0) 166 167 t.Add(&a.z, &a.y) 168 ty.Add(&b.z, &b.y) 169 ty.Mul(t, ty) 170 ty.Sub(ty, v0) 171 ty.Sub(ty, v1) 172 t.MulV1(v2) 173 ty.Add(ty, t) 174 175 t.Add(&a.z, &a.x) 176 tx.Add(&b.z, &b.x) 177 tx.Mul(tx, t) 178 tx.Sub(tx, v0) 179 tx.Add(tx, v1) 180 tx.Sub(tx, v2) 181 return e 182 } 183 184 func (e *gfP12) Square(a *gfP12) *gfP12 { 185 tmp := &gfP12{} 186 tmp.SquareNC(a) 187 gfp12Copy(e, tmp) 188 return e 189 } 190 191 // Square without value copy, will use e directly, so e can't be same as a. 192 func (e *gfP12) SquareNC(a *gfP12) *gfP12 { 193 // (z + y*w + x*w^2)* (z + y*w + x*w^2) 194 // z^2 + z*y*w + z*x*w^2 + y*z*w + y^2*w^2 + y*x*v + x*z*w^2 + x*y*v + x^2 *v *w 195 // (z^2 + y*x*v + x*y*v) + (z*y + y*z + v * x^2)w + (z*x + y^2 + x*z)*w^2 196 // (z^2 + 2*x*y*v) + (v*x^2 + 2*y*z) *w + (y^2 + 2*x*z) * w^2 197 // Karatsuba method 198 tx := &e.x 199 ty := &e.y 200 tz := &e.z 201 t, v0, v1, v2 := &gfP4{}, &gfP4{}, &gfP4{}, &gfP4{} 202 v0.SquareNC(&a.z) 203 v1.SquareNC(&a.y) 204 v2.SquareNC(&a.x) 205 206 t.Add(&a.y, &a.x) 207 tz.SquareNC(t) 208 tz.Sub(tz, v1) 209 tz.Sub(tz, v2) 210 tz.MulV1(tz) 211 tz.Add(tz, v0) 212 213 t.Add(&a.z, &a.y) 214 ty.SquareNC(t) 215 ty.Sub(ty, v0) 216 ty.Sub(ty, v1) 217 t.MulV1(v2) 218 ty.Add(ty, t) 219 220 t.Add(&a.z, &a.x) 221 tx.SquareNC(t) 222 tx.Sub(tx, v0) 223 tx.Add(tx, v1) 224 tx.Sub(tx, v2) 225 226 return e 227 } 228 229 // Cyclo6Square is used in final exponentiation after easy part(a ^ ((p^2 + 1)(p^6-1))). 230 // Note that after the easy part of the final exponentiation, 231 // the resulting element lies in cyclotomic subgroup. 232 // "New software speed records for cryptographic pairings" 233 // Section 3.3, Final exponentiation 234 // https://cryptojedi.org/papers/dclxvi-20100714.pdf 235 // The fomula reference: 236 // Granger/Scott (PKC2010). 237 // Section 3.2 238 // https://eprint.iacr.org/2009/565.pdf 239 func (e *gfP12) Cyclo6Square(a *gfP12) *gfP12 { 240 tmp := &gfP12{} 241 tmp.Cyclo6SquareNC(a) 242 gfp12Copy(e, tmp) 243 return e 244 } 245 246 // Special squaring loop for use on elements in T_6(fp2) (after the 247 // easy part of the final exponentiation. Used in the hard part 248 // of the final exponentiation. Function uses formulas in 249 // Granger/Scott (PKC2010). 250 func (e *gfP12) Cyclo6Squares(a *gfP12, n int) *gfP12 { 251 // Square first round 252 in := &gfP12{} 253 tx, ty, tz := &gfP4{}, &gfP4{}, &gfP4{} 254 255 v0 := &in.x 256 v1 := &in.y 257 v2 := &in.z 258 259 v0.SquareVNC(&a.x) // (t02, t10) 260 v1.SquareNC(&a.y) // (t12, t01) 261 v2.SquareNC(&a.z) // (t11, t00) 262 263 tx.Triple(v0) 264 ty.Triple(v1) 265 tz.Triple(v2) 266 267 v0.Double(&a.x) // (f12, f01) 268 v0.y.Neg(&v0.y) 269 v1.Double(&a.y) // (f02, f10) 270 v1.x.Neg(&v1.x) 271 v2.Double(&a.z) // (f11, f00) 272 v2.y.Neg(&v2.y) 273 274 v0.Add(ty, v0) 275 v1.Add(tx, v1) 276 v2.Add(tz, v2) 277 278 tmp := &gfP12{} 279 var tmp2 *gfP12 280 281 for i := 1; i < n; i++ { 282 v0 = &tmp.x 283 v1 = &tmp.y 284 v2 = &tmp.z 285 286 v0.SquareVNC(&in.x) // (t02, t10) 287 v1.SquareNC(&in.y) // (t12, t01) 288 v2.SquareNC(&in.z) // (t11, t00) 289 290 tx.Triple(v0) 291 ty.Triple(v1) 292 tz.Triple(v2) 293 294 v0.Double(&in.x) // (f12, f01) 295 v0.y.Neg(&v0.y) 296 v1.Double(&in.y) // (f02, f10) 297 v1.x.Neg(&v1.x) 298 v2.Double(&in.z) // (f11, f00) 299 v2.y.Neg(&v2.y) 300 301 v0.Add(ty, v0) 302 v1.Add(tx, v1) 303 v2.Add(tz, v2) 304 305 // Switch references 306 tmp2 = in 307 in = tmp 308 tmp = tmp2 309 } 310 gfp12Copy(e, in) 311 return e 312 } 313 314 // Special Square without value copy, will use e directly, so e can't be same as a. 315 func (e *gfP12) Cyclo6SquareNC(a *gfP12) *gfP12 { 316 tx, ty, tz := &gfP4{}, &gfP4{}, &gfP4{} 317 318 v0 := &e.x 319 v1 := &e.y 320 v2 := &e.z 321 322 v0.SquareVNC(&a.x) // (t02, t10) 323 v1.SquareNC(&a.y) // (t12, t01) 324 v2.SquareNC(&a.z) // (t11, t00) 325 326 tx.Triple(v0) 327 ty.Triple(v1) 328 tz.Triple(v2) 329 330 v0.Double(&a.x) // (f12, f01) 331 v0.y.Neg(&v0.y) 332 v1.Double(&a.y) // (f02, f10) 333 v1.x.Neg(&v1.x) 334 v2.Double(&a.z) // (f11, f00) 335 v2.y.Neg(&v2.y) 336 337 v0.Add(ty, v0) 338 v1.Add(tx, v1) 339 v2.Add(tz, v2) 340 341 return e 342 } 343 344 func (e *gfP12) Squares(a *gfP12, n int) *gfP12 { 345 // Square first round 346 in := &gfP12{} 347 tx := &in.x 348 ty := &in.y 349 tz := &in.z 350 t, v0, v1, v2 := &gfP4{}, &gfP4{}, &gfP4{}, &gfP4{} 351 352 v0.SquareNC(&a.z) 353 v1.SquareNC(&a.y) 354 v2.SquareNC(&a.x) 355 356 t.Add(&a.y, &a.x) 357 tz.SquareNC(t) 358 tz.Sub(tz, v1) 359 tz.Sub(tz, v2) 360 tz.MulV1(tz) 361 tz.Add(tz, v0) 362 363 t.Add(&a.z, &a.y) 364 ty.SquareNC(t) 365 ty.Sub(ty, v0) 366 ty.Sub(ty, v1) 367 t.MulV1(v2) 368 ty.Add(ty, t) 369 370 t.Add(&a.z, &a.x) 371 tx.SquareNC(t) 372 tx.Sub(tx, v0) 373 tx.Add(tx, v1) 374 tx.Sub(tx, v2) 375 376 tmp := &gfP12{} 377 var tmp2 *gfP12 378 379 for i := 1; i < n; i++ { 380 tx = &tmp.x 381 ty = &tmp.y 382 tz = &tmp.z 383 384 v0.SquareNC(&in.z) 385 v1.SquareNC(&in.y) 386 v2.SquareNC(&in.x) 387 388 t.Add(&in.y, &in.x) 389 tz.SquareNC(t) 390 tz.Sub(tz, v1) 391 tz.Sub(tz, v2) 392 tz.MulV1(tz) 393 tz.Add(tz, v0) 394 395 t.Add(&in.z, &in.y) 396 ty.SquareNC(t) 397 ty.Sub(ty, v0) 398 ty.Sub(ty, v1) 399 t.MulV1(v2) 400 ty.Add(ty, t) 401 402 t.Add(&in.z, &in.x) 403 tx.SquareNC(t) 404 tx.Sub(tx, v0) 405 tx.Add(tx, v1) 406 tx.Sub(tx, v2) 407 408 // Switch references 409 tmp2 = in 410 in = tmp 411 tmp = tmp2 412 } 413 gfp12Copy(e, in) 414 return e 415 } 416 417 func (e *gfP12) Exp(f *gfP12, power *big.Int) *gfP12 { 418 sum := (&gfP12{}).SetOne() 419 t := &gfP12{} 420 421 for i := power.BitLen() - 1; i >= 0; i-- { 422 t.Square(sum) 423 if power.Bit(i) != 0 { 424 sum.Mul(t, f) 425 } else { 426 sum.Set(t) 427 } 428 } 429 gfp12Copy(e, sum) 430 return e 431 } 432 433 func (e *gfP12) Invert(a *gfP12) *gfP12 { 434 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 435 // ftp://136.206.11.249/pub/crypto/pairings.pdf 436 437 // Here we can give a short explanation of how it works: let j be a cubic root of 438 // unity in GF(p^4) so that 1+j+j²=0. 439 // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z) 440 // = (xτ² + yτ + z)(Cτ²+Bτ+A) 441 // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). 442 // 443 // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) 444 // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) 445 // 446 // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) 447 t1 := (&gfP4{}).MulVNC(&a.x, &a.y) 448 A := (&gfP4{}).SquareNC(&a.z) 449 A.Sub(A, t1) 450 451 B := (&gfP4{}).SquareVNC(&a.x) 452 t1.Mul(&a.y, &a.z) 453 B.Sub(B, t1) 454 455 C := (&gfP4{}).SquareNC(&a.y) 456 t1.Mul(&a.x, &a.z) 457 C.Sub(C, t1) 458 459 F := (&gfP4{}).MulVNC(C, &a.y) 460 t1.Mul(A, &a.z) 461 F.Add(F, t1) 462 t1.MulV(B, &a.x) 463 F.Add(F, t1) 464 465 F.Invert(F) 466 467 e.x.Mul(C, F) 468 e.y.Mul(B, F) 469 e.z.Mul(A, F) 470 return e 471 } 472 473 func (e *gfP12) Neg(a *gfP12) *gfP12 { 474 e.x.Neg(&a.x) 475 e.y.Neg(&a.y) 476 e.z.Neg(&a.z) 477 return e 478 } 479 480 // (z + y*w + x*w^2)^p 481 // = z^p + y^p*w*w^(p-1)+x^p*w^2*(w^2)^(p-1) 482 // w2ToP2Minus1 = vToPMinus1 * wToPMinus1 483 func (e *gfP12) Frobenius(a *gfP12) *gfP12 { 484 tmp := &gfP4{} 485 x := &tmp.x 486 y := &tmp.y 487 488 x.Conjugate(&a.z.x) 489 y.Conjugate(&a.z.y) 490 x.MulScalar(x, vToPMinus1) 491 gfp4Copy(&e.z, tmp) 492 493 x.Conjugate(&a.y.x) 494 y.Conjugate(&a.y.y) 495 x.MulScalar(x, w2ToP2Minus1) 496 y.MulScalar(y, wToPMinus1) 497 gfp4Copy(&e.y, tmp) 498 499 x.Conjugate(&a.x.x) 500 y.Conjugate(&a.x.y) 501 x.MulScalar(x, vToPMinus1Mw2ToPMinus1) 502 y.MulScalar(y, w2ToPMinus1) 503 gfp4Copy(&e.x, tmp) 504 505 return e 506 } 507 508 // (z + y*w + x*w^2)^(p^2) 509 // = z^(p^2) + y^(p^2)*w*w^((p^2)-1)+x^(p^2)*w^2*(w^2)^((p^2)-1) 510 func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 { 511 tx := &e.x 512 ty := &e.y 513 tz := &e.z 514 515 tz.Conjugate(&a.z) 516 517 ty.Conjugate(&a.y) 518 ty.MulGFP(ty, wToP2Minus1) 519 520 tx.Conjugate(&a.x) 521 tx.MulGFP(tx, w2ToP2Minus1) 522 return e 523 } 524 525 // (z + y*w + x*w^2)^(p^3) 526 // =z^(p^3) + y^(p^3)*w*w^((p^3)-1)+x^(p^3)*w^2*(w^2)^((p^3)-1) 527 // =z^(p^3) + y^(p^3)*w*vToPMinus1-x^(p^3)*w^2 528 // vToPMinus1 * vToPMinus1 = -1 529 func (e *gfP12) FrobeniusP3(a *gfP12) *gfP12 { 530 x, y := &gfP2{}, &gfP2{} 531 532 x.Conjugate(&a.z.x) 533 y.Conjugate(&a.z.y) 534 x.MulScalar(x, vToPMinus1) 535 x.Neg(x) 536 e.z.x.Set(x) 537 e.z.y.Set(y) 538 539 x.Conjugate(&a.y.x) 540 y.Conjugate(&a.y.y) 541 //x.MulScalar(x, vToPMinus1) 542 //x.Neg(x) 543 //x.MulScalar(x, vToPMinus1) 544 y.MulScalar(y, vToPMinus1) 545 e.y.x.Set(x) 546 e.y.y.Set(y) 547 548 x.Conjugate(&a.x.x) 549 y.Conjugate(&a.x.y) 550 x.MulScalar(x, vToPMinus1) 551 y.Neg(y) 552 e.x.x.Set(x) 553 e.x.y.Set(y) 554 555 return e 556 } 557 558 // (z + y*w + x*w^2)^(p^6) 559 // = ((z + y*w + x*w^2)^(p^3))^(p^3) 560 func (e *gfP12) FrobeniusP6(a *gfP12) *gfP12 { 561 tx := &e.x 562 ty := &e.y 563 tz := &e.z 564 565 tz.Conjugate(&a.z) 566 567 ty.Conjugate(&a.y) 568 ty.Neg(ty) 569 570 tx.Conjugate(&a.x) 571 572 return e 573 } 574 575 // code logic from https://github.com/miracl/MIRACL/blob/master/source/curve/pairing/zzn12a.h 576 func (e *gfP12) Conjugate(a *gfP12) *gfP12 { 577 e.z.Conjugate(&a.z) 578 e.y.Conjugate(&a.y) 579 e.y.Neg(&e.y) 580 e.x.Conjugate(&a.x) 581 return e 582 } 583 584 // Select sets q to p1 if cond == 1, and to p2 if cond == 0. 585 func (q *gfP12) Select(p1, p2 *gfP12, cond int) *gfP12 { 586 q.x.Select(&p1.x, &p2.x, cond) 587 q.y.Select(&p1.y, &p2.y, cond) 588 q.z.Select(&p1.z, &p2.z, cond) 589 return q 590 }