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; }
ZZn6 g(ECn& A,ECn& B,ECn& C,ECn& D,ZZn3& Qx,ZZn3& Qy,ZZn3& Sx,ZZn3& Sy) { ZZn6 u; ZZn lam; big ptr; ECn P; P=A; ptr=A.add(B); if (ptr==NULL) return (ZZn6)1; lam=ptr; u=line(P,A,lam,Qx,Qy); P=C; ptr=C.add(D); if (ptr==NULL) return (ZZn6)1; lam=ptr; return u*line(P,C,lam,Sx,Sy); }
ZZn6 g(ECn& A,ECn& B,ECn& C,ECn& D,ZZn3& Qx,ZZn3& Qy,ZZn3& Sx,ZZn3& Sy) { ZZn6 u; int type; ZZn lam; big ptr; ECn P; P=A; type=A.add(B,&ptr); if (!type) return (ZZn6)1; lam=ptr; u=line(P,A,lam,Qx,Qy); P=C; type=C.add(D,&ptr); if (!type) return (ZZn6)1; lam=ptr; return u*line(P,C,lam,Sx,Sy); }
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 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 BaseOT::PointToByteArray(BYTE* pBufIdx, int field_size, ECn &point) { int itmp; Big bigtmp; //compress to x-point and y-bit and convert to byte array itmp = point.get(bigtmp); //first store the y-bit pBufIdx[0] = (BYTE) (itmp & 0x01); //then store the x-coordinate (sec-param/8 + 4 byte size) big_to_bytes(field_size, bigtmp.getbig(), (char*) pBufIdx+1, true); }
BOOL ecap(ECn& P,ECn& Q,Big& order,ZZn& zeta,Big& cofactor,ZZn& res) { BOOL Ok; Big Qx,Qy; ZZn bQx; Q.get(Qx,Qy); bQx=zeta*zeta*(ZZn)Qx; Ok=fast_tate_pairing(P,(ZZn)Qx,(ZZn)Qy,bQx,order,cofactor,res); if (Ok) return TRUE; return FALSE; }
BOOL ecap(ECn3& P,ECn& Q,Big& x,ZZn &X,ZZn18& r) { BOOL Ok; Big xx,yy; ZZn Qx,Qy; Q.get(xx,yy); Qx=xx; Qy=yy; Ok=fast_pairing(P,Qx,Qy,x,X,r); if (Ok) return TRUE; return FALSE; }
void g(ECn& A,ECn& B,ZZn2& Qx,ZZn& Qy,ZZn2& num,ZZn2& denom,int as,BOOL first) { ZZn lam,mQy; ZZn2 d,u; big ptr; ECn P=A; if (as==ADD) { // Evaluate line from A, and then evaluate vertical through destination ptr=A.add(B); if (ptr==NULL) { num=0; return; } else lam=ptr; if (A.iszero()) { u=vertical(P,Qx); d=1; } else { u=line(P,A,lam,Qx,Qy); d=vertical(A,Qx); } } else // as==SUB { // Evaluate Vertical at A, and then line from A to destination // (Note swap num and denom, Qy=-Qy, process lines "backwards") u=vertical(A,Qx); ptr=A.sub(B); if (ptr==NULL) { num=0; return; } else lam=ptr; if (A.iszero()) { d=u; } else { mQy=-Qy; d=line(P,A,lam,Qx,mQy); } } if (first) {num= u; denom= d; } else {num*=u; denom*=d; } // 6 ZZn muls }
ZZn8 g(ECn& A,ECn& B,ZZn4& Qx,ZZn4& Qy) { int type; ZZn lam; big ptr; ECn P=A; // Evaluate line from A type=A.add(B,&ptr); if (!type) return (ZZn8)1; lam=ptr; return line(P,A,lam,Qx,Qy); }
ECn CvSakke::ecn_from_string( const String& str ) { ECn result; size_t pos = str.find(","); if ( pos == String::npos ) return result; Big x, y; String decoded; CvBase64::Decode( str.substr( 1, pos-1 ), decoded ); x = from_binary( (int)decoded.size(), (char*)decoded.data() ); decoded.clear(); CvBase64::Decode( str.substr( pos+1, BN_BYTES ), decoded ); y = from_binary( (int)decoded.size(), (char*)decoded.data() ); result.set( x, y ); return result; }
ZZn4 g(ECn& A,ECn& B,ZZn2& Qx,ZZn2& Qy) { int type; ZZn lam,extra1,extra2; big ptr,ex1,ex2; ECn P=A; // Evaluate line from A type=A.add(B,&ptr,&ex1,&ex2); if (!type) return (ZZn4)1; lam=ptr; extra1=ex1; extra2=ex2; return line(P,A,B,type,lam,extra1,extra2,Qx,Qy); }
ZZn2 g(ECn& A,ECn& B,ZZn& Px,ZZn& Py) { int type; ZZn lam,extra1,extra2; ZZn2 u; ECn P=A; big ptr,ex1,ex2; type=A.add(B,&ptr,&ex1,&ex2); if (!type) return (ZZn2)1; lam=ptr; extra1=ex1; extra2=ex2; return line(P,A,B,type,lam,extra1,extra2,Px,Py); }
ZZn2 g(ECn& A,ECn& B,ZZn& a,ZZn& d) { int type; ZZn lam,extra1,extra2; ECn P=A; big ptr,ex1,ex2; // Evaluate line from A - lam is line slope type=A.add(B,&ptr,&ex1,&ex2); if (!type) return (ZZn2)1; lam=ptr; // in projective case slope = lam/A.z extra1=ex1; extra2=ex2; return line(P,A,B,type,lam,extra1,extra2,a,d); }
BOOL ecap(ECn2& P,ECn& Q,Big& x,ZZn2 &X,ZZn12& r) { BOOL Ok; Big xx,yy; ZZn Qx,Qy; P.norm(); cout<<"P:"<<P<<endl; Q.get(xx,yy); Qx=xx; Qy=yy; Ok=fast_pairing(P,Qx,Qy,x,X,r); if (Ok) return TRUE; return FALSE; }
BOOL ecap(ECn& P,ECn& Q,Big& order,ZZn2& cube,ZZn2& res) { ZZn2 Qx; ZZn Qy,iy; Big xx,yy; Q.get(xx,yy); Qx=(ZZn)xx*cube; Qy=(ZZn)yy; iy=(ZZn)1/(Qy+1); Qx=-2*Qx*iy; Qy=(Qy-3)*iy; // Q+=(0,1) if (fast_tate_pairing(P,Qx,Qy,order,res)) return TRUE; return FALSE; }
int ECnTochar (ECn &e, char *c, int s) { Big x, y; e.get(x, y); int len = 0; int totlen = sizeof (int)*2; // cout << "Entering ECnTochar" << endl; // format: 4 bytes length, followed by the big if (s <= sizeof (int)) return -1; // Code assumes epoint contains either nulls or bigs > 0 s -= sizeof (int); c += sizeof (int); if (x.iszero()) { len = 0; } else { len = to_binary (x, s, c, FALSE); } if (len < 0) { return -1; } memcpy ((char *)(c - sizeof(int)), (void *)&len, sizeof (int)); totlen += len; s -= len; c += len; // cout << "Len1 " << len << " x " << x; if (s <= sizeof (int)) return -1; s -= sizeof (int); c += sizeof (int); len = to_binary (y, s, c, FALSE); if (len < 0) return -1; memcpy ((char *)(c - sizeof(int)), (void *)&len, sizeof (int)); totlen += len; // cout << "Len2 " << len << " y " << y; return totlen; }
BOOL ecap(ECn& P,ECn& Q,Big& order,ZZn2& cube,ZZn2& res) { ZZn2 Qx,Qy; Big xx,yy; #ifdef SCOTT ZZn a,b,x,y,ib,w,t1,y2,ib2; #else ZZn2 lambda,ox; #endif Q.get(xx,yy); Qx=(ZZn)xx*cube; Qy=(ZZn)yy; #ifndef SCOTT // point doubling lambda=(3*Qx*Qx)/(Qy+Qy); ox=Qx; Qx=lambda*lambda-(Qx+Qx); Qy=lambda*(ox-Qx)-Qy; #else // explicit point subtraction Qx.get(a,b); y=yy; ib=(ZZn)1/b; t1=a*b*b; y2=y*y; ib2=ib*ib; w=y2+2*t1; x=-w*ib2; y=-y*(w+t1)*(ib2*ib); Qx.set(x); Qy.set((ZZn)0,y); #endif if (fast_tate_pairing(P,Qx,Qy,order,res)) return TRUE; return FALSE; }
extern "C" int schoof_main(int argc,char **argv) { ofstream ofile; int low,lower,ip,pbits,lp,i,j,jj,m,n,nl,L,k,tau,lambda; mr_utype t[100]; Big a,b,p,nrp,x,y,d,s; PolyMod XX,XP,YP,XPP,YPP; PolyMod Pf[100],P2f[100],P3f[100]; Poly G,P[100],P2[100],P3[100],Y2,Y4,Fl; miracl *mip=&precision; BOOL escape,search,fout,dir,gotP,gotA,gotB,eigen,anomalous; BOOL permisso[100]; ZZn delta,j_invariant; ZZn EB,EA,T,T1,T3,A2,A4,AZ,AW; int Base; argv++; argc--; if (argc<1) { cout << "Incorrect Usage" << endl; cout << "Program finds the number of points (NP) on an Elliptic curve" << endl; cout << "which is defined over the Galois field GF(P), P a prime" << endl; cout << "The Elliptic Curve has the equation Y^2 = X^3 + AX + B mod P" << endl; cout << "(Or use flag -E for Inverted Edwards coordinates X^2+AY^2=X^2.Y^2+B mod P)" << endl; cout << "schoof <prime number P> <A> <B>" << endl; cout << "OR" << endl; cout << "schoof -f <formula for P> <A> <B>" << endl; #if defined(unix) cout << "e.g. schoof -f 2^192-2^64-1 -3 35317045537" << endl; #else cout << "e.g. schoof -f 2#192-2#64-1 -3 35317045537" << endl; #endif cout << "To output to a file, use flag -o <filename>" << endl; cout << "To search downwards for a prime, use flag -d" << endl; cout << "To input P, A and B in Hex, precede with -h" << endl; cout << "To search for NP prime incrementing B, use flag -s" << endl; cout << "(For Edwards curve the search is for NP=4*prime)" << endl; cout << "\nFreeware from Certivox, Dublin, Ireland" << endl; cout << "Full C++ source code and MIRACL multiprecision library available" << endl; cout << "Also faster Schoof-Elkies-Atkin implementation" << endl; cout << "email [email protected]" << endl; return 0; } ip=0; gprime(10000); // generate small primes < 1000 search=fout=dir=gotP=gotA=gotB=FALSE; p=0; a=0; b=0; // Interpret command line Base=10; while (ip<argc) { if (strcmp(argv[ip],"-f")==0) { ip++; if (!gotP && ip<argc) { ss=argv[ip++]; tt=0; eval(); p=tt; gotP=TRUE; continue; } else { cout << "Error in command line" << endl; return 0; } } if (strcmp(argv[ip],"-o")==0) { ip++; if (ip<argc) { fout=TRUE; ofile.open(argv[ip++]); continue; } else { cout << "Error in command line" << endl; return 0; } } if (strcmp(argv[ip],"-d")==0) { ip++; dir=TRUE; continue; } if (strcmp(argv[ip],"-E")==0) { ip++; Edwards=TRUE; continue; } if (strcmp(argv[ip],"-s")==0) { ip++; search=TRUE; continue; } if (strcmp(argv[ip],"-h")==0) { ip++; Base=16; continue; } if (!gotP) { mip->IOBASE=Base; p=argv[ip++]; mip->IOBASE=10; gotP=TRUE; continue; } if (!gotA) { mip->IOBASE=Base; a=argv[ip++]; mip->IOBASE=10; gotA=TRUE; continue; } if (!gotB) { mip->IOBASE=Base; b=argv[ip++]; mip->IOBASE=10; gotB=TRUE; continue; } cout << "Error in command line" << endl; return 0; } if (!gotP || !gotA || !gotB) { cout << "Error in command line" << endl; return 0; } if (!prime(p)) { int incr=0; cout << "That number is not prime!" << endl; if (dir) { cout << "Looking for next lower prime" << endl; p-=1; incr++; while (!prime(p)) { p-=1; incr++; } cout << "Prime P = P-" << incr << endl; } else { cout << "Looking for next higher prime" << endl; p+=1; incr++; while (!prime(p)) { p+=1; incr++; } cout << "Prime P = P+" << incr << endl; } cout << "Prime P = " << p << endl; } pbits=bits(p); cout << "P mod 24 = " << p%24 << endl; cout << "P is " << pbits << " bits long" << endl; // loop for "-s" search option forever { fft_reset(); // reset FFT tables if (Edwards) { modulo(p); EB=b; EA=a; AZ=(ZZn)1/(EA-EB); A2=2*(EA+EB)/(EA-EB); A4=1; AW=1; AW*=AZ; A2*=AZ; A4*=AZ; A4*=AW; T=4*A2; T1=3*T; T3=18*36*(2*A4); A=T3-3*T1*T1; B=-T1*T3+2*T1*T1*T1; ecurve((Big)A,(Big)B,p,MR_AFFINE); // initialise Elliptic Curve } else { ecurve(a,b,p,MR_AFFINE); // initialise Elliptic Curve A=a; B=b; } // The elliptic curve as a Polynomial Y2=0; Y2.addterm(B,0); Y2.addterm(A,1); Y2.addterm((ZZn)1,3); Y4=Y2*Y2; cout << "Counting the number of points (NP) on the curve" << endl; if (Edwards) { cout << "X^2+" << EA << "*Y^2=X^2*Y^2+" << EB << endl; cout << "Equivalent to Weierstrass form" << endl; } cout << "y^2= " << Y2 << " mod " << p << endl; delta=-16*(4*A*A*A+27*B*B); if (delta==0) { cout << "Not Allowed! 4A^3+27B^2 = 0" << endl; if (search) {b+=1; continue; } else return 0; } anomalous=FALSE; j_invariant=(-1728*64*A*A*A)/delta; cout << "j-invariant= " << j_invariant << endl; if (j_invariant==0 || j_invariant==1728) { anomalous=TRUE; cout << "Warning: j-invariant is " << j_invariant << endl; } if (pbits<14) { // do it the simple way nrp=1; x=0; while (x<p) { nrp+=1+jacobi((x*x*x+(Big)A*x+(Big)B)%p,p); x+=1; } if (Edwards) { cout << "NP/4= " << nrp/4 << endl; if (prime(nrp/4)) cout << "NP/4 is Prime!" << endl; else if (search) {b+=1; continue; } } else { cout << "NP= " << nrp << endl; if (prime(nrp)) cout << "NP is Prime!" << endl; else if (search) {b+=1; continue; } } break; } if (pbits<56) { // do it with kangaroos nrp=kangaroo(p,(Big)0,(Big)1); if (Edwards) { if (!prime(nrp/4) && search) {b+=1; continue; } } else { if (!prime(nrp) && search) {b+=1; continue; } } break; } if (pbits<=100) d=pow((Big)2,48); if (pbits>100 && pbits<=120) d=pow((Big)2,56); if (pbits>120 && pbits<=140) d=pow((Big)2,64); if (pbits>140 && pbits<=200) d=pow((Big)2,72); if (pbits>200) d=pow((Big)2,80); /* if (pbits<200) d=pow((Big)2,72); else d=pow((Big)2,80); */ d=sqrt(p/d); if (d<256) d=256; mr_utype l[100]; int pp[100]; // primes and powers // see how many primes will be needed // l[.] is the prime, pp[.] is the power for (s=1,nl=0;s<=d;nl++) { int tp=mip->PRIMES[nl]; pp[nl]=1; // every prime included once... s*=tp; for (i=0;i<nl;i++) { // if a new prime power is now in range, include its contribution int cp=mip->PRIMES[i]; int p=qpow(cp,pp[i]+1); if (p<tp) { // new largest prime power s*=cp; pp[i]++; } } } L=mip->PRIMES[nl-1]; cout << nl << " primes used (plus largest prime powers), largest is " << L << endl; for (i=0;i<nl;i++) l[i]=mip->PRIMES[i]; int start_prime; // start of primes & largest prime powers for (i=0;;i++) { if (pp[i]!=1) { mr_utype p=qpow(l[i],pp[i]); for (j=0;l[j]<p;j++) ; nl++; for (m=nl-1;m>j;m--) l[m]=l[m-1]; l[j]=p; // insert largest prime power in table } else { start_prime=i; break; } } // table of primes and prime powers now looks like:- // 2 3 5 7 9 11 13 16 17 19 .... // S p p // where S is start_prime, and p marks the largest prime powers in the range // CRT uses primes starting from S, but small primes are kept in anyway, // as they allow quick abort if searching for prime NP. // Calculate Divisor Polynomials - Schoof 1985 p.485 // Set the first few by hand.... P[1]=1; P[2]=2; P[3]=0; P[4]=0; P2[1]=1; P3[1]=1; P2[2]=P[2]*P[2]; P3[2]=P2[2]*P[2]; P[3].addterm(-(A*A),0); P[3].addterm(12*B,1); P[3].addterm(6*A,2) ; P[3].addterm((ZZn)3,4); P2[3]=P[3]*P[3]; P3[3]=P2[3]*P[3]; P[4].addterm((ZZn)(-4)*(8*B*B+A*A*A),0); P[4].addterm((ZZn)(-16)*(A*B),1); P[4].addterm((ZZn)(-20)*(A*A),2); P[4].addterm((ZZn)80*B,3); P[4].addterm((ZZn)20*A,4); P[4].addterm((ZZn)4,6); P2[4]=P[4]*P[4]; P3[4]=P2[4]*P[4]; lower=5; // next one to be calculated // Finding the order modulo 2 // If GCD(X^P-X,X^3+AX+B) == 1 , trace=1 mod 2, else trace=0 mod 2 XX=0; XX.addterm((ZZn)1,1); setmod(Y2); XP=pow(XX,p); G=gcd(XP-XX); t[0]=0; if (isone(G)) t[0]=1; cout << "NP mod 2 = " << (p+1-(int)t[0])%2; if ((p+1-(int)t[0])%2==0) { cout << " ***" << endl; if (search && !Edwards) {b+=1; continue; } } else cout << endl; PolyMod one,XT,YT,ZT,XL,YL,ZL,ZL2,ZT2,ZT3; one=1; // polynomial = 1 Crt CRT(nl-start_prime,&l[start_prime]); // initialise for application of the // chinese remainder thereom // now look for trace%prime for prime=3,5,7,11 etc // actual trace is found by combining these via CRT escape=FALSE; for (i=1;i<nl;i++) { lp=l[i]; // next prime k=p%lp; // generation of Divisor polynomials as needed // See Schoof p. 485 for (j=lower;j<=lp+1;j++) { // different for even and odd if (j%2==1) { n=(j-1)/2; if (n%2==0) P[j]=P[n+2]*P3[n]*Y4-P3[n+1]*P[n-1]; else P[j]=P[n+2]*P3[n]-Y4*P3[n+1]*P[n-1]; } else { n=j/2; P[j]=P[n]*(P[n+2]*P2[n-1]-P[n-2]*P2[n+1])/(ZZn)2; } if (j <= 1+(L+1)/2) { // precalculate for later P2[j]=P[j]*P[j]; P3[j]=P2[j]*P[j]; } } if (lp+2>lower) lower=lp+2; for (tau=0;tau<=lp/2;tau++) permisso[tau]=TRUE; setmod(P[lp]); MY2=Y2; MY4=Y4; // These next are time-consuming calculations of X^P, Y^P, X^(P*P) and Y^(P*P) cout << "X^P " << flush; XP=pow(XX,p); // Eigenvalue search - see Menezes // Batch the GCDs as they are slow. // This gives us product of both eigenvalues - a polynomial of degree (lp-1) // But thats a lot better than (lp^2-1)/2 eigen=FALSE; if (!anomalous && prime((Big)lp)) { PolyMod Xcoord,batch; batch=1; cout << "\b\b\b\bGCD " << flush; for (tau=1;tau<=(lp-1)/2;tau++) { if (tau%2==0) Xcoord=(XP-XX)*P2[tau]*MY2+(PolyMod)P[tau-1]*P[tau+1]; else Xcoord=(XP-XX)*P2[tau]+(PolyMod)P[tau-1]*P[tau+1]*MY2; batch*=Xcoord; } Fl=gcd(batch); // just one GCD! if (degree(Fl)==(lp-1)) eigen=TRUE; } if (eigen) { setmod(Fl); MY2=Y2; MY4=Y4; // // Only the Y-coordinate is calculated. No need for X^P ! // cout << "\b\b\b\bY^P" << flush; YP=pow(MY2,(p-1)/2); cout << "\b\b\b"; // // Now looking for value of lambda which satisfies // (X^P,Y^P) = lambda.(XX,YY). // // Note that it appears to be sufficient to only compare the Y coordinates (!?) // cout << "NP mod " << lp << " = " << flush; Pf[0]=0; P2f[0]=0; P3f[0]=0; Pf[1]=1; P2f[1]=1; P3f[1]=1; low=2; for (lambda=1;lambda<=(lp-1)/2;lambda++) { int res=0; PolyMod Ry,Ty; tau=(lambda+invers(lambda,lp)*p)%lp; cout << setw(3) << (p+1-tau)%lp << flush; // Get Divisor Polynomials as needed - this time mod the new (small) modulus Fl for (jj=low;jj<=lambda+2;jj++) Pf[jj]=(PolyMod)P[jj]; if (lambda+3>low) low=lambda+3; // compare Y-coordinates - 5 polynomial mod-muls required P2f[lambda+1]=Pf[lambda+1]*Pf[lambda+1]; P3f[lambda]=P2f[lambda]*Pf[lambda]; if (lambda%2==0) { Ry=(Pf[lambda+2]*P2f[lambda-1]-Pf[lambda-2]*P2f[lambda+1])/4; Ty=MY4*YP*P3f[lambda]; } else { if (lambda==1) Ry=(Pf[lambda+2]*P2f[lambda-1]+P2f[lambda+1])/4; else Ry=(Pf[lambda+2]*P2f[lambda-1]-Pf[lambda-2]*P2f[lambda+1])/4; Ty=YP*P3f[lambda]; } if (degree(gcd(Ty-Ry))!=0) res=1; if (degree(gcd(Ty+Ry))!=0) res=2; if (res!=0) { // has it doubled, or become point at infinity? if (res==2) { // it doubled - wrong sign tau=(lp-tau)%lp; cout << "\b\b\b"; cout << setw(3) << (p+1-tau)%lp << flush; } t[i]=tau; if ((p+1-tau)%lp==0) { cout << " ***" << endl; if (search && (!Edwards || lp!=4)) escape=TRUE; } else cout << endl; break; } cout << "\b\b\b"; } for (jj=0;jj<low;jj++) { Pf[jj].clear(); P2f[jj].clear(); P3f[jj].clear(); } if (escape) break; continue; } // no eigenvalue found, but some tau values can be eliminated... if (!anomalous && prime((Big)lp)) { if (degree(Fl)==0) { for (tau=0;tau<=lp/2;tau++) { jj=(lp+tau*tau-(4*p)%lp)%lp; if (jac(jj,lp)!=(-1)) permisso[tau]=FALSE; } } else { // Fl==P[lp] so tau=+/- sqrt(p) mod lp jj=(int)(2*sqrmp((p%lp),lp))%lp; for (tau=0;tau<=lp/2;tau++) permisso[tau]=FALSE; if (jj<=lp/2) permisso[jj]=TRUE; else permisso[lp-jj]=TRUE; } } if (!prime((Big)lp)) { // prime power for (jj=0;jj<start_prime;jj++) if (lp%(int)l[jj]==0) { for (tau=0;tau<=lp/2;tau++) { permisso[tau]=FALSE; if (tau%(int)l[jj]==(int)t[jj]) permisso[tau]=TRUE; if ((lp-tau)%(int)l[jj]==(int)t[jj]) permisso[tau]=TRUE; } break; } } cout << "\b\b\b\bY^P " << flush; YP=pow(MY2,(p-1)/2); cout << "\b\b\b\bX^PP" << flush; if (lp<40) XPP=compose(XP,XP); // This is faster! else XPP=pow(XP,p); cout << "\b\b\b\bY^PP" << flush; if (lp<40) YPP=YP*compose(YP,XP); // This is faster! else YPP=pow(YP,p+1); cout << "\b\b\b\b"; PolyMod Pk,P2k,PkP1,PkM1,PkP2; Pk=P[k]; PkP1=P[k+1]; PkM1=P[k-1]; PkP2=P[k+2]; P2k=(Pk*Pk); // // This is Schoof's algorithm, stripped to its bare essentials // // Now looking for the value of tau which satisfies // (X^PP,Y^PP) + k.(X,Y) = tau.(X^P,Y^P) // // Note that (X,Y) are rational polynomial expressions for points on // an elliptic curve, so "+" means elliptic curve point addition // // k.(X,Y) can be found directly from Divisor polynomials // Schoof Prop (2.2) // // Points are converted to projective (X,Y,Z) form // This is faster (x2). Observe that (X/Z^2,Y/Z^3,1) is the same // point in projective co-ordinates as (X,Y,Z) // if (k%2==0) { XT=XX*MY2*P2k-PkM1*PkP1; YT=(PkP2*PkM1*PkM1-P[k-2]*PkP1*PkP1)/4; XT*=MY2; // fix up, so that Y has implicit y multiplier YT*=MY2; // rather than Z ZT=MY2*Pk; } else { XT=(XX*P2k-MY2*PkM1*PkP1); if (k==1) YT=(PkP2*PkM1*PkM1+PkP1*PkP1)/4; else YT=(PkP2*PkM1*PkM1-P[k-2]*PkP1*PkP1)/4; ZT=Pk; } elliptic_add(XT,YT,ZT,XPP,YPP,one); // // Test for Schoof's case 1 - LHS (XT,YT,ZT) is point at infinity // cout << "NP mod " << lp << " = " << flush; if (iszero(ZT)) { // Is it zero point? (XPP,YPP) = - K(X,Y) t[i]=0; cout << setw(3) << (p+1)%lp; if ((p+1)%lp==0) { cout << " ***" << endl; if (search && (!Edwards || lp!=4)) {escape=TRUE; break;} } else cout << endl; continue; } // try all candidates one after the other PolyMod XP2,XP3,XP4,XP6,YP2,YP4; PolyMod ZT2XP,ZT2YP2,XPYP2,XTYP2,ZT3YP; ZT2=ZT*ZT; ZT3=ZT2*ZT; XP2=XP*XP; XP3=XP*XP2; XP4=XP2*XP2; XP6=XP3*XP3; YP2=MY2*(YP*YP); YP4=YP2*YP2; ZT2XP=ZT2*XP; ZT2YP2=ZT2*YP2; XPYP2=XP*YP2; XTYP2=XT*YP2; ZT3YP=ZT3*YP; Pf[0]=0; Pf[1]=1; Pf[2]=2; P2f[1]=1; P3f[1]=1; P2f[2]=Pf[2]*Pf[2]; P3f[2]=P2f[2]*Pf[2]; Pf[3]=3*XP4+6*A*XP2+12*B*XP-A*A; P2f[3]=Pf[3]*Pf[3]; P3f[3]=P2f[3]*Pf[3]; Pf[4]=(4*XP6+20*A*XP4+80*B*XP3-20*A*A*XP2-16*A*B*XP-32*B*B-4*A*A*A); P2f[4]=Pf[4]*Pf[4]; P3f[4]=P2f[4]*Pf[4]; low=5; for (tau=1;tau<=lp/2;tau++) { int res=0; PolyMod Rx,Tx,Ry,Ty; if (!permisso[tau]) continue; cout << setw(3) << (p+1-tau)%lp << flush; for (jj=low;jj<=tau+2;jj++) { // different for odd and even if (jj%2==1) { /* 3 mod-muls */ n=(jj-1)/2; if (n%2==0) Pf[jj]=Pf[n+2]*P3f[n]*YP4-P3f[n+1]*Pf[n-1]; else Pf[jj]=Pf[n+2]*P3f[n]-YP4*P3f[n+1]*Pf[n-1]; } else { /* 3 mod-muls */ n=jj/2; Pf[jj]=Pf[n]*(Pf[n+2]*P2f[n-1]-Pf[n-2]*P2f[n+1])/(ZZn)2; } P2f[jj]=Pf[jj]*Pf[jj]; // square if (jj<=1+(1+(lp/2))/2) P3f[jj]=P2f[jj]*Pf[jj]; // cube } if (tau+3>low) low=tau+3; if (tau%2==0) { // 4 mod-muls Rx=ZT2*(XPYP2*P2f[tau]-Pf[tau-1]*Pf[tau+1]); Tx=XTYP2*P2f[tau]; } else { // 4 mod-muls Rx=(ZT2XP*P2f[tau]-ZT2YP2*Pf[tau-1]*Pf[tau+1]); Tx=XT*P2f[tau]; } if (iszero(Rx-Tx)) { // we have a result. Now compare Y's if (tau%2==0) { Ry=ZT3YP*(Pf[tau+2]*P2f[tau-1]-Pf[tau-2]*P2f[tau+1]); Ty=4*YT*YP4*P2f[tau]*Pf[tau]; } else { if (tau==1) Ry=ZT3YP*(Pf[tau+2]*P2f[tau-1]+P2f[tau+1]); else Ry=ZT3YP*(Pf[tau+2]*P2f[tau-1]-Pf[tau-2]*P2f[tau+1]); Ty=4*YT*P2f[tau]*Pf[tau]; } if (iszero(Ry-Ty)) res=1; else res=2; } if (res!=0) { // has it doubled, or become point at infinity? if (res==2) { // it doubled - wrong sign tau=lp-tau; cout << "\b\b\b"; cout << setw(3) << (p+1-tau)%lp << flush; } t[i]=tau; if ((p+1-tau)%lp==0) { cout << " ***" << endl; if (search && (!Edwards || lp!=4)) escape=TRUE; } else cout << endl; break; } cout << "\b\b\b"; } for (jj=0;jj<low;jj++) { Pf[jj].clear(); P2f[jj].clear(); P3f[jj].clear(); } if (escape) break; } Modulus.clear(); for (i=0;i<=L+1;i++) { P[i].clear(); // reclaim space P2[i].clear(); P3[i].clear(); } if (escape) {b+=1; continue;} Big order,ordermod; ordermod=1; for (i=0;i<nl-start_prime;i++) ordermod*=(int)l[start_prime+i]; order=(p+1-CRT.eval(&t[start_prime]))%ordermod; // get order mod product of primes nrp=kangaroo(p,order,ordermod); if (Edwards) { if (!prime(nrp/4) && search) {b+=1; continue; } else break; } else { if (!prime(nrp) && search) {b+=1; continue; } else break; } } if (fout) { ECn P; ofile << bits(p) << endl; mip->IOBASE=16; ofile << p << endl; ofile << a << endl; ofile << b << endl; // generate a random point on the curve // point will be of prime order for "ideal" curve, otherwise any point if (!Edwards) { do { x=rand(p); } while (!P.set(x,x)); P.get(x,y); ofile << nrp << endl; } else { ZZn X,Y,Z,R,TA,TB,TC,TD,TE; forever { X=randn(); R=(X*X-EB)/(X*X-EA); if (!qr(R))continue; Y=sqrt(R); break; } Z=1; // double point twice (4*P) for (i=0;i<2;i++) { TA = X*X; TB = Y*Y; TC = TA+TB; TD = TA-TB; TE = (X+Y)*(X+Y)-TC; X = TC*TD; Y = TE*(TC-2*EB*Z*Z); Z = TD*TE; } X/=Z; Y/=Z; x=X; y=Y; ofile << nrp/4 << endl; } ofile << x << endl; ofile << y << endl; mip->IOBASE=10; } if (p==nrp) { cout << "WARNING: Curve is anomalous" << endl; return 0; } if (p+1==nrp) { cout << "WARNING: Curve is supersingular" << endl; } // check MOV condition for curves of Cryptographic interest // if (pbits<128) return 0; d=1; for (i=1;i<50;i++) { d=modmult(d,p,nrp); if (d==1) { if (i==1 || prime(nrp)) cout << "WARNING: Curve fails MOV condition - K = " << i << endl; else cout << "WARNING: Curve fails MOV condition - K <= " << i << endl; return 0; } } return 0; }
void force(ZZn& x,ZZn& y,ECn& A) { // A=(x,y) copy(getbig(x),A.get_point()->X); copy(getbig(y),A.get_point()->Y); A.get_point()->marker=MR_EPOINT_NORMALIZED; }
ECn mul(const Big& e1,const ECn& p1,const Big& e2,const ECn& p2) { ECn t; ecurve_mult2(e1.getbig(),p1.get_point(),e2.getbig(),p2.get_point(),t.get_point()); return t; }
int main(int argc, char **argv) { miracl *mip=&precision; Big p,R,B,mc,curve_b,cru,cof,tau[9]; Big m,x,y,w,t,c,n,r,a,b,gx,gy,r2modp; Big np,PP,TT,FF; int i,A,curve,bb,chunk,words,mbits,bytes,ip=0; int modtype,curvetype,curve_a,curve_b_i,cof_i,lang=0; ZZn2 X; ECn P; ECn2 Q; ECn4 QQ; ECn8 Q8; ZZn4 XA,YA,AA,BB; ZZn8 X8,Y8; ZZn2 Aa,Ab,Ba,Bb; ZZn2 Xa,Ya; ZZn zcru; char pre0[50],pre1[50],pre2[50],pre3[50],pre4[50],pre5[50],pre6[50]; char post0[50],post1[50],post2[50],post3[50],post4[50],post5[50],post6[50]; char pre7[50],post7[50],lg[50]; char xxx[20],yyy[20],zzz[20]; char curvename[30],fieldname[30]; argv++; argc--; if (argc<4) { help(); return 0; } strcpy(curvename,argv[0]); // curve=atoi(argv[ip++]); for (i=0;;i++) { if (curvename[i]==0) break; curvename[i]=toupper(curvename[i]); } //cout << "curvename= " << curvename << " " << strlen(curvename) << endl; curve=0; ip++; chunk=atoi(argv[ip++]); bb=atoi(argv[ip++]); strcpy(lg,argv[ip]); if (chunk !=16 && chunk!=32 && chunk!=64) {help(); return 0;} if (bb<0 || bb>=chunk) {help(); return 0;} // Specify curve constants if (strcmp(curvename,"ED25519")==0) { // ED25519 curve=1; printf("Curve= ED25519\n"); strcpy(fieldname,"25519"); mbits=255; // bits in modulus words=(1+((mbits-1)/bb)); // words per Big curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=-1; // Curve A parameter cof=8; p=pow((Big)2,mbits)-19; // Modulus r=pow((Big)2,252)+(char *)"27742317777372353535851937790883648493"; // group order mip->IOBASE=16; curve_b=(char *)"52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3"; // curve B parameter gx=(char *)"216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"; // generator point gy=(char *)"6666666666666666666666666666666666666666666666666666666666666658"; } if (strcmp(curvename,"C25519")==0) { curve=2; printf("Curve= C25519\n"); strcpy(fieldname,"25519"); mbits=255; words=(1+((mbits-1)/bb)); curvetype=MONTGOMERY; modtype=PSEUDO_MERSENNE; curve_a=486662; cof=8; p=pow((Big)2,mbits)-19; r=pow((Big)2,252)+(char *)"27742317777372353535851937790883648493"; curve_b=0; mip->IOBASE=16; gx=(char *)"9"; gy=0; } if (strcmp(curvename,"NIST256")==0) { curve=3; printf("Curve= NIST256\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"115792089210356248762697446949407573530086143415290314195533631308867097853951"; r=(char *)"115792089210356248762697446949407573529996955224135760342422259061068512044369"; mip->IOBASE=16; curve_b=(char *)"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"; gx=(char *)"6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"; gy=(char *)"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"; } if (strcmp(curvename,"BRAINPOOL")==0) { curve=4; printf("Curve= BRAINPOOL\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"76884956397045344220809746629001649093037950200943055203735601445031516197751"; mip->IOBASE=16; r=(char *)"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7"; mip->IOBASE=10; curve_b=(char *)"46214326585032579593829631435610129746736367449296220983687490401182983727876"; mip->IOBASE=16; gx=(char *)"a3e8eb3cc1cfe7b7732213b23a656149afa142c47aafbc2b79a191562e1305f4"; gy=(char *)"2d996c823439c56d7f7b22e14644417e69bcb6de39d027001dabe8f35b25c9be"; } if (strcmp(curvename,"ANSSI")==0) { curve=5; printf("Curve= ANSSI\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"109454571331697278617670725030735128145969349647868738157201323556196022393859"; mip->IOBASE=16; r=(char *)"F1FD178C0B3AD58F10126DE8CE42435B53DC67E140D2BF941FFDD459C6D655E1"; mip->IOBASE=10; curve_b=(char *)"107744541122042688792155207242782455150382764043089114141096634497567301547839"; mip->IOBASE=16; gx=(char *)"b6b3d4c356c139eb31183d4749d423958c27d2dcaf98b70164c97a2dd98f5cff"; gy=(char *)"6142e0f7c8b204911f9271f0f3ecef8c2701c307e8e4c9e183115a1554062cfb"; } if (strcmp(curvename,"HIFIVE")==0) { curve=6; printf("Curve= HIFIVE\n"); strcpy(fieldname,curvename); mbits=336; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=8; p=pow((Big)2,336)-3; mip->IOBASE=16; r=(char *)"200000000000000000000000000000000000000000071415FA9850C0BD6B87F93BAA7B2F95973E9FA805"; mip->IOBASE=10; curve_b=(char *)"11111"; mip->IOBASE=16; gx=(char *)"C"; gy=(char *)"C0DC616B56502E18E1C161D007853D1B14B46C3811C7EF435B6DB5D5650CA0365DB12BEC68505FE8632"; } if (strcmp(curvename,"GOLDILOCKS")==0) { curve=7; printf("Curve= GOLDILOCKS\n"); strcpy(fieldname,curvename); mbits=448; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=GENERALISED_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,448)-pow((Big)2,224)-1; r=(p+1-(char *)"28312320572429821613362531907042076847709625476988141958474579766324")/4; mip->IOBASE=10; curve_b=p-39081; mip->IOBASE=16; gx=(char *)"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555"; gy=(char *)"ae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed"; } if (strcmp(curvename,"NIST384")==0) { curve=8; printf("Curve= NIST384\n"); strcpy(fieldname,curvename); mbits=384; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319"; r=p+1-(char *)"1388124618062372383606759648309780106643088307173319169677"; curve_b=(char *)"27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575"; mip->IOBASE=16; gx=(char *)"aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"; gy=(char *)"3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"; } if (strcmp(curvename,"C41417")==0) { curve=9; printf("Curve= C41417\n"); strcpy(fieldname,curvename); mbits=414; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; p=pow((Big)2,mbits)-17; cof=8; r=pow((Big)2,411)-(char *)"33364140863755142520810177694098385178984727200411208589594759"; // Group Order curve_b=(char *)"3617"; mip->IOBASE=16; gx=(char *)"1a334905141443300218c0631c326e5fcd46369f44c03ec7f57ff35498a4ab4d6d6ba111301a73faa8537c64c4fd3812f3cbc595"; gy=(char *)"22"; } if (strcmp(curvename,"NIST521")==0) { curve=10; printf("Curve= NIST521\n"); strcpy(fieldname,curvename); mbits=521; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=pow((Big)2,mbits)-1; mip->IOBASE=16; r=(char *)"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; // Group Order curve_b=(char *)"51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"; gx=(char *)"C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"; gy=(char *)"11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; } if (strcmp(curvename,"NUMS256W")==0) { curve=11; printf("Curve= NUMS256W\n"); strcpy(fieldname,"256PMW"); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=PSEUDO_MERSENNE; curve_a=-3; cof=1; p=pow((Big)2,mbits)-189; mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE43C8275EA265C6020AB20294751A825"; // Group Order curve_b=(char *)"25581"; gx=(char *)"BC9ED6B65AAADB61297A95A04F42CB0983579B0903D4C73ABC52EE1EB21AACB1"; gy=(char *)"D08FC0F13399B6A673448BF77E04E035C955C3D115310FBB80B5B9CB2184DE9F"; } if (strcmp(curvename,"NUMS256E")==0) { curve=12; printf("Curve= NUMS256E\n"); strcpy(fieldname,"256PME"); mbits=256; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,mbits)-189; mip->IOBASE=16; r=(char *)"4000000000000000000000000000000041955AA52F59439B1A47B190EEDD4AF5"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC355"; gx=(char *)"8A7514FB6AEA237DCD1E3D5F69209BD60C398A0EE3083586A0DEC0902EED13DA"; gy=(char *)"44D53E9FD9D925C7CE9665D9A64B8010715F61D810856ED32FA616E7798A89E6"; } if (strcmp(curvename,"NUMS384W")==0) { curve=13; printf("Curve= NUMS384W\n"); strcpy(fieldname,"384PM"); mbits=384; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=PSEUDO_MERSENNE; curve_a=-3; cof=1; p=pow((Big)2,mbits)-317; mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD61EAF1EEB5D6881BEDA9D3D4C37E27A604D81F67B0E61B9"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77BB"; gx=(char *)"757956F0B16F181C4880CA224105F1A60225C1CDFB81F9F4F3BD291B2A6CC742522EED100F61C47BEB9CBA042098152A"; gy=(char *)"ACDEE368E19B8E38D7E33D300584CF7EB0046977F87F739CB920837D121A837EBCD6B4DBBFF4AD265C74B8EC66180716"; } if (strcmp(curvename,"NUMS384E")==0) { curve=14; printf("Curve= NUMS384E\n"); strcpy(fieldname,"384PM"); mbits=384; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,mbits)-317; mip->IOBASE=16; r=(char *)"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2471A1CB46BE1CF61E4555AAB35C87920B9DCC4E6A3897D"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD19F"; gx=(char *)"61B111FB45A9266CC0B6A2129AE55DB5B30BF446E5BE4C005763FFA8F33163406FF292B16545941350D540E46C206BDE"; gy=(char *)"82983E67B9A6EEB08738B1A423B10DD716AD8274F1425F56830F98F7F645964B0072B0F946EC48DC9D8D03E1F0729392"; } if (strcmp(curvename,"NUMS512W")==0) { curve=15; printf("Curve= NUMS512W\n"); strcpy(fieldname,"512PM"); mbits=512; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=PSEUDO_MERSENNE; curve_a=-3; cof=1; p=pow((Big)2,mbits)-569; mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B3CA4FB94E7831B4FC258ED97D0BDC63B568B36607CD243CE153F390433555D"; // Group Order curve_b=(char *)"1D99B"; gx=(char *)"3AC03447141D0A93DA2B7002A03D3B5298CAD83BB501F6854506E0C25306D9F95021A151076B359E93794286255615831D5D60137D6F5DE2DC8287958CABAE57"; gy=(char *)"943A54CA29AD56B3CE0EEEDC63EBB1004B97DBDEABBCBB8C8F4B260C7BD14F14A28415DA8B0EEDE9C121A840B25A5602CF2B5C1E4CFD0FE923A08760383527A6"; } if (strcmp(curvename,"NUMS512E")==0) { curve=16; printf("Curve= NUMS512E\n"); strcpy(fieldname,"512PM"); mbits=512; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,mbits)-569; mip->IOBASE=16; r=(char *)"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4F0636D2FCF91BA9E3FD8C970B686F52A4605786DEFECFF67468CF51BEED46D"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFECBEF"; gx=(char *)"DF8E316D128DB69C7A18CB7888D3C5332FD1E79F4DC4A38227A17EBE273B81474621C14EEE46730F78BDC992568904AD0FE525427CC4F015C5B9AB2999EC57FE"; gy=(char *)"6D09BFF39D49CA7198B0F577A82A256EE476F726D8259D22A92B6B95909E834120CA53F2E9963562601A06862AECC1FD0266D38A9BF1D01F326DDEC0C1E2F5E1"; } if (strcmp(curvename,"SECP256K1")==0) { // SECP256K1 curve=17; printf("Curve= SECP256K1\n"); strcpy(fieldname,"SECP256K1"); mbits=256; // bits in modulus words=(1+((mbits-1)/bb)); // words per Big curvetype=WEIERSTRASS; /*if (chunk<64)*/ modtype=NOT_SPECIAL; //modtype=PSEUDO_MERSENNE; curve_a=0; // Curve A parameter cof=1; p=pow((Big)2,mbits)-pow((Big)2,32)-977; // Modulus mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"; // group order curve_b=(char *)"7"; // curve B parameter gx=(char *)"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"; // generator point gy=(char *)"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"; } if (strcmp(curvename,"BN254")==0) { curve=18; printf("Curve= BN254\n"); strcpy(fieldname,curvename); mbits=254; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"4080000000000001"; // Fast but not GT_STRONG parameter p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1; // Modulus t=6*x*x+1; r=p+1-t; // Group order curve_b=2; gx=p-1; // generator point in G1 gy=1; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_D; // twist type Xa.set((ZZn)0,(ZZn)-1); Ya.set((ZZn)1,ZZn(0)); Q.set(Xa,Ya); Q=(p-1+t)*Q; // generator point in G2 cru=(18*pow(x,3)-18*x*x+9*x-2); // cube root of unity for GLV method } if (strcmp(curvename,"BN254CX")==0) { curve=19; printf("Curve= BN254CX\n"); strcpy(fieldname,curvename); mbits=254; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"4000000003C012B1"; p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1; t=6*x*x+1; r=p+1-t; curve_b=2; gx=p-1; gy=1; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_D; Xa.set((ZZn)0,(ZZn)-1); Ya.set((ZZn)1,ZZn(0)); Q.set(Xa,Ya); Q=(p-1+t)*Q; // generator point in G2 cru=(18*pow(x,3)-18*x*x+9*x-2); } if (strcmp(curvename,"BLS383")==0) { curve=20; printf("Curve= BLS383\n"); strcpy(fieldname,curvename); mbits=383; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; // x=(char *)"11000001000000040"; x=(char *)"10008000001001200"; // SIGN_OF_X is POSITIVE p=(pow(x,6)-2*pow(x,5)+2*pow(x,3)+x+1)/3; t=x+1; r=pow(x,4)-x*x+1; cof=(p+1-t)/r; // gx=-2; gy=-1; // curve_b=9; gx=1; gy=4; curve_b=15; ecurve((Big)0,curve_b,p,MR_AFFINE); // mip->TWIST=MR_SEXTIC_D; mip->TWIST=MR_SEXTIC_M; P.set(gx,gy); P*=cof; P.get(gx,gy); //cout << "gx= " << gx << endl; //cout << "gy= " << gy << endl; //cout << "y^2= " << (gy*gy)%p << endl; //cout << "x^3+b= " << (gx*gx*gx+15)%p << endl; //while (!Q.set(randn2())) ; // probably not best way to choose this Xa=1; while (!Q.set(Xa)) { Xa=Xa+(ZZn2)1; } TT=t*t-2*p; PP=p*p; FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(-3*FF+TT)/2; // 2 possibilities... Q=(np/r)*Q; zcru=pow((ZZn)2,(p-1)/3); // zcru*=zcru; // right cube root of unity cru=(Big)zcru; } if (strcmp(curvename,"BLS381")==0) { curve=21; printf("Curve= BLS381\n"); strcpy(fieldname,curvename); mbits=381; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"d201000000010000"; // SIGN_OF_X is NEGATIVE p=(pow(x,6)+2*pow(x,5)-2*pow(x,3)-x+1)/3; t=-x+1; r=pow(x,4)-x*x+1; cof=(p+1-t)/r; curve_b=4; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; gx=1; while (!P.set(gx)) { gx=gx+1; } P*=cof; P.get(gx,gy); Xa=1; while (!Q.set(Xa)) { Xa=Xa+(ZZn2)1; } Q.get(Xa,Ya); Ya=-Ya; Q.set(Xa,Ya); TT=t*t-2*p; PP=p*p; FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(-3*FF+TT)/2; // 2 possibilities... Q=(np/r)*Q; zcru=pow((ZZn)2,(p-1)/3); //zcru*=zcru; // right cube root of unity ?? if x>0 do this?? cru=(Big)zcru; } if (strcmp(curvename,"BLS461")==0) { curve=24; printf("Curve= BLS461\n"); strcpy(fieldname,curvename); mbits=461; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"1FFFFFFBFFFE00000000"; // SIGN_OF_X is NEGATIVE p=(pow(x,6)+2*pow(x,5)-2*pow(x,3)-x+1)/3; t=-x+1; r=pow(x,4)-x*x+1; cof=(p+1-t)/r; gx=-2; gy=-1; curve_b=9; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; P.set(gx,gy); P*=cof; P.get(gx,gy); while (!Q.set(randn2())) ; // probably not best way to choose this TT=t*t-2*p; PP=p*p; FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(-3*FF+TT)/2; // 2 possibilities... Q=(np/r)*Q; zcru=pow((ZZn)2,(p-1)/3); //zcru*=zcru; // right cube root of unity cru=(Big)zcru; } if (strcmp(curvename,"FP256BN")==0) { curve=22; printf("Curve= FP256BN\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"6882F5C030B0A801"; // Slow! p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1; t=6*x*x+1; r=p+1-t; curve_b=3; gx=1; gy=2; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; Q.set((ZZn2)1); //while (!Q.set(randn2())) ; Q=(p-1+t)*Q; cru=(18*pow(x,3)-18*x*x+9*x-2); cout << pre1 << toupperit((char *)"CURVE_Cru",lang) << post1; output(chunk,words,cru,m); cout << term << endl; } if (strcmp(curvename,"FP512BN")==0) { curve=23; printf("Curve= FP512BN\n"); strcpy(fieldname,curvename); mbits=512; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"6882F5C030B0F7F010B306BB5E1BD80F"; // Slow! p=36*pow(x,4)+36*pow(x,3)+24*x*x+6*x+1; t=6*x*x+1; r=p+1-t; curve_b=3; gx=1; gy=2; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; Q.set((ZZn2)1); //while (!Q.set(randn2())) ; Q=(p-1+t)*Q; cru=p-(18*pow(x,3)+18*x*x+9*x+2); } if (strcmp(curvename,"BLS24")==0) { curve=25; printf("Curve= BLS24\n"); strcpy(fieldname,curvename); mbits=479; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; // Note - this is GT-Strong curve x=(char *)"100020011FF80"; // SIGN_OF_X is POSITIVE //x=-x; p=(1+x+x*x-pow(x,4)+2*pow(x,5)-pow(x,6)+pow(x,8)-2*pow(x,9)+pow(x,10))/3; t=x+1; r=pow(x,8)-pow(x,4)+1; cof=(p+1-t)/r; //x=-x; gx=5; gy=12; curve_b=19; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; P.set(gx,gy); P*=cof; P.get(gx,gy); Big x0=0; forever { ZZn4 X; ZZn2 t; x0+=1; t.set((ZZn)0,(ZZn)x0); X.set(t,(ZZn2)0); if (!QQ.set(X)) continue; break; } TT=t*t*t*t-4*p*t*t+2*p*p; PP=pow(p,4); FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(3*FF+TT)/2; QQ=(np/r)*QQ; //cout << "QQ= " << QQ << endl; //cout << "2*QQ= " << QQ+QQ << endl; //cout << "3*QQ= " << (QQ+QQ)+QQ << endl; zcru=pow((ZZn)2,(p-1)/3); //zcru*=zcru; // right cube root of unity - not for M-TYPE cru=(Big)zcru; }
int main() { int i,ns; int sign; BOOL ontwist; Big m1,m2,n,p,t,x,cube,y,b,eta,w,cf[4],X,Y; Big PP,TT,FF; miracl*mip=&precision; ECn P; ECn2 Q,T; ZZn2 xi,r; x=pow((Big)2,62)+pow((Big)2,55)-1; // x is this size to get right size for t, p and n // x is low hamming weight mip->IOBASE=16; sign=1; // 1= positive, 2=negative for +/- x solutions ns=1; for (i=0;i<100;i++) { forever { forever { sign=3-sign; // always looking for +ve x solutions. if (sign==1) x+=1; if (sign==1) p=36*pow(x,4)+36*pow(x,3)+24*x*x+6*x+1; else p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1; //cout << "x= " << x << " p%8= " << p%8 << " p%6= " << p%6 << " p%9= " << p%9 << endl; //if (prime(p)) cout << "p is prime" << endl; // Now check congruence conditions if (p%8==1) continue; // if (p%9==1) continue; if (p%8==7 && (p%5==1 || p%5==4)) continue; if (!prime(p)) continue; modulo(p); if (p%8==5) xi.set(0,1); if (p%8==3) xi.set(1,1); if (p%8==7) xi.set(2,1); // make sure its irreducible if (pow(xi,(p*p-1)/2)==1) {/*cout << "Failed - not a square" << endl; */ continue;} if (pow(xi,(p*p-1)/3)==1) {/*cout << "Failed - not a cube" << endl;*/ continue;} // make sure that x^6-c is irreducible t=6*x*x+1; n=p+1-t; if (prime(n)) break; } cf[3]=1; cf[2]=6*x*x+1; cf[1]=36*x*x*x-18*x*x+12*x+1; cf[0]=36*x*x*x-30*x*x+18*x-2; // find number of points on sextic twist.. TT=t*t-2*p; PP=p*p; FF=(4*PP-TT*TT)/3; FF=sqrt(FF); // m1=PP+1-(-3*FF+TT)/2; // 2 possibilities... This is the wrong curve. m2=PP+1-(3*FF+TT)/2; b=1; forever { b+=1; if (b==2) { X=-1; Y=1; } else if (b==3) { X=1; Y=2; } else if (b==8) { X=1; Y=3; } else if (b==15) { X=1; Y=4; } else { do { X=rand(p); Y=sqrt(X*X*X+b,p); } while (Y==0); } ecurve(0,b,p,MR_AFFINE); P.set(X,Y); if ((n*P).iszero()) break; } mip->TWIST=MR_SEXTIC_M; do { r=randn2(); } while (!Q.set(r)); Q*=m2/n; if ((n*Q).iszero()) break; mip->TWIST=MR_SEXTIC_D; do { r=randn2(); } while (!Q.set(r)); Q*=m2/n; if ((n*Q).iszero()) break; cout << "Something Wrong" << endl; exit(0); } // Note that this program only produces BN curves for which y^2=x^3+B/D yields the correct twist // It would be possible to modify to find curves on the other twist y^2=x^3+B*D- but a lot of changes required! cout << "solution " << ns << endl; cout << "irreducible polynomial = X^6 - " << xi << endl; if (sign==1) { cout << "x mod 12 = " << x%12 << endl; cout << "x= +" << x << endl; } else { cout << "x mod 12 = " << 12-(x%12) << endl; cout << "x= -" << x << endl; } cout << "p=" << p << endl; cout << "p mod 72 = " << p%72 << endl; cout << "bits(p)= " << bits(p) << endl; cout << "n=" << n << endl; cout << "t=" << t << endl; cout << "ham(6*x+2)= " << ham(6*x+2) << " (small is better for R-ate pairing)" << endl; cout << "bits(t)= " << bits(t) << endl; cout << "ham(t-1) = " << ham(t-1) << " (small is better for Ate pairing)" << endl; cout << "bits(n)= " << bits(n) << endl; cout << "ham(n-1) = " << ham(n-1) << " (small is better for Tate pairing)" << endl; mip->IOBASE=10; cout << "E(Fp): y^2=x^3+" << b << endl; mip->IOBASE=16; if (mip->TWIST==MR_SEXTIC_M) cout << "Twist type M" << endl; if (mip->TWIST==MR_SEXTIC_D) cout << "Twist type D" << endl; mip->IOBASE=10; cout << "Hard part= " << (p*p*p*p-p*p+1)/n << endl; mip->IOBASE=16; cout << "Point P= " << P << endl; cout << "Point Q= " << Q << endl; T=n*Q; cout << "check - if right twist should be O - n*Q= " << T << endl << endl; ns++; } return 0; }
int main() { miracl *mip=&precision; Big s,x,q,p,t,A,B,cf,X,Y,sru,n,best_s,f; Big T,P,F,m1,m2; ECn W; ECn2 Q; ZZn2 r; mip->IOBASE=16; int i,ns,sign,best_ham=1000; sign=1; // 1= positive, 2=negative for +/- x solutions s="1400000000000000"; ns=1; for (i=0;i<100;i++) { forever { forever { sign=3-sign; // always looking for +ve x solutions. if (sign==1) s+=1; if (sign==1) x=5+30*s; else x=5-30*s; t=(2*pow(x,3) - 11*x + 15)/15; q=(pow(x,4) - 8*pow(x,2) + 25)/450; cf=(5*x*x+10*x+25)/2; n=cf*q; p=cf*q+t-1; // avoids overflow.. if (p%8!=5) continue; // p will be 1 mod 4 if (!prime(q)) continue; if (!prime(p)) continue; break; } T=t*t-2*p; P=p*p; F=(4*P-T*T); F=sqrt(F); m1=P+1-F; // Wrong Curve m2=P+1+F; A=0; B=0; forever { A+=1; do { X=rand(p); Y=sqrt(X*X*X+A*X,p); } while (Y==0); ecurve(A,B,p,MR_AFFINE); W.set(X,Y); W*=cf; if ((q*W).iszero()) break; } mip->TWIST=MR_QUARTIC_M; do { r=randn2(); } while (!Q.set(r)); Q*=(m2/q); if ((q*Q).iszero()) break; mip->TWIST=MR_QUARTIC_D; do { r=randn2(); } while (!Q.set(r)); Q*=(m2/q); if ((q*Q).iszero()) break; cout << "Something wrong!" << endl; exit(0); } cout << "solution " << ns << endl; cout << "irreducible polynomial = X^4 - [0,1]" << endl; if (sign==1) { cout << "s= +" << s << endl; cout << "s%12= " << s%12 << endl; } else { cout << "s= -" << s << endl; cout << "s%12= " << 12-(s%12) << endl; } cout << "x= " << x << " ham(x)= " << ham(x) << endl; cout << "p= " << p << " bits(p)= " << bits(p) << endl; cout << "q= " << q << " bits(q)= " << bits(q) << endl; cout << "n= " << n << endl; cout << "t= " << t << endl; cout << "cf= " << cf << endl; //cout << "W= " << W << endl; cout << "q*W= " << q*W << endl; mip->IOBASE=10; cout << "E(Fp): y^2=x^3+" << A << "x" << endl; mip->IOBASE=16; if (mip->TWIST==MR_QUARTIC_M) cout << "Twist type M" << endl; if (mip->TWIST==MR_QUARTIC_D) cout << "Twist type D" << endl; //cout << "Q= " << Q << endl; Q*=q; cout << "check - if right twist should be O - q*Q= " << Q << endl; if (ham(x)<best_ham) {best_ham=ham(x);best_s=s;} cout << "So far minimum hamming weight of x= " << best_ham << endl; cout << "for seed= " << best_s << endl << endl; ns++; } return 0; }
void extract(ECn& A,ZZn& x,ZZn& y) { // (x,y) <- A x=(A.get_point())->X; y=(A.get_point())->Y; }
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; }
void extract(ECn& A,ZZn& x,ZZn& y) { x=(A.get_point())->X; y=(A.get_point())->Y; }
int main() { miracl *mip=&precision; Big s,x,q,p,t,A,B,cf,X,Y,sru,n,best_s,f,tau[5],TAU; Big T,P,F,m1,m2,m3,m4; BOOL got_one; ECn W; ECn4 Q; ZZn4 XX,YY,r; ZZn2 xi; int i,ns,sign,best_ham=1000; mip->IOBASE=16; s="E000000000000000"; ns=1; forever { s+=1; for (sign=1;sign<=2;sign++) { if (sign==1) x=s; else x=-s; if (x<0 || ham(x)>7) continue; // filter out difficult or poor solutions t=1+x; p=1+x+x*x-pow(x,4)+2*pow(x,5)-pow(x,6)+pow(x,8)-2*pow(x,9)+pow(x,10); q=1-pow(x,4)+pow(x,8); if (p%3!=0) continue; p/=3; if (p%8==1) continue; if (!prime(p)) continue; if (!prime(q)) continue; modulo(p); if (p%8==5) xi.set(0,1); if (p%8==3) xi.set(1,1); if (p%8==7) xi.set(2,1); // make sure its irreducible if (pow(xi,(p*p-1)/2)==1) {/*cout << "Failed - not a square" << endl; */ continue;} if (pow(xi,(p*p-1)/3)==1) {/*cout << "Failed - not a cube" << endl; */ continue;} // make sure that x^6-c is irreducible n=p+1-t; cf=n/q; tau[0]=2; // count points on twist over extension p^4 tau[1]=t; for (i=1;i<4;i++ ) tau[i+1]=t*tau[i]-p*tau[i-1]; P=p*p*p*p; TAU=tau[4]; F=(4*P-TAU*TAU)/3; F=sqrt(F); m2=P+1-(3*F+TAU)/2; // cout << "m2%q= " << m2%q << endl; B=1; // find curve equation forever { B+=1; if (B==2) { X=-1; Y=1; } else if (B==3) { X=1; Y=2; } else if (B==8) { X=1; Y=3; } else if (B==15) { X=1; Y=4; } else { do { X=rand(p); Y=sqrt(X*X*X+B,p); } while (Y==0); } ecurve(0,B,p,MR_AFFINE); W.set(X,Y); W*=cf; if ((q*W).iszero()) break; } mip->TWIST=MR_SEXTIC_M; // is it an M-type twist...? do { r=randn4(); } while (!Q.set(r)); got_one=FALSE; Q*=(m2/q); if ((q*Q).iszero()) got_one=TRUE; // cout << "m1*Q= " << m1*Q << endl; // cout << "m1%q= " << m1%q << endl; else { mip->TWIST=MR_SEXTIC_D; // no, so it must be D-type. do { r=randn4(); } while (!Q.set(r)); Q*=(m2/q); if ((q*Q).iszero()) got_one=TRUE; } if (!got_one) {cout << "Bad twist" << endl; exit(0);} // Huh? if (mip->TWIST==MR_SEXTIC_M) continue; // not interested just now cout << "solution " << ns << endl; cout << "x= " << x << " ham(x)= " << ham(x) << endl; cout << "p= " << p << " bits(p)= " << bits(p) << endl; cout << "q= " << q << " bits(q)= " << bits(q) << endl; cout << "n= " << n << endl; cout << "t= " << t << endl; cout << "cf= " << cf << endl; cout << "W= " << W << endl; cout << "q*W= " << q*W << endl; mip->IOBASE=10; cout << "E(Fp): y^2=x^3+" << B << endl; cout << "(p-1)%24= " << (p-1)%24 << endl; cout << "p%8= " << p%8 << endl; mip->IOBASE=16; if (mip->TWIST==MR_SEXTIC_M) cout << "Twist type M" << endl; if (mip->TWIST==MR_SEXTIC_D) cout << "Twist type D" << endl; Q*=q; cout << "check - if right twist should be O - q*Q= " << Q << endl; if (ham(x)<best_ham) {best_ham=ham(x);best_s=s;} cout << "So far minimum hamming weight of x= " << best_ham << endl; cout << "for seed= " << best_s << endl; cout << endl; ns++; } } return 0; }