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;         
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);

}
Beispiel #6
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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  
}
Beispiel #10
0
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;
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
}
Beispiel #14
0
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);
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
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;
}
Beispiel #21
0
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;
	}
Beispiel #23
0
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;
}
Beispiel #24
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;
}
Beispiel #25
0
void extract(ECn& A,ZZn& x,ZZn& y)
{ // (x,y) <- A
    x=(A.get_point())->X;
    y=(A.get_point())->Y;
}
Beispiel #26
0
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;            
}
Beispiel #27
0
void extract(ECn& A,ZZn& x,ZZn& y)
{ 
    x=(A.get_point())->X;
    y=(A.get_point())->Y;
}
Beispiel #28
0
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;
}