github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/FP256BN/PAIR.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 BN Curve Pairing functions */
    21  
    22  package FP256BN
    23  
    24  
    25  
    26  /* Line function */
    27  func line(A *ECP2,B *ECP2,Qx *FP,Qy *FP) *FP12 {
    28  	var a *FP4
    29  	var b *FP4
    30  	var c *FP4
    31  
    32  	if (A==B) { /* Doubling */
    33  		XX:=NewFP2copy(A.getx())  //X
    34  		YY:=NewFP2copy(A.gety())  //Y
    35  		ZZ:=NewFP2copy(A.getz())  //Z
    36  		YZ:=NewFP2copy(YY)        //Y 
    37  		YZ.mul(ZZ)                //YZ
    38  		XX.sqr()			//X^2
    39  		YY.sqr()			//Y^2
    40  		ZZ.sqr()			//Z^2
    41  			
    42  		YZ.imul(4)
    43  		YZ.neg(); YZ.norm()       //-4YZ
    44  		YZ.pmul(Qy);               //-4YZ.Ys
    45  
    46  		XX.imul(6)                //6X^2
    47  		XX.pmul(Qx);              //6X^2.Xs
    48  
    49  		sb:=3*CURVE_B_I
    50  		ZZ.imul(sb); 			// 3bZ^2
    51  		if SEXTIC_TWIST == D_TYPE {	
    52  			ZZ.div_ip2();
    53  		}
    54  		if SEXTIC_TWIST == M_TYPE {
    55  			ZZ.mul_ip();
    56  			ZZ.add(ZZ);
    57  			YZ.mul_ip();
    58  			YZ.norm();
    59  		}
    60  		ZZ.norm() // 3b.Z^2 
    61  
    62  		YY.add(YY)
    63  		ZZ.sub(YY); ZZ.norm()     // 3b.Z^2-2Y^2
    64  
    65  		a=NewFP4fp2s(YZ,ZZ);          // -4YZ.Ys | 3b.Z^2-2Y^2 | 6X^2.Xs 
    66  		if SEXTIC_TWIST == D_TYPE {	
    67  
    68  			b=NewFP4fp2(XX)             // L(0,1) | L(0,0) | L(1,0)
    69  			c=NewFP4int(0)
    70  		}
    71  		if SEXTIC_TWIST == M_TYPE {
    72  			b=NewFP4int(0)
    73  			c=NewFP4fp2(XX); c.times_i()
    74  		}
    75  		A.dbl();
    76  
    77  	} else { /* Addition */
    78  
    79  		X1:=NewFP2copy(A.getx())    // X1
    80  		Y1:=NewFP2copy(A.gety())    // Y1
    81  		T1:=NewFP2copy(A.getz())    // Z1
    82  		T2:=NewFP2copy(A.getz())    // Z1
    83  			
    84  		T1.mul(B.gety())    // T1=Z1.Y2 
    85  		T2.mul(B.getx())    // T2=Z1.X2
    86  
    87  		X1.sub(T2); X1.norm()  // X1=X1-Z1.X2
    88  		Y1.sub(T1); Y1.norm()  // Y1=Y1-Z1.Y2
    89  
    90  		T1.copy(X1)            // T1=X1-Z1.X2
    91  		X1.pmul(Qy)            // X1=(X1-Z1.X2).Ys
    92  
    93  		if SEXTIC_TWIST == M_TYPE {
    94  			X1.mul_ip()
    95  			X1.norm()
    96  		}
    97  
    98  		T1.mul(B.gety())       // T1=(X1-Z1.X2).Y2
    99  
   100  		T2.copy(Y1)           // T2=Y1-Z1.Y2
   101  		T2.mul(B.getx())       // T2=(Y1-Z1.Y2).X2
   102  		T2.sub(T1); T2.norm()          // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
   103  		Y1.pmul(Qx);  Y1.neg(); Y1.norm() // Y1=-(Y1-Z1.Y2).Xs
   104  
   105  		a=NewFP4fp2s(X1,T2)       // (X1-Z1.X2).Ys  |  (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2  | - (Y1-Z1.Y2).Xs
   106  		if SEXTIC_TWIST == D_TYPE {
   107  			b=NewFP4fp2(Y1)
   108  			c=NewFP4int(0)
   109  		}
   110  		if SEXTIC_TWIST == M_TYPE {
   111  			b=NewFP4int(0)
   112  			c=NewFP4fp2(Y1); c.times_i()
   113  		}
   114  		A.Add(B);
   115  	}
   116  
   117  
   118  	return NewFP12fp4s(a,b,c)
   119  }
   120  
   121  /* Optimal R-ate pairing */
   122  func Ate(P1 *ECP2,Q1 *ECP) *FP12 {
   123  	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   124  	x:=NewBIGints(CURVE_Bnx)
   125  	n:=NewBIGcopy(x)
   126  	K:=NewECP2()
   127  	var lv *FP12
   128  	
   129  	if CURVE_PAIRING_TYPE == BN {
   130  		if SEXTIC_TWIST==M_TYPE {
   131  			f.inverse();
   132  			f.norm();
   133  		}
   134  		n.pmul(6)
   135  		if SIGN_OF_X==POSITIVEX {
   136  			n.inc(2)
   137  		} else {
   138  			n.dec(2)
   139  		}
   140  	} else {n.copy(x)}
   141  	
   142  	n.norm()
   143  
   144  	n3:=NewBIGcopy(n);
   145  	n3.pmul(3);
   146  	n3.norm();
   147  
   148  	P:=NewECP2(); P.Copy(P1); P.Affine()
   149  	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
   150  
   151  
   152  	Qx:=NewFPcopy(Q.getx())
   153  	Qy:=NewFPcopy(Q.gety())
   154  
   155  	A:=NewECP2()
   156  	r:=NewFP12int(1)
   157  
   158  	A.Copy(P)
   159  
   160  	NP:=NewECP2()
   161  	NP.Copy(P)
   162  	NP.neg()
   163  
   164  	nb:=n3.nbits()
   165  
   166  	for i:=nb-2;i>=1;i-- {
   167  		r.sqr()
   168  		lv=line(A,A,Qx,Qy)
   169  		r.smul(lv,SEXTIC_TWIST)
   170  		bt:=n3.bit(i)-n.bit(i);
   171  		if bt==1 {
   172  			lv=line(A,P,Qx,Qy)
   173  			r.smul(lv,SEXTIC_TWIST)
   174  		}	
   175  		if bt==-1 {
   176  			//P.neg()
   177  			lv=line(A,NP,Qx,Qy)
   178  			r.smul(lv,SEXTIC_TWIST)
   179  			//P.neg()
   180  		}		
   181  	}
   182  
   183  	if SIGN_OF_X==NEGATIVEX {
   184  		r.conj()
   185  	}
   186  
   187  
   188  /* R-ate fixup required for BN curves */
   189  
   190  	if CURVE_PAIRING_TYPE == BN {
   191  		if SIGN_OF_X==NEGATIVEX {
   192  			//r.conj()
   193  			A.neg()
   194  		}
   195  
   196  		K.Copy(P)
   197  		K.frob(f)
   198  		lv=line(A,K,Qx,Qy)
   199  		r.smul(lv,SEXTIC_TWIST)
   200  		K.frob(f)
   201  		K.neg()
   202  		lv=line(A,K,Qx,Qy)
   203  		r.smul(lv,SEXTIC_TWIST)
   204  	} 
   205  
   206  	return r
   207  }
   208  
   209  /* Optimal R-ate double pairing e(P,Q).e(R,S) */
   210  func Ate2(P1 *ECP2,Q1 *ECP,R1 *ECP2,S1 *ECP) *FP12 {
   211  	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   212  	x:=NewBIGints(CURVE_Bnx)
   213  	n:=NewBIGcopy(x)
   214  	K:=NewECP2()
   215  	var lv *FP12
   216  
   217  	if CURVE_PAIRING_TYPE == BN {
   218  		if SEXTIC_TWIST==M_TYPE {
   219  			f.inverse();
   220  			f.norm();
   221  		}
   222  		n.pmul(6); 
   223  		if SIGN_OF_X==POSITIVEX {
   224  			n.inc(2)
   225  		} else {
   226  			n.dec(2)
   227  		}
   228  	} else {n.copy(x)}
   229  	
   230  	n.norm()
   231  
   232  	n3:=NewBIGcopy(n);
   233  	n3.pmul(3);
   234  	n3.norm();
   235  
   236  	P:=NewECP2(); P.Copy(P1); P.Affine()
   237  	Q:=NewECP(); Q.Copy(Q1); Q.Affine()
   238  	R:=NewECP2(); R.Copy(R1); R.Affine()
   239  	S:=NewECP(); S.Copy(S1); S.Affine()
   240  
   241  
   242  	Qx:=NewFPcopy(Q.getx())
   243  	Qy:=NewFPcopy(Q.gety())
   244  	Sx:=NewFPcopy(S.getx())
   245  	Sy:=NewFPcopy(S.gety())
   246  
   247  	A:=NewECP2()
   248  	B:=NewECP2()
   249  	r:=NewFP12int(1)
   250  
   251  	A.Copy(P)
   252  	B.Copy(R)
   253  	NP:=NewECP2()
   254  	NP.Copy(P)
   255  	NP.neg()
   256  	NR:=NewECP2()
   257  	NR.Copy(R)
   258  	NR.neg()
   259  
   260  
   261  	nb:=n3.nbits()
   262  
   263  	for i:=nb-2;i>=1;i-- {
   264  		r.sqr()
   265  		lv=line(A,A,Qx,Qy)
   266  		r.smul(lv,SEXTIC_TWIST)
   267  		lv=line(B,B,Sx,Sy)
   268  		r.smul(lv,SEXTIC_TWIST)
   269  		bt:=n3.bit(i)-n.bit(i);
   270  		if bt==1 {
   271  			lv=line(A,P,Qx,Qy)
   272  			r.smul(lv,SEXTIC_TWIST)
   273  			lv=line(B,R,Sx,Sy)
   274  			r.smul(lv,SEXTIC_TWIST)
   275  		}
   276  		if bt==-1 {
   277  			//P.neg(); 
   278  			lv=line(A,NP,Qx,Qy)
   279  			r.smul(lv,SEXTIC_TWIST)
   280  			//P.neg(); 
   281  			//R.neg()
   282  			lv=line(B,NR,Sx,Sy)
   283  			r.smul(lv,SEXTIC_TWIST)
   284  			//R.neg()
   285  		}
   286  	}
   287  
   288  	if SIGN_OF_X==NEGATIVEX {
   289  		r.conj()
   290  	}
   291  
   292  /* R-ate fixup */
   293  	if CURVE_PAIRING_TYPE == BN {
   294  		if SIGN_OF_X==NEGATIVEX {
   295  		//	r.conj()
   296  			A.neg()
   297  			B.neg()
   298  		}
   299  		K.Copy(P)
   300  		K.frob(f)
   301  
   302  		lv=line(A,K,Qx,Qy)
   303  		r.smul(lv,SEXTIC_TWIST)
   304  		K.frob(f)
   305  		K.neg()
   306  		lv=line(A,K,Qx,Qy)
   307  		r.smul(lv,SEXTIC_TWIST)
   308  
   309  		K.Copy(R)
   310  		K.frob(f)
   311  
   312  		lv=line(B,K,Sx,Sy)
   313  		r.smul(lv,SEXTIC_TWIST)
   314  		K.frob(f)
   315  		K.neg()
   316  		lv=line(B,K,Sx,Sy)
   317  		r.smul(lv,SEXTIC_TWIST)
   318  	}
   319  
   320  	return r
   321  }
   322  
   323  /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
   324  func Fexp(m *FP12) *FP12 {
   325  	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   326  	x:=NewBIGints(CURVE_Bnx)
   327  	r:=NewFP12copy(m)
   328  		
   329  /* Easy part of final exp */
   330  	lv:=NewFP12copy(r)
   331  	lv.Inverse()
   332  	r.conj()
   333  
   334  	r.Mul(lv)
   335  	lv.Copy(r)
   336  	r.frob(f)
   337  	r.frob(f)
   338  	r.Mul(lv)
   339  /* Hard part of final exp */
   340  	if CURVE_PAIRING_TYPE == BN {
   341  		lv.Copy(r)
   342  		lv.frob(f)
   343  		x0:=NewFP12copy(lv)
   344  		x0.frob(f)
   345  		lv.Mul(r)
   346  		x0.Mul(lv)
   347  		x0.frob(f)
   348  		x1:=NewFP12copy(r)
   349  		x1.conj()
   350  		x4:=r.Pow(x)
   351  		if SIGN_OF_X==POSITIVEX {
   352  			x4.conj();
   353  		}
   354  
   355  		x3:=NewFP12copy(x4)
   356  		x3.frob(f)
   357  
   358  		x2:=x4.Pow(x)
   359  		if SIGN_OF_X==POSITIVEX {
   360  			x2.conj();
   361  		}
   362  
   363  		x5:=NewFP12copy(x2); x5.conj()
   364  		lv=x2.Pow(x)
   365  		if SIGN_OF_X==POSITIVEX {
   366  			lv.conj();
   367  		}
   368  
   369  		x2.frob(f)
   370  		r.Copy(x2); r.conj()
   371  
   372  		x4.Mul(r)
   373  		x2.frob(f)
   374  
   375  		r.Copy(lv)
   376  		r.frob(f)
   377  		lv.Mul(r)
   378  
   379  		lv.usqr()
   380  		lv.Mul(x4)
   381  		lv.Mul(x5)
   382  		r.Copy(x3)
   383  		r.Mul(x5)
   384  		r.Mul(lv)
   385  		lv.Mul(x2)
   386  		r.usqr()
   387  		r.Mul(lv)
   388  		r.usqr()
   389  		lv.Copy(r)
   390  		lv.Mul(x1)
   391  		r.Mul(x0)
   392  		lv.usqr()
   393  		r.Mul(lv)
   394  		r.reduce()
   395  	} else {
   396  		
   397  // Ghamman & Fouotsa Method
   398  		y0:=NewFP12copy(r); y0.usqr()
   399  		y1:=y0.Pow(x)
   400  		if SIGN_OF_X==NEGATIVEX {
   401  			y1.conj();
   402  		}
   403  
   404  		x.fshr(1); y2:=y1.Pow(x); 
   405  		if SIGN_OF_X==NEGATIVEX {
   406  			y2.conj();
   407  		}
   408  		
   409  		x.fshl(1)
   410  		y3:=NewFP12copy(r); y3.conj()
   411  		y1.Mul(y3)
   412  
   413  		y1.conj()
   414  		y1.Mul(y2)
   415  
   416  		y2=y1.Pow(x)
   417  		if SIGN_OF_X==NEGATIVEX {
   418  			y2.conj();
   419  		}
   420  
   421  
   422  		y3=y2.Pow(x)
   423  		if SIGN_OF_X==NEGATIVEX {
   424  			y3.conj();
   425  		}
   426  
   427  		y1.conj()
   428  		y3.Mul(y1)
   429  
   430  		y1.conj();
   431  		y1.frob(f); y1.frob(f); y1.frob(f)
   432  		y2.frob(f); y2.frob(f)
   433  		y1.Mul(y2)
   434  
   435  		y2=y3.Pow(x)
   436  		if SIGN_OF_X==NEGATIVEX {
   437  			y2.conj();
   438  		}
   439  
   440  		y2.Mul(y0)
   441  		y2.Mul(r)
   442  
   443  		y1.Mul(y2)
   444  		y2.Copy(y3); y2.frob(f)
   445  		y1.Mul(y2)
   446  		r.Copy(y1)
   447  		r.reduce()
   448  
   449  
   450  /*
   451  		x0:=NewFP12copy(r)
   452  		x1:=NewFP12copy(r)
   453  		lv.Copy(r); lv.frob(f)
   454  		x3:=NewFP12copy(lv); x3.conj(); x1.Mul(x3)
   455  		lv.frob(f); lv.frob(f)
   456  		x1.Mul(lv)
   457  
   458  		r.Copy(r.Pow(x))  //r=r.Pow(x);
   459  		x3.Copy(r); x3.conj(); x1.Mul(x3)
   460  		lv.Copy(r); lv.frob(f)
   461  		x0.Mul(lv)
   462  		lv.frob(f)
   463  		x1.Mul(lv)
   464  		lv.frob(f)
   465  		x3.Copy(lv); x3.conj(); x0.Mul(x3)
   466  
   467  		r.Copy(r.Pow(x))
   468  		x0.Mul(r)
   469  		lv.Copy(r); lv.frob(f); lv.frob(f)
   470  		x3.Copy(lv); x3.conj(); x0.Mul(x3)
   471  		lv.frob(f)
   472  		x1.Mul(lv)
   473  
   474  		r.Copy(r.Pow(x))
   475  		lv.Copy(r); lv.frob(f)
   476  		x3.Copy(lv); x3.conj(); x0.Mul(x3)
   477  		lv.frob(f)
   478  		x1.Mul(lv)
   479  
   480  		r.Copy(r.Pow(x))
   481  		x3.Copy(r); x3.conj(); x0.Mul(x3)
   482  		lv.Copy(r); lv.frob(f)
   483  		x1.Mul(lv)
   484  
   485  		r.Copy(r.Pow(x))
   486  		x1.Mul(r)
   487  
   488  		x0.usqr()
   489  		x0.Mul(x1)
   490  		r.Copy(x0)
   491  		r.reduce() */
   492  	}
   493  	return r
   494  }
   495  
   496  /* GLV method */
   497  func glv(e *BIG) []*BIG {
   498  	var u []*BIG
   499  	if CURVE_PAIRING_TYPE == BN {
   500  		t:=NewBIGint(0)
   501  		q:=NewBIGints(CURVE_Order)
   502  		var v []*BIG
   503  
   504  		for i:=0;i<2;i++ {
   505  			t.copy(NewBIGints(CURVE_W[i]))  // why not just t=new BIG(ROM.CURVE_W[i]); 
   506  			d:=mul(t,e)
   507  			v=append(v,NewBIGcopy(d.div(q)))
   508  			u=append(u,NewBIGint(0))
   509  		}
   510  		u[0].copy(e)
   511  		for i:=0;i<2;i++ {
   512  			for j:=0;j<2;j++ {
   513  				t.copy(NewBIGints(CURVE_SB[j][i]))
   514  				t.copy(Modmul(v[j],t,q))
   515  				u[i].add(q)
   516  				u[i].sub(t)
   517  				u[i].Mod(q)
   518  			}
   519  		}
   520  	} else {
   521  		q:=NewBIGints(CURVE_Order)
   522  		x:=NewBIGints(CURVE_Bnx)
   523  		x2:=smul(x,x)
   524  		u=append(u,NewBIGcopy(e))
   525  		u[0].Mod(x2)
   526  		u=append(u,NewBIGcopy(e))
   527  		u[1].div(x2)
   528  		u[1].rsub(q)
   529  	}
   530  	return u
   531  }
   532  
   533  /* Galbraith & Scott Method */
   534  func gs(e *BIG) []*BIG {
   535  	var u []*BIG
   536  	if CURVE_PAIRING_TYPE == BN {
   537  		t:=NewBIGint(0)
   538  		q:=NewBIGints(CURVE_Order)
   539  
   540  		var v []*BIG
   541  		for i:=0;i<4;i++ {
   542  			t.copy(NewBIGints(CURVE_WB[i]))
   543  			d:=mul(t,e)
   544  			v=append(v,NewBIGcopy(d.div(q)))
   545  			u=append(u,NewBIGint(0))
   546  		}
   547  		u[0].copy(e)
   548  		for i:=0;i<4;i++ {
   549  			for j:=0;j<4;j++ {
   550  				t.copy(NewBIGints(CURVE_BB[j][i]))
   551  				t.copy(Modmul(v[j],t,q))
   552  				u[i].add(q)
   553  				u[i].sub(t)
   554  				u[i].Mod(q)
   555  			}
   556  		}
   557  	} else {
   558  		q:=NewBIGints(CURVE_Order)
   559  		x:=NewBIGints(CURVE_Bnx)
   560  		w:=NewBIGcopy(e)
   561  		for i:=0;i<3;i++ {
   562  			u=append(u,NewBIGcopy(w))
   563  			u[i].Mod(x)
   564  			w.div(x)
   565  		}
   566  		u=append(u,NewBIGcopy(w))
   567  		if SIGN_OF_X==NEGATIVEX {
   568  			u[1].copy(Modneg(u[1],q));
   569  			u[3].copy(Modneg(u[3],q));
   570  		}
   571  	}
   572  	return u
   573  }	
   574  
   575  /* Multiply P by e in group G1 */
   576  func G1mul(P *ECP,e *BIG) *ECP {
   577  	var R *ECP
   578  	if (USE_GLV) {
   579  		//P.Affine()
   580  		R=NewECP()
   581  		R.Copy(P)
   582  		Q:=NewECP()
   583  		Q.Copy(P); Q.Affine()
   584  		q:=NewBIGints(CURVE_Order)
   585  		cru:=NewFPbig(NewBIGints(CURVE_Cru))
   586  		t:=NewBIGint(0)
   587  		u:=glv(e)
   588  		Q.getx().mul(cru)
   589  
   590  		np:=u[0].nbits()
   591  		t.copy(Modneg(u[0],q))
   592  		nn:=t.nbits()
   593  		if nn<np {
   594  			u[0].copy(t)
   595  			R.neg()
   596  		}
   597  
   598  		np=u[1].nbits()
   599  		t.copy(Modneg(u[1],q))
   600  		nn=t.nbits()
   601  		if nn<np {
   602  			u[1].copy(t)
   603  			Q.neg()
   604  		}
   605  		u[0].norm()
   606  		u[1].norm()
   607  		R=R.Mul2(u[0],Q,u[1])
   608  			
   609  	} else {
   610  		R=P.mul(e)
   611  	}
   612  	return R
   613  }
   614  
   615  /* Multiply P by e in group G2 */
   616  func G2mul(P *ECP2,e *BIG) *ECP2 {
   617  	var R *ECP2
   618  	if (USE_GS_G2) {
   619  		var Q []*ECP2
   620  		f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   621  
   622  		if SEXTIC_TWIST==M_TYPE {
   623  			f.inverse();
   624  			f.norm();
   625  		}
   626  
   627  		q:=NewBIGints(CURVE_Order)
   628  		u:=gs(e)
   629  
   630  		t:=NewBIGint(0)
   631  		//P.Affine()
   632  		Q=append(Q,NewECP2());  Q[0].Copy(P);
   633  		for i:=1;i<4;i++ {
   634  			Q=append(Q,NewECP2()); Q[i].Copy(Q[i-1])
   635  			Q[i].frob(f)
   636  		}
   637  		for i:=0;i<4;i++ {
   638  			np:=u[i].nbits()
   639  			t.copy(Modneg(u[i],q))
   640  			nn:=t.nbits()
   641  			if nn<np {
   642  				u[i].copy(t)
   643  				Q[i].neg()
   644  			}
   645  			u[i].norm()
   646  		}
   647  
   648  		R=mul4(Q,u)
   649  
   650  	} else {
   651  		R=P.mul(e)
   652  	}
   653  	return R
   654  }
   655  
   656  /* f=f^e */
   657  /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */
   658  func GTpow(d *FP12,e *BIG) *FP12 {
   659  	var r *FP12
   660  	if USE_GS_GT {
   661  		var g []*FP12
   662  		f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   663  		q:=NewBIGints(CURVE_Order)
   664  		t:=NewBIGint(0)
   665  	
   666  		u:=gs(e)
   667  
   668  		g=append(g,NewFP12copy(d))
   669  		for i:=1;i<4;i++ {
   670  			g=append(g,NewFP12int(0))
   671  			g[i].Copy(g[i-1])
   672  			g[i].frob(f)
   673  		}
   674  		for i:=0;i<4;i++ {
   675  			np:=u[i].nbits()
   676  			t.copy(Modneg(u[i],q))
   677  			nn:=t.nbits()
   678  			if nn<np {
   679  				u[i].copy(t)
   680  				g[i].conj()
   681  			}
   682  			u[i].norm()			
   683  		}
   684  		r=pow4(g,u)
   685  	} else {
   686  		r=d.Pow(e)
   687  	}
   688  	return r
   689  }
   690  
   691  /* test group membership - no longer needed*/
   692  /* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
   693  /*
   694  func GTmember(m *FP12) bool {
   695  	if m.Isunity() {return false}
   696  	r:=NewFP12copy(m)
   697  	r.conj()
   698  	r.Mul(m)
   699  	if !r.Isunity() {return false}
   700  
   701  	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   702  
   703  	r.Copy(m); r.frob(f); r.frob(f)
   704  	w:=NewFP12copy(r); w.frob(f); w.frob(f)
   705  	w.Mul(m)
   706  	if !GT_STRONG {
   707  		if !w.Equals(r) {return false}
   708  		x:=NewBIGints(CURVE_Bnx);
   709  		r.Copy(m); w=r.Pow(x); w=w.Pow(x)
   710  		r.Copy(w); r.sqr(); r.Mul(w); r.sqr()
   711  		w.Copy(m); w.frob(f)
   712  	}
   713  	return w.Equals(r)
   714  }
   715  */
   716  /*
   717  func main() {
   718  
   719  	Q:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy))
   720  	P:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb)))
   721  
   722  	//r:=NewBIGints(CURVE_Order)
   723  	//xa:=NewBIGints(CURVE_Pxa)
   724  
   725  	fmt.Printf("P= "+P.toString())
   726  	fmt.Printf("\n");
   727  	fmt.Printf("Q= "+Q.toString());
   728  	fmt.Printf("\n");
   729  
   730  	//m:=NewBIGint(17)
   731  
   732  	e:=Ate(P,Q)
   733  	e=Fexp(e)
   734  	for i:=1;i<1000;i++ {
   735  		e=Ate(P,Q)
   736  //	fmt.Printf("\ne= "+e.toString())
   737  //	fmt.Printf("\n")
   738  
   739  		e=Fexp(e)
   740  	}
   741  	//	e=GTpow(e,m);
   742  
   743  	fmt.Printf("\ne= "+e.toString())
   744  	fmt.Printf("\n");
   745  	GLV:=glv(r)
   746  
   747  	fmt.Printf("GLV[0]= "+GLV[0].toString())
   748  	fmt.Printf("\n")
   749  
   750  	fmt.Printf("GLV[0]= "+GLV[1].toString())
   751  	fmt.Printf("\n")
   752  
   753  	G:=NewECP(); G.Copy(Q)
   754  	R:=NewECP2(); R.Copy(P)
   755  
   756  
   757  	e=Ate(R,Q)
   758  	e=Fexp(e)
   759  
   760  	e=GTpow(e,xa)
   761  	fmt.Printf("\ne= "+e.toString());
   762  	fmt.Printf("\n")
   763  
   764  	R=G2mul(R,xa)
   765  	e=Ate(R,G)
   766  	e=Fexp(e)
   767  
   768  	fmt.Printf("\ne= "+e.toString())
   769  	fmt.Printf("\n")
   770  
   771  	G=G1mul(G,xa)
   772  	e=Ate(P,G)
   773  	e=Fexp(e)
   774  	fmt.Printf("\ne= "+e.toString())
   775  	fmt.Printf("\n") 
   776  }
   777  */