BOOL fast_pairing(ECn2& P,ZZn& Qx,ZZn& Qy,Big &x,ZZn2 &X,ZZn12& res) { ECn2 A,KA; ZZn2 AX,AY; int i,nb; Big n; ZZn12 r; ZZn12 t0,t1; ZZn12 x0,x1,x2,x3,x4,x5; #ifdef MR_COUNT_OPS fpc=fpa=fpx=fpmq=fpsq=fpaq=0; #endif if (x<0) n=-(6*x+2); else n=6*x+2; A=P; nb=bits(n); r=1; // Short Miller loop r.mark_as_miller(); for (i=nb-2;i>=0;i--) { r*=r; r*=g(A,A,Qx,Qy); if (bit(n,i)) r*=g(A,P,Qx,Qy); } // Combining ideas due to Longa, Aranha et al. and Naehrig KA=P; q_power_frobenius(KA,X); if (x<0) {A=-A; r.conj();} r*=g(A,KA,Qx,Qy); q_power_frobenius(KA,X); KA=-KA; r*=g(A,KA,Qx,Qy); #ifdef MR_COUNT_OPS cout << "Miller fpc= " << fpc << endl; cout << "Miller fpa= " << fpa << endl; cout << "Miller fpx= " << fpx << endl; cout << "Miller fpmq= " << fpmq << endl; cout << "Miller fpsq= " << fpsq << endl; cout << "Miller fpaq= " << fpaq << endl; fpa=fpc=fpx=fpmq=fpsq=fpaq=0; #endif if (r.iszero()) return FALSE; // The final exponentiation t0=r; r.conj(); r/=t0; // r^(p^6-1) r.mark_as_regular(); // no longer "miller" t0=r; r.powq(X); r.powq(X); r*=t0; // r^[(p^6-1)*(p^2+1)] r.mark_as_unitary(); // from now on all inverses are just conjugates !! (and squarings are faster) res=r; // Newer new idea... // See "On the final exponentiation for calculating pairings on ordinary elliptic curves" // Michael Scott and Naomi Benger and Manuel Charlemagne and Luis J. Dominguez Perez and Ezekiel J. Kachisa t0=res; t0.powq(X); x0=t0; x0.powq(X); x0*=(res*t0); x0.powq(X); x1=inverse(res); // just a conjugation! x4=pow(res,-x); // x is sparse.. x3=x4; x3.powq(X); x2=pow(x4,-x); x5=inverse(x2); t0=pow(x2,-x); x2.powq(X); x4/=x2; x2.powq(X); res=t0; res.powq(X); t0*=res; t0*=t0; t0*=x4; t0*=x5; res=x3*x5; res*=t0; t0*=x2; res*=res; res*=t0; res*=res; t0=res*x1; res*=x0; t0*=t0; t0*=res; #ifdef MR_COUNT_OPS cout << "FE fpc= " << fpc << endl; cout << "FE fpa= " << fpa << endl; cout << "FE fpx= " << fpx << endl; cout << "FE fpmq= " << fpmq << endl; cout << "FE fpsq= " << fpsq << endl; cout << "FE fpaq= " << fpaq << endl; fpa=fpc=fpx=fpmq=fpsq=fpaq=0; #endif res= t0; return TRUE; }
GT PFC::multi_miller(int n,G2** QQ,G1** PP) { GT z; ZZn *Px,*Py; int i,j,*k,nb; ECn2 *Q,*A; ECn P; ZZn12 res; Big m; Big X=*x; Px=new ZZn[n]; Py=new ZZn[n]; Q=new ECn2[n]; A=new ECn2[n]; k=new int[n]; if (X<0) m=-(6*X+2); else m=6*X+2; nb=bits(m); res=1; for (j=0;j<n;j++) { k[j]=0; P=PP[j]->g; normalise(P); Q[j]=QQ[j]->g; Q[j].norm(); extract(P,Px[j],Py[j]); } for (j=0;j<n;j++) A[j]=Q[j]; for (i=nb-2;i>=0;i--) { res*=res; for (j=0;j<n;j++) { if (QQ[j]->ptable==NULL) res*=g(A[j],A[j],Px[j],Py[j]); else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); } if (bit(m,i)==1) for (j=0;j<n;j++) { if (QQ[j]->ptable==NULL) res*=g(A[j],Q[j],Px[j],Py[j]); else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); } if (res.iszero()) return 0; } if (X<0) res.conj(); for (j=0;j<n;j++) { q_power_frobenius(Q[j],*frob); if (QQ[j]->ptable==NULL) { if (X<0) A[j]=-A[j]; res*=g(A[j],Q[j],Px[j],Py[j]); } else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); q_power_frobenius(Q[j],*frob); if (QQ[j]->ptable==NULL) { Q[j]=-Q[j]; res*=g(A[j],Q[j],Px[j],Py[j]); } else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); } delete [] k; delete [] A; delete [] Q; delete [] Py; delete [] Px; z.g=res; return z; }