BOOL power_tate(ECn& P,ECn4 Q,Big& q,Big *cf,ZZn2 &Fr,Big &e,ZZn4& r) { int i,nb; ECn A; ZZn8 w,res,a[4]; ZZn4 Qx,Qy; ZZn2 x,y; Big carry,ex[4]; Big p=get_modulus(); Q.get(Qx,Qy); Qx=txd(Qx); Qy=txd(txd(Qy)); res=1; /* Left to right method */ A=P; nb=bits(q); for (i=nb-2;i>=0;i--) { res*=res; res*=g(A,A,Qx,Qy); if (bit(q,i)) res*=g(A,P,Qx,Qy); } if (!A.iszero() || res.iszero()) return FALSE; w=res; w.powq(Fr); w.powq(Fr); // ^(p^4-1) w.powq(Fr); w.powq(Fr); res=w/res; res.mark_as_unitary(); a[3]=res; a[2]=a[3]; a[2].powq(Fr); a[1]=a[2]; a[1].powq(Fr); a[0]=a[1]; a[0].powq(Fr); if (e.isone()) for (i=0;i<4;i++) ex[i]=cf[i]; else { // cf *= e carry=0; for (i=3;i>=0;i--) carry=mad(cf[i],e,carry,p,ex[i]); } res=pow(4,a,ex); r=real(res); // compression // r=powl(real(res),cf); // ^(p*p*p*p+1)/q if (r.isunity()) return FALSE; return TRUE; }
GF2m4x pow(const GF2m4x& a,const Big& k) { int i,j,nb,n,nbw,nzs; GF2m4x u,u2,t[16]; if (k.iszero()) return (GF2m4x)1; u=a; if (k.isone()) 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; }
BOOL power_tate(ECn2& P,ECn Q,Big& T,Big *cf,ZZn2 &Fr,Big &e,ZZn2& r) { int i,nb; ECn2 A; ZZn4 w,res,a[2]; ZZn Qx,Qy; Big carry,ex[2],p=get_modulus(); extract(Q,Qx,Qy); res=1; /* Left to right method */ A=P; nb=bits(T); for (i=nb-2;i>=0;i--) { res*=res; res*=g(A,A,Qx,Qy); if (bit(T,i)) res*=g(A,P,Qx,Qy); } // if (!A.iszero() || res.iszero()) return FALSE; w=res; w.powq(Fr); w.powq(Fr); // ^(p^2-1) res=w/res; res.mark_as_unitary(); if (e.isone()) { ex[0]=cf[0]; ex[1]=cf[1]; } else { // cf *= e carry=mad(cf[1],e,(Big)0,p,ex[1]); mad(cf[0],e,carry,p,ex[0]); } a[0]=a[1]=res; a[0].powq(Fr); res=pow(2,a,ex); r=real(res); // compression if (r.isunity()) return FALSE; return TRUE; }