BOOL ecap2(ECn& P,ECn3 Q,ECn& R,ECn3 &S,Big& order,Big& cf) { ECn PP=P; ECn RR=R; ZZn3 Qx,Qy,Sx,Sy; int qnr=-get_mip()->cnr; normalise(PP); Q.get(Qx,Qy); // untwist Qx=Qx/qnr; Qy=tx(Qy); Qy=Qy/(qnr*qnr); RR=R; normalise(RR); S.get(Sx,Sy); // untwist Sx=Sx/qnr; Sy=tx(Sy); Sy=Sy/(qnr*qnr); return fast_double_tate_pairing(PP,Qx,Qy,RR,Sx,Sy,order,cf); }
void cofactor(ECn3 &S,Big &x, ZZn2& X) { // S=Phi(2xP)+phi^2(2xP) ZZn6 X1,X2,Y1,Y2; ZZn3 Sx,Sy,T; ECn3 S2; int qnr=get_mip()->cnr; S*=x; S+=S; // hard work done here S.get(Sx,Sy); // untwist Sx=Sx/qnr; Sy=tx(Sy); Sy=Sy/(qnr*qnr); X1=shuffle(Sx,(ZZn3)0); Y1=shuffle((ZZn3)0,Sy); X1.powq(X); Y1.powq(X); X2=X1; Y2=Y1; X2.powq(X); Y2.powq(X); unshuffle(X1,Sx,T); unshuffle(Y1,T,Sy); // twist Sx=qnr*Sx; Sy=txd(Sy*qnr*qnr); S.set(Sx,Sy); unshuffle(X2,Sx,T); unshuffle(Y2,T,Sy); //twist (again, like we did last summer...) Sx=qnr*Sx; Sy=txd(Sy*qnr*qnr); S2.set(Sx,Sy); S+=S2; }
ZZn6 line(ECn3& A,ECn3& C,ECn3& B,int type,ZZn3& slope,ZZn3& ex1,ZZn3& ex2,ZZn& Px,ZZn& Py) { ZZn6 w; ZZn3 d; #ifdef AFFINE ZZn3 x,y; A.get(x,y); d.set1(Py); w=shuffle(y-slope*(Px+x),d); #endif #ifdef PROJECTIVE ZZn3 x,y,z,z3,t; C.getZ(z3); d.set1(Py); if (type==MR_ADD) { // exploit that B is in affine ZZn3 x2,y2; B.get(x2,y2); y2*=z3; d*=z3; w=shuffle(y2-slope*(Px+x2),d); } if (type==MR_DOUBLE) { // use extra information from point doubling A.get(x,y,z); w=shuffle(ex1-slope*(Px*ex2+x),d*z3*ex2); } #endif return w; }
ZZn18 g(ECn3& A,ECn3& B,ZZn& Qx,ZZn& Qy) { ZZn3 lam; ZZn18 r; ECn3 P=A; // Evaluate line from A A.add(B,lam); if (A.iszero()) return (ZZn18)1; r=line(P,A,lam,Qx,Qy); return r; }
BOOL ecap(ECn& P,ECn3& Q,Big& x,ZZn2 &X,ZZn6& res) { BOOL Ok; ECn PP=P; ZZn3 Qx,Qy; int qnr=get_mip()->cnr; normalise(PP); Q.get(Qx,Qy); // untwist Qx=Qx/qnr; Qy=tx(Qy); Qy=Qy/(qnr*qnr); #ifdef MR_COUNT_OPS fpc=fpa=fpx=0; #endif Ok=fast_tate_pairing(PP,Qx,Qy,x,X,res); #ifdef MR_COUNT_OPS printf("After pairing fpc= %d fpa= %d fpx= %d\n",fpc,fpa,fpx); fpa=fpc=fpx=0; #endif if (Ok) return TRUE; return FALSE; }
ECn3 hash_and_map3(char *ID) { int i; ECn3 S; ZZn3 X; Big x0=H1(ID); forever { x0+=1; X.set((ZZn)0,(ZZn)x0,(ZZn)0); if (!S.set(X)) continue; break; } return S; }
ECn3 psi(ECn3 &A,ZZn &W,int n) { int i; ECn3 R; ZZn3 X,Y; ZZn FF; // Fast multiplication of A by q^n A.get(X,Y); FF=NR*W*W; for (i=0;i<n;i++) { // assumes p=13 mod 18 X.powq(); X=tx(FF*X); Y.powq(); Y*=(ZZn)get_mip()->sru; } R.set(X,Y); return R; }
ECn3 hash_and_map3(char *ID) { int i; ECn3 S; ZZn3 X; Big x0=H1(ID); forever { x0+=1; X.set2((ZZn)x0); if (!S.set(X)) continue; break; } // cout << "S= " << S << endl; return S; }
int PFC::precomp_for_mult(G2& w,BOOL small) { ECn3 v; ZZn3 x,y; int i,j,k,bp,is,t; if (small) t=MR_ROUNDUP(2*S,WINDOW_SIZE); else t=MR_ROUNDUP(bits(*ord),WINDOW_SIZE); w.g.norm(); v=w.g; w.mtable=new ECn3[1<<WINDOW_SIZE]; v.norm(); w.mtable[1]=v; w.mtbits=t; for (j=0;j<t;j++) v+=v; k=1; for (i=2;i<(1<<WINDOW_SIZE);i++) { if (i==(1<<k)) { k++; v.norm(); w.mtable[i]=v; for (j=0;j<t;j++) v+=v; continue; } bp=1; for (j=0;j<k;j++) { if (i&bp) { is=1<<j; w.mtable[i]+=w.mtable[is]; } bp<<=1; } w.mtable[i].norm(); } return (1<<WINDOW_SIZE); }
ZZn6 g(ECn3& A,ECn3& B,ZZn& Px,ZZn& Py) { BOOL type; ZZn3 lam,ex1,ex2; ECn3 Q=A; // Evaluate line from A to A+B type=A.add(B,lam,&ex1,&ex2); return line(Q,A,B,type,lam,ex1,ex2,Px,Py); }
void q_power_frobenius(ECn3 &S,ZZn2& X) { ZZn6 X1,X2,Y1,Y2; ZZn3 Sx,Sy,T; int qnr=get_mip()->cnr; S.get(Sx,Sy); // untwist Sx=Sx/qnr; Sy=tx(Sy); Sy=Sy/(qnr*qnr); X1=shuffle(Sx,(ZZn3)0); Y1=shuffle((ZZn3)0,Sy); X1.powq(X); Y1.powq(X); unshuffle(X1,Sx,T); unshuffle(Y1,T,Sy); // twist Sx=qnr*Sx; Sy=txd(Sy*qnr*qnr); S.set(Sx,Sy); }
ZZn18 line(ECn3& A,ECn3& C,ZZn3& slope,ZZn& Qx,ZZn& Qy) { ZZn18 w; ZZn6 nn,dd; ZZn3 X,Y; A.get(X,Y); nn.set(Qy,Y-slope*X); dd.set(slope*Qx); w.set(nn,dd); //cout << "1. w= " << w << endl; return w; }
BOOL ate(ECn3& Q,ECn& P,Big &x,ZZn2& X,ZZn6& res) { int i,j,n,nb,nbw,nzs; ECn3 A; ZZn Px,Py; ZZn6 w; Big q=x*x-x+1; #ifdef MR_COUNT_OPS fpc=fpa=fpx=0; #endif normalise(P); #ifdef PROJECTIVE Q.norm(); #endif extract(P,Px,Py); Px+=Px; // because x^6+2 is irreducible.. simplifies line function calculation Py+=Py; res=1; A=Q; // reset A nb=bits(x); res.mark_as_miller(); for (i=nb-2;i>=0;i--) { res*=res; res*=g(A,A,Px,Py); if (bit(x,i)==1) res*=g(A,Q,Px,Py); if (res.iszero()) return FALSE; } #ifdef MR_COUNT_OPS printf("After Miller fpc= %d fpa= %d fpx= %d\n",fpc,fpa,fpx); #endif // if (!A.iszero() || res.iszero()) return FALSE; w=res; w.powq(X); res*=w; // ^(p+1) w=res; w.powq(X); w.powq(X); w.powq(X); res=w/res; // ^(p^3-1) // exploit the clever "trick" for a half-length exponentiation! res.mark_as_unitary(); w=res; res.powq(X); // res*=res; // res=pow(res,CF); if (x<0) res/=powu(w,-x); else res*=powu(w,x); #ifdef MR_COUNT_OPS printf("After pairing fpc= %d fpa= %d fpx= %d\n",fpc,fpa,fpx); fpa=fpc=fpx=0; #endif if (res==(ZZn6)1) return FALSE; return TRUE; }