github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-317/g2.go (about) 1 // Copyright 2020 Consensys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package bls24317 18 19 import ( 20 "crypto/rand" 21 "github.com/consensys/gnark-crypto/ecc" 22 "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" 23 "github.com/consensys/gnark-crypto/ecc/bls24-317/internal/fptower" 24 "github.com/consensys/gnark-crypto/internal/parallel" 25 "math/big" 26 "runtime" 27 ) 28 29 // G2Affine is a point in affine coordinates (x,y) 30 type G2Affine struct { 31 X, Y fptower.E4 32 } 33 34 // G2Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) 35 type G2Jac struct { 36 X, Y, Z fptower.E4 37 } 38 39 // g2JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) 40 type g2JacExtended struct { 41 X, Y, ZZ, ZZZ fptower.E4 42 } 43 44 // g2Proj point in projective coordinates 45 type g2Proj struct { 46 x, y, z fptower.E4 47 } 48 49 // ------------------------------------------------------------------------------------------------- 50 // Affine coordinates 51 52 // Set sets p to a in affine coordinates. 53 func (p *G2Affine) Set(a *G2Affine) *G2Affine { 54 p.X, p.Y = a.X, a.Y 55 return p 56 } 57 58 // setInfinity sets p to the infinity point, which is encoded as (0,0). 59 // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). 60 func (p *G2Affine) setInfinity() *G2Affine { 61 p.X.SetZero() 62 p.Y.SetZero() 63 return p 64 } 65 66 // ScalarMultiplication computes and returns p = [s]a 67 // where p and a are affine points. 68 func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { 69 var _p G2Jac 70 _p.FromAffine(a) 71 _p.mulGLV(&_p, s) 72 p.FromJacobian(&_p) 73 return p 74 } 75 76 // ScalarMultiplicationBase computes and returns p = [s]g 77 // where g is the affine point generating the prime subgroup. 78 func (p *G2Affine) ScalarMultiplicationBase(s *big.Int) *G2Affine { 79 var _p G2Jac 80 _p.mulGLV(&g2Gen, s) 81 p.FromJacobian(&_p) 82 return p 83 } 84 85 // Add adds two points in affine coordinates. 86 // It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. 87 // 88 // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl 89 func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { 90 var q G2Jac 91 // a is infinity, return b 92 if a.IsInfinity() { 93 p.Set(b) 94 return p 95 } 96 // b is infinity, return a 97 if b.IsInfinity() { 98 p.Set(a) 99 return p 100 } 101 if a.X.Equal(&b.X) { 102 // if b == a, we double instead 103 if a.Y.Equal(&b.Y) { 104 q.DoubleMixed(a) 105 return p.FromJacobian(&q) 106 } else { 107 // if b == -a, we return 0 108 return p.setInfinity() 109 } 110 } 111 var H, HH, I, J, r, V fptower.E4 112 H.Sub(&b.X, &a.X) 113 HH.Square(&H) 114 I.Double(&HH).Double(&I) 115 J.Mul(&H, &I) 116 r.Sub(&b.Y, &a.Y) 117 r.Double(&r) 118 V.Mul(&a.X, &I) 119 q.X.Square(&r). 120 Sub(&q.X, &J). 121 Sub(&q.X, &V). 122 Sub(&q.X, &V) 123 q.Y.Sub(&V, &q.X). 124 Mul(&q.Y, &r) 125 J.Mul(&a.Y, &J).Double(&J) 126 q.Y.Sub(&q.Y, &J) 127 q.Z.Double(&H) 128 129 return p.FromJacobian(&q) 130 } 131 132 // Double doubles a point in affine coordinates. 133 // It converts the point to Jacobian coordinates, doubles it using Jacobian 134 // addition with a.Z=1, and converts it back to affine coordinates. 135 // 136 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl 137 func (p *G2Affine) Double(a *G2Affine) *G2Affine { 138 var q G2Jac 139 q.FromAffine(a) 140 q.DoubleMixed(a) 141 p.FromJacobian(&q) 142 return p 143 } 144 145 // Sub subtracts two points in affine coordinates. 146 // It uses a similar approach to Add, but negates the second point before adding. 147 func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { 148 var bneg G2Affine 149 bneg.Neg(b) 150 p.Add(a, &bneg) 151 return p 152 } 153 154 // Equal tests if two points in affine coordinates are equal. 155 func (p *G2Affine) Equal(a *G2Affine) bool { 156 return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) 157 } 158 159 // Neg sets p to the affine negative point -a = (a.X, -a.Y). 160 func (p *G2Affine) Neg(a *G2Affine) *G2Affine { 161 p.X = a.X 162 p.Y.Neg(&a.Y) 163 return p 164 } 165 166 // FromJacobian converts a point p1 from Jacobian to affine coordinates. 167 func (p *G2Affine) FromJacobian(p1 *G2Jac) *G2Affine { 168 169 var a, b fptower.E4 170 171 if p1.Z.IsZero() { 172 p.X.SetZero() 173 p.Y.SetZero() 174 return p 175 } 176 177 a.Inverse(&p1.Z) 178 b.Square(&a) 179 p.X.Mul(&p1.X, &b) 180 p.Y.Mul(&p1.Y, &b).Mul(&p.Y, &a) 181 182 return p 183 } 184 185 // String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. 186 func (p *G2Affine) String() string { 187 if p.IsInfinity() { 188 return "O" 189 } 190 return "E([" + p.X.String() + "," + p.Y.String() + "])" 191 } 192 193 // IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). 194 // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). 195 func (p *G2Affine) IsInfinity() bool { 196 return p.X.IsZero() && p.Y.IsZero() 197 } 198 199 // IsOnCurve returns true if the affine point p in on the curve. 200 func (p *G2Affine) IsOnCurve() bool { 201 var point G2Jac 202 point.FromAffine(p) 203 return point.IsOnCurve() // call this function to handle infinity point 204 } 205 206 // IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. 207 func (p *G2Affine) IsInSubGroup() bool { 208 var _p G2Jac 209 _p.FromAffine(p) 210 return _p.IsInSubGroup() 211 } 212 213 // ------------------------------------------------------------------------------------------------- 214 // Jacobian coordinates 215 216 // Set sets p to a in Jacobian coordinates. 217 func (p *G2Jac) Set(q *G2Jac) *G2Jac { 218 p.X, p.Y, p.Z = q.X, q.Y, q.Z 219 return p 220 } 221 222 // Equal tests if two points in Jacobian coordinates are equal. 223 func (p *G2Jac) Equal(q *G2Jac) bool { 224 // If one point is infinity, the other must also be infinity. 225 if p.Z.IsZero() { 226 return q.Z.IsZero() 227 } 228 // If the other point is infinity, return false since we can't 229 // the following checks would be incorrect. 230 if q.Z.IsZero() { 231 return false 232 } 233 234 var pZSquare, aZSquare fptower.E4 235 pZSquare.Square(&p.Z) 236 aZSquare.Square(&q.Z) 237 238 var lhs, rhs fptower.E4 239 lhs.Mul(&p.X, &aZSquare) 240 rhs.Mul(&q.X, &pZSquare) 241 if !lhs.Equal(&rhs) { 242 return false 243 } 244 lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) 245 rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) 246 247 return lhs.Equal(&rhs) 248 } 249 250 // Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). 251 func (p *G2Jac) Neg(q *G2Jac) *G2Jac { 252 *p = *q 253 p.Y.Neg(&q.Y) 254 return p 255 } 256 257 // AddAssign sets p to p+a in Jacobian coordinates. 258 // 259 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl 260 func (p *G2Jac) AddAssign(q *G2Jac) *G2Jac { 261 262 // p is infinity, return q 263 if p.Z.IsZero() { 264 p.Set(q) 265 return p 266 } 267 268 // q is infinity, return p 269 if q.Z.IsZero() { 270 return p 271 } 272 273 var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fptower.E4 274 Z1Z1.Square(&q.Z) 275 Z2Z2.Square(&p.Z) 276 U1.Mul(&q.X, &Z2Z2) 277 U2.Mul(&p.X, &Z1Z1) 278 S1.Mul(&q.Y, &p.Z). 279 Mul(&S1, &Z2Z2) 280 S2.Mul(&p.Y, &q.Z). 281 Mul(&S2, &Z1Z1) 282 283 // if p == q, we double instead 284 if U1.Equal(&U2) && S1.Equal(&S2) { 285 return p.DoubleAssign() 286 } 287 288 H.Sub(&U2, &U1) 289 I.Double(&H). 290 Square(&I) 291 J.Mul(&H, &I) 292 r.Sub(&S2, &S1).Double(&r) 293 V.Mul(&U1, &I) 294 p.X.Square(&r). 295 Sub(&p.X, &J). 296 Sub(&p.X, &V). 297 Sub(&p.X, &V) 298 p.Y.Sub(&V, &p.X). 299 Mul(&p.Y, &r) 300 S1.Mul(&S1, &J).Double(&S1) 301 p.Y.Sub(&p.Y, &S1) 302 p.Z.Add(&p.Z, &q.Z) 303 p.Z.Square(&p.Z). 304 Sub(&p.Z, &Z1Z1). 305 Sub(&p.Z, &Z2Z2). 306 Mul(&p.Z, &H) 307 308 return p 309 } 310 311 // SubAssign sets p to p-a in Jacobian coordinates. 312 // It uses a similar approach to AddAssign, but negates the point a before adding. 313 func (p *G2Jac) SubAssign(q *G2Jac) *G2Jac { 314 var tmp G2Jac 315 tmp.Set(q) 316 tmp.Y.Neg(&tmp.Y) 317 p.AddAssign(&tmp) 318 return p 319 } 320 321 // Double sets p to [2]q in Jacobian coordinates. 322 // 323 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 324 func (p *G2Jac) DoubleMixed(a *G2Affine) *G2Jac { 325 var XX, YY, YYYY, S, M, T fptower.E4 326 XX.Square(&a.X) 327 YY.Square(&a.Y) 328 YYYY.Square(&YY) 329 S.Add(&a.X, &YY). 330 Square(&S). 331 Sub(&S, &XX). 332 Sub(&S, &YYYY). 333 Double(&S) 334 M.Double(&XX). 335 Add(&M, &XX) // -> + A, but A=0 here 336 T.Square(&M). 337 Sub(&T, &S). 338 Sub(&T, &S) 339 p.X.Set(&T) 340 p.Y.Sub(&S, &T). 341 Mul(&p.Y, &M) 342 YYYY.Double(&YYYY). 343 Double(&YYYY). 344 Double(&YYYY) 345 p.Y.Sub(&p.Y, &YYYY) 346 p.Z.Double(&a.Y) 347 348 return p 349 } 350 351 // AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. 352 // 353 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl 354 func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { 355 356 //if a is infinity return p 357 if a.IsInfinity() { 358 return p 359 } 360 // p is infinity, return a 361 if p.Z.IsZero() { 362 p.X = a.X 363 p.Y = a.Y 364 p.Z.SetOne() 365 return p 366 } 367 368 var Z1Z1, U2, S2, H, HH, I, J, r, V fptower.E4 369 Z1Z1.Square(&p.Z) 370 U2.Mul(&a.X, &Z1Z1) 371 S2.Mul(&a.Y, &p.Z). 372 Mul(&S2, &Z1Z1) 373 374 // if p == a, we double instead 375 if U2.Equal(&p.X) && S2.Equal(&p.Y) { 376 return p.DoubleMixed(a) 377 } 378 379 H.Sub(&U2, &p.X) 380 HH.Square(&H) 381 I.Double(&HH).Double(&I) 382 J.Mul(&H, &I) 383 r.Sub(&S2, &p.Y).Double(&r) 384 V.Mul(&p.X, &I) 385 p.X.Square(&r). 386 Sub(&p.X, &J). 387 Sub(&p.X, &V). 388 Sub(&p.X, &V) 389 J.Mul(&J, &p.Y).Double(&J) 390 p.Y.Sub(&V, &p.X). 391 Mul(&p.Y, &r) 392 p.Y.Sub(&p.Y, &J) 393 p.Z.Add(&p.Z, &H) 394 p.Z.Square(&p.Z). 395 Sub(&p.Z, &Z1Z1). 396 Sub(&p.Z, &HH) 397 398 return p 399 } 400 401 // Double sets p to [2]q in Jacobian coordinates. 402 // 403 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 404 func (p *G2Jac) Double(q *G2Jac) *G2Jac { 405 p.Set(q) 406 p.DoubleAssign() 407 return p 408 } 409 410 // DoubleAssign doubles p in Jacobian coordinates. 411 // 412 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 413 func (p *G2Jac) DoubleAssign() *G2Jac { 414 415 var XX, YY, YYYY, ZZ, S, M, T fptower.E4 416 417 XX.Square(&p.X) 418 YY.Square(&p.Y) 419 YYYY.Square(&YY) 420 ZZ.Square(&p.Z) 421 S.Add(&p.X, &YY) 422 S.Square(&S). 423 Sub(&S, &XX). 424 Sub(&S, &YYYY). 425 Double(&S) 426 M.Double(&XX).Add(&M, &XX) 427 p.Z.Add(&p.Z, &p.Y). 428 Square(&p.Z). 429 Sub(&p.Z, &YY). 430 Sub(&p.Z, &ZZ) 431 T.Square(&M) 432 p.X = T 433 T.Double(&S) 434 p.X.Sub(&p.X, &T) 435 p.Y.Sub(&S, &p.X). 436 Mul(&p.Y, &M) 437 YYYY.Double(&YYYY).Double(&YYYY).Double(&YYYY) 438 p.Y.Sub(&p.Y, &YYYY) 439 440 return p 441 } 442 443 // ScalarMultiplication computes and returns p = [s]a 444 // where p and a are Jacobian points. 445 // using the GLV technique. 446 // see https://www.iacr.org/archive/crypto2001/21390189.pdf 447 func (p *G2Jac) ScalarMultiplication(q *G2Jac, s *big.Int) *G2Jac { 448 return p.mulGLV(q, s) 449 } 450 451 // ScalarMultiplicationBase computes and returns p = [s]g 452 // where g is the prime subgroup generator. 453 func (p *G2Jac) ScalarMultiplicationBase(s *big.Int) *G2Jac { 454 return p.mulGLV(&g2Gen, s) 455 456 } 457 458 // String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. 459 func (p *G2Jac) String() string { 460 _p := G2Affine{} 461 _p.FromJacobian(p) 462 return _p.String() 463 } 464 465 // FromAffine converts a point a from affine to Jacobian coordinates. 466 func (p *G2Jac) FromAffine(a *G2Affine) *G2Jac { 467 if a.IsInfinity() { 468 p.Z.SetZero() 469 p.X.SetOne() 470 p.Y.SetOne() 471 return p 472 } 473 p.Z.SetOne() 474 p.X.Set(&a.X) 475 p.Y.Set(&a.Y) 476 return p 477 } 478 479 // IsOnCurve returns true if the Jacobian point p in on the curve. 480 func (p *G2Jac) IsOnCurve() bool { 481 var left, right, tmp, ZZ fptower.E4 482 left.Square(&p.Y) 483 right.Square(&p.X).Mul(&right, &p.X) 484 ZZ.Square(&p.Z) 485 tmp.Square(&ZZ).Mul(&tmp, &ZZ) 486 tmp.MulBybTwistCurveCoeff(&tmp) 487 right.Add(&right, &tmp) 488 return left.Equal(&right) 489 } 490 491 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 492 // https://eprint.iacr.org/2021/1130.pdf, sec.4 493 // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2 494 // ψ(p) = [x₀]P 495 func (p *G2Jac) IsInSubGroup() bool { 496 var res, tmp G2Jac 497 tmp.psi(p) 498 res.ScalarMultiplication(p, &xGen). 499 SubAssign(&tmp) 500 501 return res.IsOnCurve() && res.Z.IsZero() 502 503 } 504 505 // mulWindowed computes the 2-bits windowed double-and-add scalar 506 // multiplication p=[s]q in Jacobian coordinates. 507 func (p *G2Jac) mulWindowed(q *G2Jac, s *big.Int) *G2Jac { 508 509 var res G2Jac 510 var ops [3]G2Jac 511 512 ops[0].Set(q) 513 if s.Sign() == -1 { 514 ops[0].Neg(&ops[0]) 515 } 516 res.Set(&g2Infinity) 517 ops[1].Double(&ops[0]) 518 ops[2].Set(&ops[0]).AddAssign(&ops[1]) 519 520 b := s.Bytes() 521 for i := range b { 522 w := b[i] 523 mask := byte(0xc0) 524 for j := 0; j < 4; j++ { 525 res.DoubleAssign().DoubleAssign() 526 c := (w & mask) >> (6 - 2*j) 527 if c != 0 { 528 res.AddAssign(&ops[c-1]) 529 } 530 mask = mask >> 2 531 } 532 } 533 p.Set(&res) 534 535 return p 536 537 } 538 539 // psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map. 540 func (p *G2Jac) psi(q *G2Jac) *G2Jac { 541 p.Set(q) 542 p.X.Frobenius(&p.X).Mul(&p.X, &endo.u) 543 p.Y.Frobenius(&p.Y).Mul(&p.Y, &endo.v) 544 p.Z.Frobenius(&p.Z) 545 return p 546 } 547 548 // phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), 549 // where w is a third root of unity. 550 func (p *G2Jac) phi(q *G2Jac) *G2Jac { 551 p.Set(q) 552 p.X.MulByElement(&p.X, &thirdRootOneG2) 553 return p 554 } 555 556 // mulGLV computes the scalar multiplication using a windowed-GLV method 557 // 558 // see https://www.iacr.org/archive/crypto2001/21390189.pdf 559 func (p *G2Jac) mulGLV(q *G2Jac, s *big.Int) *G2Jac { 560 561 var table [15]G2Jac 562 var res G2Jac 563 var k1, k2 fr.Element 564 565 res.Set(&g2Infinity) 566 567 // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q 568 table[0].Set(q) 569 table[3].phi(q) 570 571 // split the scalar, modifies ±q, ϕ(q) accordingly 572 k := ecc.SplitScalar(s, &glvBasis) 573 574 if k[0].Sign() == -1 { 575 k[0].Neg(&k[0]) 576 table[0].Neg(&table[0]) 577 } 578 if k[1].Sign() == -1 { 579 k[1].Neg(&k[1]) 580 table[3].Neg(&table[3]) 581 } 582 583 // precompute table (2 bits sliding window) 584 // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 585 table[1].Double(&table[0]) 586 table[2].Set(&table[1]).AddAssign(&table[0]) 587 table[4].Set(&table[3]).AddAssign(&table[0]) 588 table[5].Set(&table[3]).AddAssign(&table[1]) 589 table[6].Set(&table[3]).AddAssign(&table[2]) 590 table[7].Double(&table[3]) 591 table[8].Set(&table[7]).AddAssign(&table[0]) 592 table[9].Set(&table[7]).AddAssign(&table[1]) 593 table[10].Set(&table[7]).AddAssign(&table[2]) 594 table[11].Set(&table[7]).AddAssign(&table[3]) 595 table[12].Set(&table[11]).AddAssign(&table[0]) 596 table[13].Set(&table[11]).AddAssign(&table[1]) 597 table[14].Set(&table[11]).AddAssign(&table[2]) 598 599 // bounds on the lattice base vectors guarantee that k1, k2 are len(r)/2 or len(r)/2+1 bits long max 600 // this is because we use a probabilistic scalar decomposition that replaces a division by a right-shift 601 k1 = k1.SetBigInt(&k[0]).Bits() 602 k2 = k2.SetBigInt(&k[1]).Bits() 603 604 // we don't target constant-timeness so we check first if we increase the bounds or not 605 maxBit := k1.BitLen() 606 if k2.BitLen() > maxBit { 607 maxBit = k2.BitLen() 608 } 609 hiWordIndex := (maxBit - 1) / 64 610 611 // loop starts from len(k1)/2 or len(k1)/2+1 due to the bounds 612 for i := hiWordIndex; i >= 0; i-- { 613 mask := uint64(3) << 62 614 for j := 0; j < 32; j++ { 615 res.Double(&res).Double(&res) 616 b1 := (k1[i] & mask) >> (62 - 2*j) 617 b2 := (k2[i] & mask) >> (62 - 2*j) 618 if b1|b2 != 0 { 619 s := (b2<<2 | b1) 620 res.AddAssign(&table[s-1]) 621 } 622 mask = mask >> 2 623 } 624 } 625 626 p.Set(&res) 627 return p 628 } 629 630 // ClearCofactor maps a point in curve to r-torsion 631 func (p *G2Affine) ClearCofactor(a *G2Affine) *G2Affine { 632 var _p G2Jac 633 _p.FromAffine(a) 634 _p.ClearCofactor(&_p) 635 p.FromJacobian(&_p) 636 return p 637 } 638 639 // ClearCofactor maps a point in curve to r-torsion 640 func (p *G2Jac) ClearCofactor(q *G2Jac) *G2Jac { 641 // https://eprint.iacr.org/2017/419.pdf, section 4.2 642 // multiply by (3x⁴-3)*cofacor 643 644 var xg, xxg, xxxg, xxxxg, res, t G2Jac 645 xg.ScalarMultiplication(q, &xGen).SubAssign(q) 646 xxg.ScalarMultiplication(&xg, &xGen) 647 xxxg.ScalarMultiplication(&xxg, &xGen) 648 xxxxg.ScalarMultiplication(&xxxg, &xGen) 649 650 res.Set(&xxxxg). 651 SubAssign(q) 652 653 t.Set(&xxxg). 654 psi(&t). 655 AddAssign(&res) 656 657 res.Set(&xxg). 658 psi(&res). 659 psi(&res). 660 AddAssign(&t) 661 662 t.Set(&xg). 663 psi(&t). 664 psi(&t). 665 psi(&t). 666 AddAssign(&res) 667 668 res.Double(q). 669 psi(&res). 670 psi(&res). 671 psi(&res). 672 psi(&res). 673 AddAssign(&t) 674 675 p.Set(&res) 676 677 return p 678 679 } 680 681 // ------------------------------------------------------------------------------------------------- 682 // extended Jacobian coordinates 683 684 // Set sets p to a in extended Jacobian coordinates. 685 func (p *g2JacExtended) Set(q *g2JacExtended) *g2JacExtended { 686 p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ 687 return p 688 } 689 690 // setInfinity sets p to the infinity point (1,1,0,0). 691 func (p *g2JacExtended) setInfinity() *g2JacExtended { 692 p.X.SetOne() 693 p.Y.SetOne() 694 p.ZZ = fptower.E4{} 695 p.ZZZ = fptower.E4{} 696 return p 697 } 698 699 // IsInfinity checks if the p is infinity, i.e. p.ZZ=0. 700 func (p *g2JacExtended) IsInfinity() bool { 701 return p.ZZ.IsZero() 702 } 703 704 // fromJacExtended converts an extended Jacobian point to an affine point. 705 func (p *G2Affine) fromJacExtended(q *g2JacExtended) *G2Affine { 706 if q.ZZ.IsZero() { 707 p.X = fptower.E4{} 708 p.Y = fptower.E4{} 709 return p 710 } 711 p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) 712 p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) 713 return p 714 } 715 716 // fromJacExtended converts an extended Jacobian point to a Jacobian point. 717 func (p *G2Jac) fromJacExtended(q *g2JacExtended) *G2Jac { 718 if q.ZZ.IsZero() { 719 p.Set(&g2Infinity) 720 return p 721 } 722 p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) 723 p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) 724 p.Z.Set(&q.ZZZ) 725 return p 726 } 727 728 // unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. 729 func (p *G2Jac) unsafeFromJacExtended(q *g2JacExtended) *G2Jac { 730 p.X.Square(&q.ZZ).Mul(&p.X, &q.X) 731 p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) 732 p.Z = q.ZZZ 733 return p 734 } 735 736 // add sets p to p+q in extended Jacobian coordinates. 737 // 738 // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s 739 func (p *g2JacExtended) add(q *g2JacExtended) *g2JacExtended { 740 //if q is infinity return p 741 if q.ZZ.IsZero() { 742 return p 743 } 744 // p is infinity, return q 745 if p.ZZ.IsZero() { 746 p.Set(q) 747 return p 748 } 749 750 var A, B, U1, U2, S1, S2 fptower.E4 751 752 // p2: q, p1: p 753 U2.Mul(&q.X, &p.ZZ) 754 U1.Mul(&p.X, &q.ZZ) 755 A.Sub(&U2, &U1) 756 S2.Mul(&q.Y, &p.ZZZ) 757 S1.Mul(&p.Y, &q.ZZZ) 758 B.Sub(&S2, &S1) 759 760 if A.IsZero() { 761 if B.IsZero() { 762 return p.double(q) 763 764 } 765 p.ZZ = fptower.E4{} 766 p.ZZZ = fptower.E4{} 767 return p 768 } 769 770 var P, R, PP, PPP, Q, V fptower.E4 771 P.Sub(&U2, &U1) 772 R.Sub(&S2, &S1) 773 PP.Square(&P) 774 PPP.Mul(&P, &PP) 775 Q.Mul(&U1, &PP) 776 V.Mul(&S1, &PPP) 777 778 p.X.Square(&R). 779 Sub(&p.X, &PPP). 780 Sub(&p.X, &Q). 781 Sub(&p.X, &Q) 782 p.Y.Sub(&Q, &p.X). 783 Mul(&p.Y, &R). 784 Sub(&p.Y, &V) 785 p.ZZ.Mul(&p.ZZ, &q.ZZ). 786 Mul(&p.ZZ, &PP) 787 p.ZZZ.Mul(&p.ZZZ, &q.ZZZ). 788 Mul(&p.ZZZ, &PPP) 789 790 return p 791 } 792 793 // double sets p to [2]q in Jacobian extended coordinates. 794 // 795 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 796 // N.B.: since we consider any point on Z=0 as the point at infinity 797 // this doubling formula works for infinity points as well. 798 func (p *g2JacExtended) double(q *g2JacExtended) *g2JacExtended { 799 var U, V, W, S, XX, M fptower.E4 800 801 U.Double(&q.Y) 802 V.Square(&U) 803 W.Mul(&U, &V) 804 S.Mul(&q.X, &V) 805 XX.Square(&q.X) 806 M.Double(&XX). 807 Add(&M, &XX) // -> + A, but A=0 here 808 U.Mul(&W, &q.Y) 809 810 p.X.Square(&M). 811 Sub(&p.X, &S). 812 Sub(&p.X, &S) 813 p.Y.Sub(&S, &p.X). 814 Mul(&p.Y, &M). 815 Sub(&p.Y, &U) 816 p.ZZ.Mul(&V, &q.ZZ) 817 p.ZZZ.Mul(&W, &q.ZZZ) 818 819 return p 820 } 821 822 // addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. 823 // 824 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s 825 func (p *g2JacExtended) addMixed(a *G2Affine) *g2JacExtended { 826 827 //if a is infinity return p 828 if a.IsInfinity() { 829 return p 830 } 831 // p is infinity, return a 832 if p.ZZ.IsZero() { 833 p.X = a.X 834 p.Y = a.Y 835 p.ZZ.SetOne() 836 p.ZZZ.SetOne() 837 return p 838 } 839 840 var P, R fptower.E4 841 842 // p2: a, p1: p 843 P.Mul(&a.X, &p.ZZ) 844 P.Sub(&P, &p.X) 845 846 R.Mul(&a.Y, &p.ZZZ) 847 R.Sub(&R, &p.Y) 848 849 if P.IsZero() { 850 if R.IsZero() { 851 return p.doubleMixed(a) 852 853 } 854 p.ZZ = fptower.E4{} 855 p.ZZZ = fptower.E4{} 856 return p 857 } 858 859 var PP, PPP, Q, Q2, RR, X3, Y3 fptower.E4 860 861 PP.Square(&P) 862 PPP.Mul(&P, &PP) 863 Q.Mul(&p.X, &PP) 864 RR.Square(&R) 865 X3.Sub(&RR, &PPP) 866 Q2.Double(&Q) 867 p.X.Sub(&X3, &Q2) 868 Y3.Sub(&Q, &p.X).Mul(&Y3, &R) 869 R.Mul(&p.Y, &PPP) 870 p.Y.Sub(&Y3, &R) 871 p.ZZ.Mul(&p.ZZ, &PP) 872 p.ZZZ.Mul(&p.ZZZ, &PPP) 873 874 return p 875 876 } 877 878 // subMixed works the same as addMixed, but negates a.Y. 879 // 880 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s 881 func (p *g2JacExtended) subMixed(a *G2Affine) *g2JacExtended { 882 883 //if a is infinity return p 884 if a.IsInfinity() { 885 return p 886 } 887 // p is infinity, return a 888 if p.ZZ.IsZero() { 889 p.X = a.X 890 p.Y.Neg(&a.Y) 891 p.ZZ.SetOne() 892 p.ZZZ.SetOne() 893 return p 894 } 895 896 var P, R fptower.E4 897 898 // p2: a, p1: p 899 P.Mul(&a.X, &p.ZZ) 900 P.Sub(&P, &p.X) 901 902 R.Mul(&a.Y, &p.ZZZ) 903 R.Neg(&R) 904 R.Sub(&R, &p.Y) 905 906 if P.IsZero() { 907 if R.IsZero() { 908 return p.doubleNegMixed(a) 909 910 } 911 p.ZZ = fptower.E4{} 912 p.ZZZ = fptower.E4{} 913 return p 914 } 915 916 var PP, PPP, Q, Q2, RR, X3, Y3 fptower.E4 917 918 PP.Square(&P) 919 PPP.Mul(&P, &PP) 920 Q.Mul(&p.X, &PP) 921 RR.Square(&R) 922 X3.Sub(&RR, &PPP) 923 Q2.Double(&Q) 924 p.X.Sub(&X3, &Q2) 925 Y3.Sub(&Q, &p.X).Mul(&Y3, &R) 926 R.Mul(&p.Y, &PPP) 927 p.Y.Sub(&Y3, &R) 928 p.ZZ.Mul(&p.ZZ, &PP) 929 p.ZZZ.Mul(&p.ZZZ, &PPP) 930 931 return p 932 933 } 934 935 // doubleNegMixed works the same as double, but negates q.Y. 936 func (p *g2JacExtended) doubleNegMixed(a *G2Affine) *g2JacExtended { 937 938 var U, V, W, S, XX, M, S2, L fptower.E4 939 940 U.Double(&a.Y) 941 U.Neg(&U) 942 V.Square(&U) 943 W.Mul(&U, &V) 944 S.Mul(&a.X, &V) 945 XX.Square(&a.X) 946 M.Double(&XX). 947 Add(&M, &XX) // -> + A, but A=0 here 948 S2.Double(&S) 949 L.Mul(&W, &a.Y) 950 951 p.X.Square(&M). 952 Sub(&p.X, &S2) 953 p.Y.Sub(&S, &p.X). 954 Mul(&p.Y, &M). 955 Add(&p.Y, &L) 956 p.ZZ.Set(&V) 957 p.ZZZ.Set(&W) 958 959 return p 960 } 961 962 // doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. 963 // 964 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 965 func (p *g2JacExtended) doubleMixed(a *G2Affine) *g2JacExtended { 966 967 var U, V, W, S, XX, M, S2, L fptower.E4 968 969 U.Double(&a.Y) 970 V.Square(&U) 971 W.Mul(&U, &V) 972 S.Mul(&a.X, &V) 973 XX.Square(&a.X) 974 M.Double(&XX). 975 Add(&M, &XX) // -> + A, but A=0 here 976 S2.Double(&S) 977 L.Mul(&W, &a.Y) 978 979 p.X.Square(&M). 980 Sub(&p.X, &S2) 981 p.Y.Sub(&S, &p.X). 982 Mul(&p.Y, &M). 983 Sub(&p.Y, &L) 984 p.ZZ.Set(&V) 985 p.ZZZ.Set(&W) 986 987 return p 988 } 989 990 // ------------------------------------------------------------------------------------------------- 991 // Homogenous projective coordinates 992 993 // Set sets p to a in projective coordinates. 994 func (p *g2Proj) Set(q *g2Proj) *g2Proj { 995 p.x, p.y, p.z = q.x, q.y, q.z 996 return p 997 } 998 999 // Neg sets p to the projective negative point -q = (q.X, -q.Y). 1000 func (p *g2Proj) Neg(q *g2Proj) *g2Proj { 1001 *p = *q 1002 p.y.Neg(&q.y) 1003 return p 1004 } 1005 1006 // FromAffine converts q in affine to p in projective coordinates. 1007 func (p *g2Proj) FromAffine(a *G2Affine) *g2Proj { 1008 if a.X.IsZero() && a.Y.IsZero() { 1009 p.z.SetZero() 1010 p.x.SetOne() 1011 p.y.SetOne() 1012 return p 1013 } 1014 p.z.SetOne() 1015 p.x.Set(&a.X) 1016 p.y.Set(&a.Y) 1017 return p 1018 } 1019 1020 // BatchScalarMultiplicationG2 multiplies the same base by all scalars 1021 // and return resulting points in affine coordinates 1022 // uses a simple windowed-NAF-like multiplication algorithm. 1023 func BatchScalarMultiplicationG2(base *G2Affine, scalars []fr.Element) []G2Affine { 1024 // approximate cost in group ops is 1025 // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) 1026 1027 nbPoints := uint64(len(scalars)) 1028 min := ^uint64(0) 1029 bestC := 0 1030 for c := 2; c <= 16; c++ { 1031 cost := uint64(1 << (c - 1)) // pre compute the table 1032 nbChunks := computeNbChunks(uint64(c)) 1033 cost += nbPoints * (uint64(c) + 1) * nbChunks // doublings + point add 1034 if cost < min { 1035 min = cost 1036 bestC = c 1037 } 1038 } 1039 c := uint64(bestC) // window size 1040 nbChunks := int(computeNbChunks(c)) 1041 1042 // last window may be slightly larger than c; in which case we need to compute one 1043 // extra element in the baseTable 1044 maxC := lastC(c) 1045 if c > maxC { 1046 maxC = c 1047 } 1048 1049 // precompute all powers of base for our window 1050 // note here that if performance is critical, we can implement as in the msmX methods 1051 // this allocation to be on the stack 1052 baseTable := make([]G2Jac, (1 << (maxC - 1))) 1053 baseTable[0].FromAffine(base) 1054 for i := 1; i < len(baseTable); i++ { 1055 baseTable[i] = baseTable[i-1] 1056 baseTable[i].AddMixed(base) 1057 } 1058 toReturn := make([]G2Affine, len(scalars)) 1059 1060 // partition the scalars into digits 1061 digits, _ := partitionScalars(scalars, c, runtime.NumCPU()) 1062 1063 // for each digit, take value in the base table, double it c time, voilà. 1064 parallel.Execute(len(scalars), func(start, end int) { 1065 var p G2Jac 1066 for i := start; i < end; i++ { 1067 p.Set(&g2Infinity) 1068 for chunk := nbChunks - 1; chunk >= 0; chunk-- { 1069 if chunk != nbChunks-1 { 1070 for j := uint64(0); j < c; j++ { 1071 p.DoubleAssign() 1072 } 1073 } 1074 offset := chunk * len(scalars) 1075 digit := digits[i+offset] 1076 1077 if digit == 0 { 1078 continue 1079 } 1080 1081 // if msbWindow bit is set, we need to subtract 1082 if digit&1 == 0 { 1083 // add 1084 p.AddAssign(&baseTable[(digit>>1)-1]) 1085 } else { 1086 // sub 1087 t := baseTable[digit>>1] 1088 t.Neg(&t) 1089 p.AddAssign(&t) 1090 } 1091 } 1092 1093 // set our result point 1094 toReturn[i].FromJacobian(&p) 1095 1096 } 1097 }) 1098 return toReturn 1099 } 1100 1101 // batchAddG2Affine adds affine points using the Montgomery batch inversion trick. 1102 // Special cases (doubling, infinity) must be filtered out before this call. 1103 func batchAddG2Affine[TP pG2Affine, TPP ppG2Affine, TC cG2Affine](R *TPP, P *TP, batchSize int) { 1104 var lambda, lambdain TC 1105 1106 // add part 1107 for j := 0; j < batchSize; j++ { 1108 lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) 1109 } 1110 1111 // invert denominator using montgomery batch invert technique 1112 { 1113 var accumulator fptower.E4 1114 lambda[0].SetOne() 1115 accumulator.Set(&lambdain[0]) 1116 1117 for i := 1; i < batchSize; i++ { 1118 lambda[i] = accumulator 1119 accumulator.Mul(&accumulator, &lambdain[i]) 1120 } 1121 1122 accumulator.Inverse(&accumulator) 1123 1124 for i := batchSize - 1; i > 0; i-- { 1125 lambda[i].Mul(&lambda[i], &accumulator) 1126 accumulator.Mul(&accumulator, &lambdain[i]) 1127 } 1128 lambda[0].Set(&accumulator) 1129 } 1130 1131 var d fptower.E4 1132 var rr G2Affine 1133 1134 // add part 1135 for j := 0; j < batchSize; j++ { 1136 // computa lambda 1137 d.Sub(&(*P)[j].Y, &(*R)[j].Y) 1138 lambda[j].Mul(&lambda[j], &d) 1139 1140 // compute X, Y 1141 rr.X.Square(&lambda[j]) 1142 rr.X.Sub(&rr.X, &(*R)[j].X) 1143 rr.X.Sub(&rr.X, &(*P)[j].X) 1144 d.Sub(&(*R)[j].X, &rr.X) 1145 rr.Y.Mul(&lambda[j], &d) 1146 rr.Y.Sub(&rr.Y, &(*R)[j].Y) 1147 (*R)[j].Set(&rr) 1148 } 1149 } 1150 1151 // RandomOnG2 produces a random point in G2 1152 // using standard map-to-curve methods, which means the relative discrete log 1153 // of the generated point with respect to the canonical generator is not known. 1154 func RandomOnG2() (G2Affine, error) { 1155 if gBytes, err := randomFrSizedBytes(); err != nil { 1156 return G2Affine{}, err 1157 } else { 1158 return HashToG2(gBytes, []byte("random on g2")) 1159 } 1160 } 1161 1162 func randomFrSizedBytes() ([]byte, error) { 1163 res := make([]byte, fr.Bytes) 1164 _, err := rand.Read(res) 1165 return res, err 1166 }