ZZn2 gp(ZZn* ptable,int &j,ZZn& Px,ZZn& Py) { ZZn2 w; w.set(ptable[j]*Px+ptable[j+1],Py); j+=2; return w; }
ZZn2 line(ECn& A,ECn& C,ECn& B,int type,ZZn& slope,ZZn& ex1,ZZn& ex2,ZZn& Px,ZZn& Py) { ZZn2 w; ZZn x,y,z3; extractZ(C,z3); if (type==MR_ADD) { extract(B,x,y); w.set(slope*(x+Px)-z3*y,z3*Py); } if (type==MR_DOUBLE) { extract(A,x,y); w.set(-(slope*ex2)*Px-slope*x+ex1,-(z3*ex2)*Py); } /* extract(A,x,y,z); x*=z; t=z; z*=z; z*=t; // 9 ZZn muls n*=z; n+=x; n*=slope; d*=z; w.set(-y,d); extractZ(C,z3); w*=z3; w+=n; */ // w.set(Px*z*z*z*slope+slope*x*z-y*z3,Py*z*z*z*z3); 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; }
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 ecap(ECn& P,ECn& Q,Big& order,BOOL precomp,ZZn *store,ZZn2& res) { ZZn Qx; ZZn2 Qy; Big xx,yy; Q.get(xx,yy); Qx=-xx; Qy.set((Big)0,yy); return fast_tate_pairing(P,Qx,Qy,order,precomp,store,res); }
void set_frobenius_constant(ZZn2 &X) { Big p=get_modulus(); switch (get_mip()->pmod8) { case 5: X.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2 break; case 3: // = (1+sqrt(-1))^(p-1)/2 case 7: // = (1+sqrt(-2))^(p-1)/2 X.set((Big)1,(Big)1); default: break; } X=pow(X,(p-1)/2); }
int H2(ZZn2 x,char *s) { // Hash an Fp2 to an n-byte string s[.]. Return n sha256 sh; Big a,b; int m; shs256_init(&sh); x.get(a,b); while (a>0) { m=a%256; shs256_process(&sh,m); a/=256; } while (b>0) { m=b%256; shs256_process(&sh,m); b/=256; } shs256_hash(&sh,s); return HASH_LEN; }
ECn2 hash_and_map2(char *ID) { int i; ECn2 S; ZZn2 X; Big x0=H1(ID); forever { x0+=1; X.set((ZZn)1,(ZZn)x0); if (!S.set(X)) continue; break; } return S; }
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; }
Big H2(ZZn2 x) { // Hash an Fp2 to a big number sha sh; Big a,u,v; char s[HASH_LEN]; int m; shs_init(&sh); x.get(u,v); a=u; while (a>0) { m=a%256; shs_process(&sh,m); a/=256; } a=v; while (a>0) { m=a%256; shs_process(&sh,m); a/=256; } shs_hash(&sh,s); a=from_binary(HASH_LEN,s); return a; }
ZZn2 get_frobenius_constant() { ZZn2 Fr; Big p=get_modulus(); switch (get_mip()->pmod8) { case 5: Fr.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2 break; case 3: // = (1+sqrt(-1))^(p-1)/2 case 7: // = (1+sqrt(-2))^(p-1)/2 Fr.set((Big)1,(Big)1); default: break; } return pow(Fr,(p-1)/2); }
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 }
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; }
void PFC::hash_and_map(G2& w,char *ID) { int i; ZZn2 X; Big x0=H1(ID); forever { x0+=1; X.set((ZZn)1,(ZZn)x0); if (!w.g.set(X)) continue; break; } map(w.g,*x,*frob); }
ECn2 hash2(char *ID,Big cof2) { ECn2 T; ZZn2 x; Big x0,y0=0; x0=H1(ID); do { x.set(x0,y0); x0+=1; } while (!is_on_curve(x)); T.set(x); T*=cof2; return T; }
// set Frobenius constant - depends on embedding degree void set_frobenius_constant(ZZn2 &X, int ed) { Big p=get_modulus(); switch (get_mip()->pmod8) { case 5: X.set((Big)0,(Big)1); // = (sqrt(-2)^(p-1)/2 break; case 3: // = (1+sqrt(-1))^(p-1)/2 X.set((Big)1,(Big)1); break; case 7: X.set((Big)2,(Big)1); // = (2+sqrt(-1))^(p-1)/2 default: break; } if (ed==12) X=pow(X,(p-1)/6); if (ed==24) X=pow(X,(p-7)/12); if (ed==48) X=pow(X,(p-19)/24); }
void PFC::random(G2& w) { int i; ZZn2 X; Big x0; if (RNG==NULL) x0=rand(*mod); else x0=strong_rand(RNG, *mod); forever { x0+=1; X.set((ZZn)1,(ZZn)x0); if (!w.g.set(X)) continue; break; } map(w.g,*x,*frob); }
ECn2 hash2(char *ID) { ECn2 T; ZZn2 x; Big x0,y0=0; x0=H1(ID); do { x.set(x0,y0); x0+=1; } while (!is_on_curve(x)); T.set(x); // cout << "T= " << T << endl; return T; }
void set_frobenius_constant(ZZn2 &X) { Big p=get_modulus(); switch (get_mip()->pmod8) { case 5: X.set((Big)0,(Big)1); // = (sqrt(sqrt(-2))^(p-1)/4 X=pow(X,(p-1)/4); break; case 3: X.set((Big)1,(Big)1); X=pow(X,(p-3)/4); break; case 7: X.set((Big)2,(Big)1); X=pow(X,(p-3)/4); // note that 4 does not divide p-1, so this is the best we can do... default: break; } }
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; }
ECn2 hash_and_map2(char *ID) { int i; ECn2 S; ZZn2 X; Big x0=H1(ID); forever { x0+=1; X.set((ZZn)0,(ZZn)x0); //cout << "X= " << X << endl; if (!S.set(X)) continue; break; } // cout << "S= " << S << endl; return S; }
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; }
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; }
void PFC::add_to_hash(const GT& x) { ZZn6 u=x.g; ZZn2 v; ZZn l,h; Big a,xx[2]; int i,j,m; u.get(v); v.get(l,h); xx[0]=l; xx[1]=h; for (i=0;i<2;i++) { a=xx[i]; while (a>0) { m=a%256; shs_process(&SH,m); a/=256; } } }
Big H2(ZZn2 y) { // Hash and compress an Fp2 to a big number sha256 sh; Big a,h; char s[HASH_LEN]; int m; shs256_init(&sh); y.get(a); while (a>0) { m=a%256; shs256_process(&sh,m); a/=256; } shs256_hash(&sh,s); h=from_binary(HASH_LEN,s); return h; }
int ZZn2Tochar (ZZn2 &z, char *c, int s) { int len = 0; int totlen = 2*sizeof(int); Big a,b; z.get (a, b); s -= sizeof (int); c += sizeof (int); if (a.iszero()) { len = 0; } else { len = to_binary(a, s, c, FALSE); } if (len < 0) return -1; *(c - sizeof(int)); memcpy ((char *)(c - sizeof (int)), (void *)&len, sizeof (int)); totlen += len; s -= len; c += len; s -= sizeof (int); c += sizeof (int); if (b.iszero()) { len = 0; } else { len = to_binary(b, s, c, FALSE); } if (len < 0) return -1; memcpy ((char *)(c - sizeof (int)), (void *)&len, sizeof (int)); totlen += len; return totlen; }
ZZn real(const ZZn2 &x) { ZZn r; x.get(r); return r; }
ZZn imaginary(const ZZn2 &x) { ZZn r,i; x.get(r,i); return i; }
BOOL fast_tate_pairing(ECn& P,ZZn2& Qx,ZZn& Qy,Big& q,ZZn2& res) { int i; Big p; ECn A; ZZn2 ha,had; #ifndef SIMPLE Big q3; ECn P2,t[11]; ZZn2 hc,hcd,z2n,z2d,zn[11],zd[11]; #endif ha=had=1; #ifdef SIMPLE // q.P = 2^17*(2^142.P +P) + P A=P; // reset A for (i=0;i<142;i++) { ha*=ha; had*=had; g(A,A,Qx,Qy,ha,had,ADD,FALSE); // 16 ZZn muls + 1 inverse if (ha==0 || had==0) return FALSE; } // 30 ZZn muls (Projective) g(A,P,Qx,Qy,ha,had,ADD,FALSE); // 11 ZZn muls + 1 inverse if (ha==0 || had==0) return FALSE; // 34 ZZn muls (Projective) for (i=0;i<17;i++) { ha*=ha; had*=had; g(A,A,Qx,Qy,ha,had,ADD,FALSE); // 16 ZZn muls + 1 inverse if (ha==0 || had==0) return FALSE; } // 30 ZZn muls (Projective) g(A,P,Qx,Qy,ha,had,ADD,FALSE); // 11 ZZn muls + 1 inverse if (ha==0 || had==0) return FALSE; // 34 ZZn muls (Projective) #else q3=q*3; zn[0]=zd[0]=1; t[0]=P2=A=P; g(P2,P2,Qx,Qy,z2n,z2d,ADD,TRUE); // P2=P+P // // Build NAF windowing table // for (i=1;i<11;i++) { // 17 ZZn muls + 1 inverse (Affine) g(A,P2,Qx,Qy,hc,hcd,ADD,TRUE); // 40 ZZn muls (Projective) t[i]=A; // precalculate t[i] = (2i+1).P zn[i]=z2n*zn[i-1]*hc; zd[i]=z2d*zd[i-1]*hcd; } A=P; // reset A /* Left to right method */ nb=bits(q3); for (i=nb-2;i>=1;i-=(nbw+nzs)) { n=naf_window(q,q3,i,&nbw,&nzs); // standard MIRACL NAF windowing for (j=0;j<nbw;j++) { ha*=ha; had*=had; g(A,A,Qx,Qy,ha,had,ADD,FALSE); // 16 ZZn muls + 1 inverse } // 30 ZZn muls (Projective) if (n>0) { ha*= zn[n/2]; had*=zd[n/2]; g(A,t[n/2],Qx,Qy,ha,had,ADD,FALSE); // 17 ZZn muls + 1 inverse } // 40 ZZn muls (Projective) if (n<0) { n=(-n); ha*=zd[n/2]; had*=zn[n/2]; g(A,t[n/2],Qx,Qy,ha,had,SUB,FALSE); // 17 ZZn muls + 1 inverse } // 40 ZZn muls (Projective) for (j=0;j<nzs;j++) { ha*=ha; had*=had; g(A,A,Qx,Qy,ha,had,ADD,FALSE); // 16 ZZn muls + 1 inversion } // 30 ZZn muls (Projective) if (ha==0 || had==0) return FALSE; } #endif if (!A.iszero()) return FALSE; res=(ha/had); 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; }
int main() { ofstream common("common.ibe"); ofstream master("master.ibe"); ECn P,Ppub; ZZn2 cube; Big s,p,q,t,n,cof,x,y; long seed; miracl *mip=&precision; cout << "Enter 9 digit random number seed = "; cin >> seed; irand(seed); // SET-UP #ifdef SIMPLE q=pow((Big)2,159)+pow((Big)2,17)+1; #else // generate random q forever { n=rand(QBITS-1,2); // 159 bit number, base 2 q=2*n+1; // 160 bit while (!prime(q)) q+=2; if (bits(q)>QBITS) continue; break; } #endif cout << "q= " << q << endl; // generate p t=(pow((Big)2,PBITS)-1)/(2*q); s=(pow((Big)2,PBITS-1)-1)/(2*q); forever { n=rand(t); if (n<s) continue; p=2*n*q-1; if (p%12!=11) continue; // must be 2 mod 3, also 3 mod 4 if (prime(p)) break; } cout << "p= " << p << endl; cof=2*n; ecurve(0,1,p,MR_PROJECTIVE); // elliptic curve y^2=x^3+1 mod p // // Find suitable cube root of unity (solution in Fp2 of x^3=1 mod p) // forever { // cube=pow(randn2(),(p+1)*(p-1)/3); cube=pow(randn2(),(p+1)/3); cube=pow(cube,p-1); if (!cube.isunity()) break; } cout << "Cube root of unity= " << cube << endl; if (!(cube*cube*cube).isunity()) { cout << "sanity check failed" << endl; exit(0); } // // Choosing an arbitrary P .... // forever { while (!P.set(randn())) ; P*=cof; if (!P.iszero()) break; } cout << "Point P= " << P << endl; // // Pick a random master key s // s=rand(q); Ppub=s*P; cout << "Secret s= " << s << endl; cout << "Point Ppub= " << Ppub << endl; common << PBITS << endl; mip->IOBASE=16; common << p << endl; common << q << endl; P.get(x,y); common << x << endl; common << y << endl; Ppub.get(x,y); common << x << endl; common << y << endl; cube.get(x,y); common << x << endl; common << y << endl; master << s << endl; return 0; }