Big H2(ZZn18 x) { // Compress and hash an Fp18 to a big number sha256 sh; ZZn6 u; ZZn3 h,l; Big a,hash; ZZn xx[6]; char s[HASH_LEN]; int i,j,m; shs256_init(&sh); x.get(u); // compress to single ZZn6 u.get(l,h); l.get(xx[0],xx[1],xx[2]); h.get(xx[3],xx[4],xx[5]); for (i=0;i<6;i++) { a=(Big)xx[i]; while (a>0) { m=a%256; shs256_process(&sh,m); a/=256; } } shs256_hash(&sh,s); hash=from_binary(HASH_LEN,s); return hash; }
void PFC::add_to_hash(const GT& x) { ZZn6 u; ZZn18 v=x.g; ZZn3 h,l; Big a; ZZn xx[6]; int i,j,m; v.get(u); u.get(l,h); l.get(xx[0],xx[1],xx[2]); h.get(xx[3],xx[4],xx[5]); for (i=0;i<6;i++) { a=(Big)xx[i]; while (a>0) { m=a%256; shs256_process(&SH,m); a/=256; } } }
BOOL fast_tate_pairing(ECn& P,ZZn6& Qx,ZZn6& Qy,Big& q,Big &cf,ZZn6& res) { int i,j,n,nb,nbw,nzs; ECn A,P2,t[16]; ZZn6 w,hc,z2n,zn[16]; res=zn[0]=1; t[0]=P2=A=P; g(P2,P2,Qx,Qy,z2n,TRUE); // P2=P+P // // Build windowing table // for (i=1;i<16;i++) { g(A,P2,Qx,Qy,hc,TRUE); t[i]=A; zn[i]=z2n*zn[i-1]*hc; } A=P; // reset A /* Left to right method */ nb=bits(q); for (i=nb-2;i>=0;i-=(nbw+nzs)) { n=window(q,i,&nbw,&nzs); // standard MIRACL windowing for (j=0;j<nbw;j++) { res*=res; g(A,A,Qx,Qy,res,FALSE); } if (n>0) { res*=zn[n/2]; g(A,t[n/2],Qx,Qy,res,FALSE); } for (j=0;j<nzs;j++) { res*=res; g(A,A,Qx,Qy,res,FALSE); } if (res.iszero()) return FALSE; } if (!A.iszero() || res.iszero()) return FALSE; res=pow(res,cf); // ^(p*p-p+1)/q w=res; w.powq(); res*=w; // ^(p+1) w=res; w.powq(); w.powq(); w.powq(); res=w/res; // ^(p^3-1) if (res.isunity()) return FALSE; return TRUE; }
ZZn6 shuffle(ZZn3 &first, ZZn3 &second) { // shuffle from a pair ZZn3's to three ZZn2's, as required by ZZn6 ZZn6 w; ZZn x0,x1,x2,x3,x4,x5; ZZn2 t0,t1,t2; first.get(x0,x2,x4); second.get(x1,x3,x5); t0.set(x0,x3); t1.set(x1,x4); t2.set(x2,x5); w.set(t0,t1,t2); return w; }
Big H2(ZZn6 y) { // Hash and compress an Fp6 to a big number sha sh; ZZn u,v,w; ZZn2 x; Big a,h,p,xx[2]; char s[HASH_LEN]; int i,j,m; shs_init(&sh); y.get(x); x.get(u,v); xx[0]=u; xx[1]=v; for (i=0;i<2;i++) { a=xx[i]; while (a>0) { m=a%256; shs_process(&sh,m); a/=256; } } shs_hash(&sh,s); h=from_binary(HASH_LEN,s); return h; }
ZZn6 line(ECn& A,ECn& C,ZZn& slope,ZZn3& Qx,ZZn3& Qy) { ZZn6 w; ZZn3 nn=Qx; ZZn x,y,z,t; extract(A,x,y,z); x*=z; t=z; z*=z; z*=t; x*=slope; t=slope*z; nn*=t; nn-=x; t=z; extract(C,x,x,z); nn+=(z*y); t*=z; w.set(nn,-Qy*t); return w; }
Big H2(ZZn6 x) { // Hash an Fp6 to a big number sha256 sh; ZZn2 u,v,w; ZZn h,l; Big a,hash,p,xx[6]; char s[HASH_LEN]; int i,j,m; shs256_init(&sh); x.get(u,v,w); u.get(l,h); xx[0]=l; xx[1]=h; v.get(l,h); xx[2]=l; xx[3]=h; w.get(l,h); xx[4]=l; xx[5]=h; for (i=0;i<6;i++) { a=xx[i]; while (a>0) { m=a%256; shs256_process(&sh,m); a/=256; } } shs256_hash(&sh,s); hash=from_binary(HASH_LEN,s); return hash; }
GT PFC::miller_loop(const G2& QQ,const G1& PP) { GT z; int i,j,n,nb,nbw,nzs; ECn3 A,Q; ECn P; ZZn Px,Py; BOOL precomp; ZZn6 res; Big X=*x; P=PP.g; Q=QQ.g; #ifdef MR_ECN3_PROJECTIVE Q.norm(); #endif precomp=FALSE; if (QQ.ptable!=NULL) precomp=TRUE; normalise(P); 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(); j=0; for (i=nb-2;i>=0;i--) { res*=res; if (precomp) res*=gp(QQ.ptable,j,Px,Py); else res*=g(A,A,Px,Py); if (bit(X,i)==1) { if (precomp) res*=gp(QQ.ptable,j,Px,Py); else res*=g(A,Q,Px,Py); } } z.g=res; return z; }
void unshuffle(ZZn6 &S,ZZn3 &first,ZZn3 &second) { // unshuffle a ZZn6 into two ZZn3's ZZn x0,x1,x2,x3,x4,x5; ZZn2 t0,t1,t2; S.get(t0,t1,t2); t0.get(x0,x3); t1.get(x1,x4); t2.get(x2,x5); first.set(x0,x2,x4); second.set(x1,x3,x5); }
ZZn6 sqrt(const ZZn6& x) { // sqrt(a+xb) = sqrt((a+sqrt(a*a-n*b*b))/2)+x.b/(2*sqrt((a+sqrt(a*a-n*b*b))/2)) // sqrt(a) = x.sqrt(a/n) // where x*x=n ZZn6 w; ZZn3 a,s,t; if (x.iszero()) return w; if (x.b.iszero()) { w.unitary=x.unitary; a=x.a; if (qr(a)) { s=sqrt(a); w.a=s; w.b=0; } else { a=txd(a); s=sqrt(a); w.a=0; w.b=s; } return w; } s=x.b; s*=s; a=x.a; a*=a; a-=tx(s); s=sqrt(a); if (s.iszero()) return w; w.unitary=x.unitary; if (qr((x.a+s)/2)) { a=sqrt((x.a+s)/2); } else { a=sqrt((x.a-s)/2); if (a.iszero()) return w; } w.a=a; w.b=x.b/(2*a); return w; }
BOOL qr(const ZZn6& x) { ZZn3 a,s; if (x.iszero()) return TRUE; if (x.b.iszero()) return TRUE; s=x.b; s*=s; a=x.a; a*=a; a-=tx(s); if (!qr(a)) return FALSE; return TRUE; /* s=sqrt(a); if (qr((x.a+s)/2) || qr((x.a-s)/2)) return TRUE; exit(0); return FALSE; */ }
void g(ECn& A,ECn& B,ZZn6& Qx,ZZn6& Qy,ZZn6& num,BOOL first) { ZZn lam; ZZn6 u; big ptr; ECn P=A; // Evaluate line from A ptr=A.add(B); if (ptr==NULL) { num.clear(); return; } else lam=ptr; if (A.iszero()) return; u=line(P,A,lam,Qx,Qy); if (first) num= u; else num*=u; }
Big H2(ZZn6 x) { // Hash an Fp6 to a big number sha sh; Big a,h,p,xx[6]; char s[20]; int i,j,m; shs_init(&sh); x.get(xx); for (i=0;i<6;i++) { a=xx[i]; while (a>0) { m=a%256; shs_process(&sh,m); a/=256; } } shs_hash(&sh,s); h=from_binary(20,s); return h; }
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; }
GT PFC::multi_miller(int n,G2** QQ,G1** PP) { GT z; ZZn *Px,*Py; int i,j,*k,nb; ECn3 *Q,*A; ECn P; ZZn6 res; Big X=*x; Px=new ZZn[n]; Py=new ZZn[n]; Q=new ECn3[n]; A=new ECn3[n]; k=new int[n]; nb=bits(X); res=1; for (j=0;j<n;j++) { k[j]=0; P=PP[j]->g; normalise(P); Q[j]=QQ[j]->g; extract(P,Px[j],Py[j]); Px[j]+=Px[j]; Py[j]+=Py[j]; } for (j=0;j<n;j++) { #ifdef MR_ECN3_PROJECTIVE Q[j].norm(); #endif 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(X,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 fast_tate_pairing(ECn& P,ZZn3& Qx,ZZn3& Qy,Big &x,ZZn2& X,ZZn6& res) { int i,j,n,nb,nbw,nzs; ECn A,P2,t[PRECOMP]; ZZn6 w,hc,z2n,zn[PRECOMP]; Big q=x*x-x+1; res=zn[0]=1; t[0]=P2=A=P; z2n=g(P2,P2,Qx,Qy); // P2=P+P normalise(P2); // // Build windowing table // for (i=1;i<PRECOMP;i++) { hc=g(A,P2,Qx,Qy); t[i]=A; zn[i]=z2n*zn[i-1]*hc; } multi_norm(PRECOMP,t); // make t points Affine /* A=P; // reset A nb=bits(q); for (i=nb-2;i>=0;i--) { res*=res; res*=g(A,A,Qx,Qy); if (bit(q,i)==1) res*=g(A,P,Qx,Qy); if (res.iszero()) return FALSE; } */ A=P; // reset A nb=bits(q); for (i=nb-2;i>=0;i-=(nbw+nzs)) { // windowing helps a little.. n=window(q,i,&nbw,&nzs,WINDOW_SIZE); // standard MIRACL windowing for (j=0;j<nbw;j++) { res*=res; res*=g(A,A,Qx,Qy); } if (n>0) { res*=zn[n/2]; res*=g(A,t[n/2],Qx,Qy); } for (j=0;j<nzs;j++) { res*=res; res*=g(A,A,Qx,Qy); } 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); if (res==(ZZn6)1) return FALSE; return TRUE; }