KGC_TEST/miracl/source/curve/pairing/freeman.cpp

264 lines
5.4 KiB
C++

/*
* Program to find Freeman pairing-friendly elliptic curves with embedding degree k=10
*
* See http://www.hpl.hp.com/techreports/2005/HPL-2005-155.html
*
* Compile as (for example)
* cl /O2 /GX freeman.cpp big.cpp miracl.lib
*
* Outputs curves to a file freeman.dat
*
* Mike Scott 6/10/2005
*
*/
#include <cstring>
#include <iostream>
#include <fstream>
#include <iomanip>
#include "big.h"
using namespace std;
// Solve the Pell equation
int pell(int max,Big D,Big F,Big& X,Big& Y,Big *SX,Big *SY,BOOL& complete)
{
int i,j,ns;
BOOL SMALLD;
Big A,P,Q,SD,G,B,OG,OB,NG,NB,T;
complete=FALSE;
SMALLD=FALSE;
if (D<F*F) SMALLD=TRUE;
SD=sqrt(D);
if (SD*SD==D) return 0;
P=0; Q=1;
OG=-P;
OB=1;
G=Q;
B=0;
ns=0;
X=Y=0;
for (i=1;;i++)
{
A=(P+SD)/Q;
P=A*Q-P;
Q=(D-P*P)/Q;
NG=A*G+OG; // G is getting bigger all the time....
NB=A*B+OB;
OG=G; OB=B;
G=NG; B=NB;
if (!SMALLD && bits(G)>max) return ns;
// abort - these are only solutions
T=G*G-D*B*B;
if (T == F/4)
{
SX[ns]=2*G; SY[ns]=2*B;
ns++;
}
if (T == F)
{
SX[ns]=G; SY[ns]=B;
ns++;
}
if (i>0 && Q==1) break;
}
if (i%2==1)
for (j=0;j<i;j++)
{
A=(P+SD)/Q;
P=A*Q-P;
Q=(D-P*P)/Q;
NG=A*G+OG;
NB=A*B+OB;
OG=G; OB=B;
G=NG; B=NB;
if (!SMALLD && bits(G)>max) return ns;
T=G*G-D*B*B;
if (T == F/4)
{
SX[ns]=2*G; SY[ns]=2*B;
ns++;
}
if (T == F)
{
SX[ns]=G; SY[ns]=B;
ns++;
}
}
complete=TRUE; // we got to the end....
X=G; Y=B; // minimal solution of x^2-dy^2=1
// can be used to find more solutions....
if (SMALLD)
{ // too small - do it the hard way
Big ylim1,ylim2,R;
ns=0;
if (F<0)
{
ylim1=sqrt(-F/D);
ylim2=sqrt(-F*(X+1)/(2*D));
}
else
{
ylim1=0;
ylim2=sqrt(F*(X-1)/(2*D));
}
// This might take too long...
// Should really implement LMM method here
if (ylim2-ylim1>300)
{
cout << "." << flush;
ylim2=ylim1+300;
}
for (B=ylim1;B<ylim2;B+=1)
{
R=F+D*B*B;
if (R<0) continue;
G=sqrt(R);
if (G*G==R)
{
SX[ns]=G; SY[ns]=B;
ns++;
}
}
}
return ns;
}
void multiply(Big& td,Big& a,Big& b,Big& c,Big& d)
{ // (c+td.d) = (a+td.b)(c+td.d)
Big t;
t=a*c+b*d*td;
d=c*b+a*d;
c=t;
}
BOOL squfree(int d)
{ // check if d is square-free
int i,s;
miracl *mip=get_mip();
for (i=0;;i++)
{
s=mip->PRIMES[i];
if ((d%(s*s))==0) return FALSE;
if ((s*s)>d) break;
}
return TRUE;
}
void results(BOOL fout,ofstream& ofile,int d,Big p,Big cf,Big ord)
{
cout << "*** Found one - p=" << bits(p) << "-bits ord=" << bits(ord) << "-bits" << endl;
cout << "D= " << d << endl;
cout << "p= " << p << endl;
cout << "ord= " << ord << endl;
cout << "cf= " << cf << endl << endl;
if (fout)
{
ofile << "*** Found one: p=" << bits(p) << "-bits ord=" << bits(ord) << "-bits p%8= " << p%8 << endl;
ofile << "D= " << d << endl;
ofile << "p= " << p << endl;
ofile << "ord= " << ord << endl;
ofile << "cf= " << cf << endl;
ofile << "cm " << p << " -D" << d << " -K" << cf << endl << endl;
}
}
int main(int argc,char **argv)
{
ofstream ofile;
int MIN_SECURITY,MAX_SECURITY,MIN_D,MAX_D,MIN_P;
int ip,j,d,d15,m,mm,solutions,mnt,start,N,precision,max;
BOOL fout,complete;
// Defaults
fout=TRUE;
precision=100;
ofile.open("freeman.dat");
miracl *mip=mirsys(precision,0);
Big F,T,M,D,W,K,C,mmax,td,X,Y,x,y,w,xn,yn,t0,u0,p,k,nrp,ord,R;
Big SX[20],SY[20];
start=1;
max=276; // 10+5120/20
gprime(100000);
MAX_D=2000000000; // as far as I can reasonably go....
for (d=start;d<=MAX_D;d++)
{
// D must be square-free
if (d%120!=43 && d%120!=67) continue;
if (!squfree(d)) continue;
td=(Big)d*15;
F=-20;
solutions=pell(max,td,F,t0,u0,SX,SY,complete);
if (!solutions) continue;
for (j=0;j<solutions;j++)
{
X=SX[j];
Y=SY[j];
forever
{
if (4*bits(X)>512) break;
if ((X-5)%15==0)
{
x=(X-5)/15;
p=25*x*x*x*x+25*x*x*x+25*x*x+10*x+3;
if (bits(p)>148)
{
if (prime(p))
{
nrp=25*x*x*x*x+25*x*x*x+15*x*x+5*x+1;
ord=trial_divide(nrp);
if (prime(ord) && bits(ord)>148)
results(fout,ofile,d,p,nrp/ord,ord);
}
}
}
if ((-X-5)%15==0)
{
x=(-X-5)/15;
p=25*x*x*x*x+25*x*x*x+25*x*x+10*x+3;
if (bits(p)>148)
{
if (prime(p))
{
nrp=25*x*x*x*x+25*x*x*x+15*x*x+5*x+1;
ord=trial_divide(nrp);
if (prime(ord) && bits(ord)>148)
results(fout,ofile,d,p,nrp/ord,ord);
}
}
}
if (!complete) break; // no more solutions
multiply(td,t0,u0,X,Y);
}
}
}
return 0;
}