github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/FP256BN/ECP2.go (about) 1 /* 2 Licensed to the Apache Software Foundation (ASF) under one 3 or more contributor license agreements. See the NOTICE file 4 distributed with this work for additional information 5 regarding copyright ownership. The ASF licenses this file 6 to you under the Apache License, Version 2.0 (the 7 "License"); you may not use this file except in compliance 8 with the License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, 13 software distributed under the License is distributed on an 14 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 KIND, either express or implied. See the License for the 16 specific language governing permissions and limitations 17 under the License. 18 */ 19 20 /* MiotCL Weierstrass elliptic curve functions over FP2 */ 21 22 package FP256BN 23 24 25 26 type ECP2 struct { 27 x *FP2 28 y *FP2 29 z *FP2 30 // INF bool 31 } 32 33 func NewECP2() *ECP2 { 34 E:=new(ECP2) 35 E.x=NewFP2int(0) 36 E.y=NewFP2int(1) 37 E.z=NewFP2int(0) 38 // E.INF=true 39 return E 40 } 41 42 /* Test this=O? */ 43 func (E *ECP2) Is_infinity() bool { 44 // if E.INF {return true} 45 E.x.reduce(); E.y.reduce(); E.z.reduce() 46 return E.x.iszilch() && E.z.iszilch() 47 } 48 /* copy this=P */ 49 func (E *ECP2) Copy(P *ECP2) { 50 E.x.copy(P.x) 51 E.y.copy(P.y) 52 E.z.copy(P.z) 53 // E.INF=P.INF 54 } 55 /* set this=O */ 56 func (E *ECP2) inf() { 57 // E.INF=true 58 E.x.zero() 59 E.y.one() 60 E.z.zero() 61 } 62 63 /* set this=-this */ 64 func (E *ECP2) neg() { 65 // if E.Is_infinity() {return} 66 E.y.norm(); E.y.neg(); E.y.norm() 67 } 68 69 /* Conditional move of Q to P dependant on d */ 70 func (E *ECP2) cmove(Q *ECP2,d int) { 71 E.x.cmove(Q.x,d) 72 E.y.cmove(Q.y,d) 73 E.z.cmove(Q.z,d) 74 /* 75 var bd bool 76 if (d==0) { 77 bd=false 78 } else {bd=true} 79 E.INF=(E.INF!=(E.INF!=Q.INF)&&bd) 80 */ 81 } 82 83 /* Constant time select from pre-computed table */ 84 func (E *ECP2) selector(W []*ECP2,b int32) { 85 MP:=NewECP2() 86 m:=b>>31 87 babs:=(b^m)-m 88 89 babs=(babs-1)/2 90 91 E.cmove(W[0],teq(babs,0)) // conditional move 92 E.cmove(W[1],teq(babs,1)) 93 E.cmove(W[2],teq(babs,2)) 94 E.cmove(W[3],teq(babs,3)) 95 E.cmove(W[4],teq(babs,4)) 96 E.cmove(W[5],teq(babs,5)) 97 E.cmove(W[6],teq(babs,6)) 98 E.cmove(W[7],teq(babs,7)) 99 100 MP.Copy(E) 101 MP.neg() 102 E.cmove(MP,int(m&1)) 103 } 104 105 /* Test if P == Q */ 106 func (E *ECP2) Equals(Q *ECP2) bool { 107 // if E.Is_infinity() && Q.Is_infinity() {return true} 108 // if E.Is_infinity() || Q.Is_infinity() {return false} 109 110 a:=NewFP2copy(E.x) 111 b:=NewFP2copy(Q.x) 112 a.mul(Q.z); b.mul(E.z) 113 114 if !a.Equals(b) {return false} 115 a.copy(E.y); b.copy(Q.y) 116 a.mul(Q.z); b.mul(E.z); 117 if !a.Equals(b) {return false} 118 119 return true 120 } 121 122 /* set to Affine - (x,y,z) to (x,y) */ 123 func (E *ECP2) Affine() { 124 if E.Is_infinity() {return} 125 one:=NewFP2int(1) 126 if E.z.Equals(one) {E.x.reduce(); E.y.reduce(); return} 127 E.z.inverse() 128 129 E.x.mul(E.z); E.x.reduce() 130 E.y.mul(E.z); E.y.reduce() 131 E.z.copy(one) 132 } 133 134 /* extract affine x as FP2 */ 135 func (E *ECP2) GetX() *FP2 { 136 W:=NewECP2(); W.Copy(E) 137 W.Affine() 138 return W.x 139 } 140 /* extract affine y as FP2 */ 141 func (E *ECP2) GetY() *FP2 { 142 W:=NewECP2(); W.Copy(E) 143 W.Affine() 144 return W.y; 145 } 146 /* extract projective x */ 147 func (E *ECP2) getx() *FP2 { 148 return E.x 149 } 150 /* extract projective y */ 151 func (E *ECP2) gety() *FP2 { 152 return E.y 153 } 154 /* extract projective z */ 155 func (E *ECP2) getz() *FP2 { 156 return E.z 157 } 158 159 /* convert to byte array */ 160 func (E *ECP2) ToBytes(b []byte) { 161 var t [int(MODBYTES)]byte 162 MB:=int(MODBYTES) 163 164 W:=NewECP2(); W.Copy(E); 165 W.Affine() 166 167 W.x.GetA().ToBytes(t[:]) 168 for i:=0;i<MB;i++ { b[i]=t[i]} 169 W.x.GetB().ToBytes(t[:]) 170 for i:=0;i<MB;i++ { b[i+MB]=t[i]} 171 172 W.y.GetA().ToBytes(t[:]) 173 for i:=0;i<MB;i++ {b[i+2*MB]=t[i]} 174 W.y.GetB().ToBytes(t[:]) 175 for i:=0;i<MB;i++ {b[i+3*MB]=t[i]} 176 } 177 178 /* convert from byte array to point */ 179 func ECP2_fromBytes(b []byte) *ECP2 { 180 var t [int(MODBYTES)]byte 181 MB:=int(MODBYTES) 182 183 for i:=0;i<MB;i++ {t[i]=b[i]} 184 ra:=FromBytes(t[:]) 185 for i:=0;i<MB;i++ {t[i]=b[i+MB]} 186 rb:=FromBytes(t[:]) 187 rx:=NewFP2bigs(ra,rb) 188 189 for i:=0;i<MB;i++ {t[i]=b[i+2*MB]} 190 ra=FromBytes(t[:]) 191 for i:=0;i<MB;i++ {t[i]=b[i+3*MB]} 192 rb=FromBytes(t[:]) 193 ry:=NewFP2bigs(ra,rb) 194 195 return NewECP2fp2s(rx,ry) 196 } 197 198 /* convert this to hex string */ 199 func (E *ECP2) toString() string { 200 W:=NewECP2(); W.Copy(E); 201 W.Affine() 202 if W.Is_infinity() {return "infinity"} 203 return "("+W.x.toString()+","+W.y.toString()+")" 204 } 205 206 /* Calculate RHS of twisted curve equation x^3+B/i */ 207 func RHS2(x *FP2) *FP2 { 208 x.norm() 209 r:=NewFP2copy(x) 210 r.sqr() 211 b:=NewFP2big(NewBIGints(CURVE_B)) 212 213 if SEXTIC_TWIST == D_TYPE { 214 b.div_ip() 215 } 216 if SEXTIC_TWIST == M_TYPE { 217 b.norm() 218 b.mul_ip() 219 b.norm() 220 } 221 r.mul(x) 222 r.add(b) 223 224 r.reduce() 225 return r 226 } 227 228 /* construct this from (x,y) - but set to O if not on curve */ 229 func NewECP2fp2s(ix *FP2,iy *FP2) *ECP2 { 230 E:=new(ECP2) 231 E.x=NewFP2copy(ix) 232 E.y=NewFP2copy(iy) 233 E.z=NewFP2int(1) 234 rhs:=RHS2(E.x) 235 y2:=NewFP2copy(E.y) 236 y2.sqr() 237 if !y2.Equals(rhs) { 238 E.inf() 239 } 240 return E 241 } 242 243 /* construct this from x - but set to O if not on curve */ 244 func NewECP2fp2(ix *FP2) *ECP2 { 245 E:=new(ECP2) 246 E.x=NewFP2copy(ix) 247 E.y=NewFP2int(1) 248 E.z=NewFP2int(1) 249 rhs:=RHS2(E.x) 250 if rhs.sqrt() { 251 E.y.copy(rhs) 252 //E.INF=false; 253 } else {E.inf()} 254 return E 255 } 256 257 /* this+=this */ 258 func (E *ECP2) dbl() int { 259 // if E.INF {return -1} 260 261 iy:=NewFP2copy(E.y) 262 if SEXTIC_TWIST == D_TYPE { 263 iy.mul_ip(); iy.norm() 264 } 265 266 t0:=NewFP2copy(E.y) //***** Change 267 t0.sqr(); 268 if SEXTIC_TWIST == D_TYPE { 269 t0.mul_ip() 270 } 271 t1:=NewFP2copy(iy) 272 t1.mul(E.z) 273 t2:=NewFP2copy(E.z) 274 t2.sqr() // z^2 275 276 E.z.copy(t0) // y^2 277 E.z.add(t0); E.z.norm() // 2y^2 278 E.z.add(E.z) 279 E.z.add(E.z) // 8y^2 280 E.z.norm() 281 282 t2.imul(3*CURVE_B_I) // 3bz^2 283 if SEXTIC_TWIST == M_TYPE { 284 t2.mul_ip() 285 t2.norm() 286 } 287 x3:=NewFP2copy(t2) 288 x3.mul(E.z) 289 290 y3:=NewFP2copy(t0) 291 292 y3.add(t2); y3.norm() 293 E.z.mul(t1) 294 t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm() 295 t0.sub(t2); t0.norm() //y^2-9bz^2 296 y3.mul(t0); y3.add(x3) //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 297 t1.copy(E.x); t1.mul(iy) // 298 E.x.copy(t0); E.x.norm(); E.x.mul(t1); E.x.add(E.x) //(y^2-9bz^2)xy2 299 300 E.x.norm() 301 E.y.copy(y3); E.y.norm() 302 303 return 1 304 } 305 306 /* this+=Q - return 0 for add, 1 for double, -1 for O */ 307 func (E *ECP2) Add(Q *ECP2) int { 308 /* if E.INF { 309 E.Copy(Q) 310 return -1 311 } 312 if Q.INF {return -1} 313 */ 314 b:=3*CURVE_B_I 315 t0:=NewFP2copy(E.x) 316 t0.mul(Q.x) // x.Q.x 317 t1:=NewFP2copy(E.y) 318 t1.mul(Q.y) // y.Q.y 319 320 t2:=NewFP2copy(E.z) 321 t2.mul(Q.z) 322 t3:=NewFP2copy(E.x) 323 t3.add(E.y); t3.norm() //t3=X1+Y1 324 t4:=NewFP2copy(Q.x) 325 t4.add(Q.y); t4.norm() //t4=X2+Y2 326 t3.mul(t4) //t3=(X1+Y1)(X2+Y2) 327 t4.copy(t0); t4.add(t1) //t4=X1.X2+Y1.Y2 328 329 t3.sub(t4); t3.norm(); 330 if SEXTIC_TWIST == D_TYPE { 331 t3.mul_ip(); t3.norm() //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 332 } 333 t4.copy(E.y); 334 t4.add(E.z); t4.norm() //t4=Y1+Z1 335 x3:=NewFP2copy(Q.y) 336 x3.add(Q.z); x3.norm() //x3=Y2+Z2 337 338 t4.mul(x3) //t4=(Y1+Z1)(Y2+Z2) 339 x3.copy(t1) // 340 x3.add(t2) //X3=Y1.Y2+Z1.Z2 341 342 t4.sub(x3); t4.norm(); 343 if SEXTIC_TWIST == D_TYPE { 344 t4.mul_ip(); t4.norm() //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 345 } 346 x3.copy(E.x); x3.add(E.z); x3.norm() // x3=X1+Z1 347 y3:=NewFP2copy(Q.x) 348 y3.add(Q.z); y3.norm() // y3=X2+Z2 349 x3.mul(y3) // x3=(X1+Z1)(X2+Z2) 350 y3.copy(t0) 351 y3.add(t2) // y3=X1.X2+Z1+Z2 352 y3.rsub(x3); y3.norm() // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 353 354 if SEXTIC_TWIST == D_TYPE { 355 t0.mul_ip(); t0.norm() // x.Q.x 356 t1.mul_ip(); t1.norm() // y.Q.y 357 } 358 x3.copy(t0); x3.add(t0) 359 t0.add(x3); t0.norm() 360 t2.imul(b) 361 if SEXTIC_TWIST == M_TYPE { 362 t2.mul_ip(); t2.norm() 363 } 364 z3:=NewFP2copy(t1); z3.add(t2); z3.norm() 365 t1.sub(t2); t1.norm() 366 y3.imul(b) 367 if SEXTIC_TWIST == M_TYPE { 368 y3.mul_ip() 369 y3.norm() 370 } 371 x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2) 372 y3.mul(t0); t1.mul(z3); y3.add(t1) 373 t0.mul(t3); z3.mul(t4); z3.add(t0) 374 375 E.x.copy(x3); E.x.norm() 376 E.y.copy(y3); E.y.norm() 377 E.z.copy(z3); E.z.norm() 378 379 return 0 380 } 381 382 /* set this-=Q */ 383 func (E *ECP2) Sub(Q *ECP2) int { 384 NQ:=NewECP2(); NQ.Copy(Q) 385 NQ.neg() 386 D:=E.Add(NQ) 387 //Q.neg() 388 return D 389 } 390 /* set this*=q, where q is Modulus, using Frobenius */ 391 func (E *ECP2) frob(X *FP2) { 392 // if E.INF {return} 393 X2:=NewFP2copy(X) 394 X2.sqr() 395 E.x.conj() 396 E.y.conj() 397 E.z.conj() 398 E.z.reduce(); 399 E.x.mul(X2) 400 E.y.mul(X2) 401 E.y.mul(X) 402 } 403 404 /* P*=e */ 405 func (E *ECP2) mul(e *BIG) *ECP2 { 406 /* fixed size windows */ 407 mt:=NewBIG() 408 t:=NewBIG() 409 P:=NewECP2() 410 Q:=NewECP2() 411 C:=NewECP2() 412 413 if E.Is_infinity() {return NewECP2()} 414 415 var W []*ECP2 416 var w [1+(NLEN*int(BASEBITS)+3)/4]int8 417 418 //E.Affine() 419 420 /* precompute table */ 421 Q.Copy(E) 422 Q.dbl() 423 424 W=append(W,NewECP2()) 425 W[0].Copy(E); 426 427 for i:=1;i<8;i++ { 428 W=append(W,NewECP2()) 429 W[i].Copy(W[i-1]) 430 W[i].Add(Q) 431 } 432 433 /* make exponent odd - add 2P if even, P if odd */ 434 t.copy(e) 435 s:=int(t.parity()) 436 t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm() 437 t.cmove(mt,s) 438 Q.cmove(E,ns) 439 C.Copy(Q) 440 441 nb:=1+(t.nbits()+3)/4 442 /* convert exponent to signed 4-bit window */ 443 for i:=0;i<nb;i++ { 444 w[i]=int8(t.lastbits(5)-16) 445 t.dec(int(w[i])); t.norm() 446 t.fshr(4) 447 } 448 w[nb]=int8(t.lastbits(5)) 449 450 P.Copy(W[(w[nb]-1)/2]) 451 for i:=nb-1;i>=0;i-- { 452 Q.selector(W,int32(w[i])) 453 P.dbl() 454 P.dbl() 455 P.dbl() 456 P.dbl() 457 P.Add(Q) 458 } 459 P.Sub(C) 460 P.Affine() 461 return P 462 } 463 464 /* Public version */ 465 func (E *ECP2) Mul(e *BIG) *ECP2 { 466 return E.mul(e) 467 } 468 469 /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ 470 // Bos & Costello https://eprint.iacr.org/2013/458.pdf 471 // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf 472 // Side channel attack secure 473 func mul4(Q []*ECP2,u []*BIG) *ECP2 { 474 W:=NewECP2() 475 P:=NewECP2() 476 var T [] *ECP2 477 mt:=NewBIG() 478 var t [] *BIG 479 480 var w [NLEN*int(BASEBITS)+1]int8 481 var s [NLEN*int(BASEBITS)+1]int8 482 483 for i:=0;i<4;i++ { 484 t=append(t,NewBIGcopy(u[i])); 485 //Q[i].Affine(); 486 } 487 488 T=append(T,NewECP2()); T[0].Copy(Q[0]) // Q[0] 489 T=append(T,NewECP2()); T[1].Copy(T[0]); T[1].Add(Q[1]) // Q[0]+Q[1] 490 T=append(T,NewECP2()); T[2].Copy(T[0]); T[2].Add(Q[2]) // Q[0]+Q[2] 491 T=append(T,NewECP2()); T[3].Copy(T[1]); T[3].Add(Q[2]) // Q[0]+Q[1]+Q[2] 492 T=append(T,NewECP2()); T[4].Copy(T[0]); T[4].Add(Q[3]) // Q[0]+Q[3] 493 T=append(T,NewECP2()); T[5].Copy(T[1]); T[5].Add(Q[3]) // Q[0]+Q[1]+Q[3] 494 T=append(T,NewECP2()); T[6].Copy(T[2]); T[6].Add(Q[3]) // Q[0]+Q[2]+Q[3] 495 T=append(T,NewECP2()); T[7].Copy(T[3]); T[7].Add(Q[3]) // Q[0]+Q[1]+Q[2]+Q[3] 496 497 // Make it odd 498 pb:=1-t[0].parity() 499 t[0].inc(pb) 500 // t[0].norm(); 501 502 // Number of bits 503 mt.zero() 504 for i:=0;i<4;i++ { 505 t[i].norm() 506 mt.or(t[i]) 507 } 508 509 nb:=1+mt.nbits(); 510 511 // Sign pivot 512 s[nb-1]=1 513 for i:=0;i<nb-1;i++ { 514 t[0].fshr(1) 515 s[i]=2*int8(t[0].parity())-1 516 } 517 518 // Recoded exponent 519 for i:=0; i<nb; i++ { 520 w[i]=0 521 k:=1 522 for j:=1; j<4; j++ { 523 bt:=s[i]*int8(t[j].parity()) 524 t[j].fshr(1) 525 t[j].dec(int(bt)>>1) 526 t[j].norm() 527 w[i]+=bt*int8(k) 528 k*=2 529 } 530 } 531 532 // Main loop 533 P.selector(T,int32(2*w[nb-1]+1)) 534 for i:=nb-2;i>=0;i-- { 535 P.dbl() 536 W.selector(T,int32(2*w[i]+s[i])) 537 P.Add(W) 538 } 539 540 // apply correction 541 W.Copy(P) 542 W.Sub(Q[0]) 543 P.cmove(W,pb) 544 545 P.Affine() 546 return P 547 } 548 549 /* 550 func mul4(Q []*ECP2,u []*BIG) *ECP2 { 551 var a [4]int8 552 T:=NewECP2() 553 C:=NewECP2() 554 P:=NewECP2() 555 556 var W [] *ECP2 557 558 mt:=NewBIG() 559 var t []*BIG 560 561 var w [NLEN*int(BASEBITS)+1]int8 562 563 for i:=0;i<4;i++ { 564 t=append(t,NewBIGcopy(u[i])); 565 Q[i].Affine(); 566 } 567 568 // precompute table 569 570 W=append(W,NewECP2()); W[0].Copy(Q[0]); W[0].Sub(Q[1]) 571 W=append(W,NewECP2()); W[1].Copy(W[0]) 572 W=append(W,NewECP2()); W[2].Copy(W[0]) 573 W=append(W,NewECP2()); W[3].Copy(W[0]) 574 W=append(W,NewECP2()); W[4].Copy(Q[0]); W[4].Add(Q[1]) 575 W=append(W,NewECP2()); W[5].Copy(W[4]) 576 W=append(W,NewECP2()); W[6].Copy(W[4]) 577 W=append(W,NewECP2()); W[7].Copy(W[4]) 578 579 T.Copy(Q[2]); T.Sub(Q[3]) 580 W[1].Sub(T) 581 W[2].Add(T) 582 W[5].Sub(T) 583 W[6].Add(T) 584 T.Copy(Q[2]); T.Add(Q[3]) 585 W[0].Sub(T) 586 W[3].Add(T) 587 W[4].Sub(T) 588 W[7].Add(T) 589 590 // if multiplier is even add 1 to multiplier, and add P to correction 591 mt.zero(); C.inf() 592 for i:=0;i<4;i++ { 593 if t[i].parity()==0 { 594 t[i].inc(1); t[i].norm() 595 C.Add(Q[i]) 596 } 597 mt.add(t[i]); mt.norm() 598 } 599 600 nb:=1+mt.nbits(); 601 602 // convert exponent to signed 1-bit window 603 for j:=0;j<nb;j++ { 604 for i:=0;i<4;i++ { 605 a[i]=int8(t[i].lastbits(2)-2) 606 t[i].dec(int(a[i])); t[i].norm() 607 t[i].fshr(1) 608 } 609 w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3]) 610 } 611 w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2)) 612 613 P.Copy(W[(w[nb]-1)/2]) 614 for i:=nb-1;i>=0;i-- { 615 T.selector(W,int32(w[i])) 616 P.dbl() 617 P.Add(T) 618 } 619 P.Sub(C) // apply correction 620 621 P.Affine() 622 return P 623 } 624 */ 625 626 /* needed for SOK */ 627 func ECP2_mapit(h []byte) *ECP2 { 628 q:=NewBIGints(Modulus) 629 x:=FromBytes(h[:]) 630 one:=NewBIGint(1) 631 var X *FP2 632 var Q,T,K,xQ,x2Q *ECP2 633 x.Mod(q) 634 for true { 635 X=NewFP2bigs(one,x) 636 Q=NewECP2fp2(X) 637 if !Q.Is_infinity() {break} 638 x.inc(1); x.norm() 639 } 640 /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ 641 Fra:=NewBIGints(Fra) 642 Frb:=NewBIGints(Frb) 643 X=NewFP2bigs(Fra,Frb) 644 if SEXTIC_TWIST == M_TYPE { 645 X.inverse() 646 X.norm() 647 } 648 649 x=NewBIGints(CURVE_Bnx) 650 651 if CURVE_PAIRING_TYPE==BN { 652 T=NewECP2(); T.Copy(Q) 653 T=T.mul(x); 654 if SIGN_OF_X==NEGATIVEX { 655 T.neg() 656 } 657 658 K=NewECP2(); K.Copy(T) 659 K.dbl(); K.Add(T); //K.Affine() 660 661 K.frob(X) 662 Q.frob(X); Q.frob(X); Q.frob(X) 663 Q.Add(T); Q.Add(K) 664 T.frob(X); T.frob(X) 665 Q.Add(T) 666 } 667 if CURVE_PAIRING_TYPE==BLS { 668 // xQ=NewECP2() 669 // x2Q=NewECP2() 670 671 xQ=Q.mul(x) 672 x2Q=xQ.mul(x) 673 674 if SIGN_OF_X==NEGATIVEX { 675 xQ.neg() 676 } 677 678 x2Q.Sub(xQ) 679 x2Q.Sub(Q) 680 681 xQ.Sub(Q) 682 xQ.frob(X) 683 684 Q.dbl() 685 Q.frob(X) 686 Q.frob(X) 687 688 Q.Add(x2Q) 689 Q.Add(xQ) 690 } 691 Q.Affine() 692 return Q 693 } 694 695 func ECP2_generator() *ECP2 { 696 var G *ECP2 697 G=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb))) 698 return G 699 }