ZZn2 pow(const ZZn2& x,const Big& k) { int i,j,nb,n,nbw,nzs; ZZn2 u,u2,t[16]; if (x.iszero()) return (ZZn2)0; if (k==0) return (ZZn2)1; u=x; if (k==1) return u; // // Prepare table for windowing // u2=(u*u); t[0]=u; for (i=1;i<16;i++) t[i]=u2*t[i-1]; // Left to right method - with windows nb=bits(k); if (nb>1) for (i=nb-2;i>=0;) { n=window(k,i,&nbw,&nzs,5); for (j=0;j<nbw;j++) u*=u; if (n>0) u*=t[n/2]; i-=nbw; if (nzs) { for (j=0;j<nzs;j++) u*=u; i-=nzs; } } return u; }
void g(ECn& A,ECn& B,ZZn& Qx,ZZn2& Qy,ZZn2& num,BOOL precomp,ZZn* store,int& ptr) { ZZn lam,x,y,m,nx; ZZn2 u; big pointer; if (num.iszero()) return; if (!precomp) { // Store line start point and slope. // Evaluate line from A, and then evaluate vertical through destination extract(A,x,y); pointer=A.add(B); if (pointer==NULL) {num=0; return;} lam=pointer; store[ptr++]=x; store[ptr++]=y; store[ptr++]=lam; if (A.iszero()) return; // line m=Qx; u=Qy; m-=x; m*=lam; // 1 ZZn muls u-=y; u-=m; } else { // extract precalculated values from the store.... - nx is a peek ahead x=store[ptr++]; y=store[ptr++]; lam=store[ptr++]; nx=store[ptr]; if (nx.iszero()) return; m=Qx; u=Qy; m-=x; m*=lam; // 1 ZZn muls u-=y; u-=m; } num*=u; // 3 ZZn muls }
GT PFC::multi_miller(int n,G1** QQ,G1** PP) { GT z; ZZn *Px,*Py; int i,j,*k,nb; ECn *Q,*A; ECn P; ZZn2 res; Big iters=*ord-1; Px=new ZZn[n]; Py=new ZZn[n]; Q=new ECn[n]; A=new ECn[n]; k=new int[n]; nb=bits(iters); res=1; for (j=0;j<n;j++) { k[j]=0; P=PP[j]->g; normalise(P); Q[j]=QQ[j]->g; normalise(Q[j]); 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(iters,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; } delete [] k; delete [] A; delete [] Q; delete [] Py; delete [] Px; z.g=res; return z; }
BOOL tate(ECn& P,ECn& Q,Big& q,ZZn& r) { int i,nb,qnr; ZZn2 res; ZZn a,d; Big p,x,y,n; ECn A; p=get_modulus(); // Note that q is fixed - q.P=2^17*(2^142.P + P) + P normalise(Q); // make sure z=1 extract(Q,a,d); qnr=get_mip()->qnr; if (qnr==-2) { a=a/2; /* Convert off twist */ d=d/4; } normalise(P); A=P; // remember A n=q-1; nb=bits(n); res=1; for (i=nb-2;i>=0;i--) { res*=res; // 2 modmul res*=g(A,A,a,d); if (bit(n,i)) res*=g(A,P,a,d); // executed just once } if (A != -P || res.iszero()) return FALSE; res=conj(res)/res; // raise to power of (p-1) r=powl(real(res),(p+1)/q); // raise to power of (p+1)/q if (r==1) return FALSE; return TRUE; }
BOOL fast_tate_pairing(ECn& P,ZZn& Qx,ZZn2& Qy,Big& q,BOOL precomp,ZZn* store,ZZn2& res) { int i,ptr=0; Big p; ECn A; if (!precomp) get_mip()->coord=MR_AFFINE; // precompute using AFFINE // coordinates res=1; // q.P = 2^17*(2^142.P +P) + P A=P; for (i=0;i<142;i++) { res*=res; g(A,A,Qx,Qy,res,precomp,store,ptr); } // 6 ZZn muls after first g(A,P,Qx,Qy,res,precomp,store,ptr); for (i=0;i<17;i++) { res*=res; g(A,A,Qx,Qy,res,precomp,store,ptr); } g(A,P,Qx,Qy,res,precomp,store,ptr); if (res.iszero()) return FALSE; if (!precomp) { if (!A.iszero()) return FALSE; get_mip()->coord=MR_PROJECTIVE; // reset } p=get_modulus(); // get p res= pow(res,(p+1)/q); // raise to power of (p^2-1)/q res=conj(res)/res; if (res.isunity()) return FALSE; return TRUE; }
BOOL fast_tate_pairing(ECn& P,ZZn2& Qx,ZZn2& Qy,Big& q,ZZn2& res) { int i,nb; Big n,p; ECn A; // q.P = 2^17*(2^142.P +P) + P res=1; A=P; // reset A #ifdef SCOTT // we can avoid last iteration.. n=q-1; #else n=q; #endif nb=bits(n); for (i=nb-2;i>=0;i--) { res*=res; g(A,A,Qx,Qy,res); if (bit(n,i)) g(A,P,Qx,Qy,res); } #ifdef SCOTT if (A!=-P || res.iszero()) return FALSE; #else if (!A.iszero()) return FALSE; #endif p=get_modulus(); // get p res= pow(res,(p+1)/q); // raise to power of (p^2-1)/q res=conj(res)/res; if (res.isunity()) return FALSE; return TRUE; }