⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cm.cpp

📁 大数运算库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * cm.cpp - Finding an elliptic curve and point of nearly prime order
 * See IEEE 1363 Annex A for documentation!
 *
 * !!! New much improved version - March 2002
 * Now tested for D up to 10^7
 *
 * Note that less precision (one-third) is needed if D is not divisible by 3
 * See Lay & Zimmer "Constructing Elliptic curves with Given Group Order over 
 * Large Finite Fields"
 *
 * Uses functions from the MIRACL multiprecision library, specifically
 * classes:-
 * Flash   - Big floating point (actually floating slash - but looks like 
 *                               floating point)
 * Complex - Big Complex flash
 * Big     - Big integer
 * ZZn     - Big integers mod an integer
 * FPoly   - Big Flash polynomial
 * Poly    - Big ZZn polynomial
 *
 * Written by Mike Scott, Dublin, Ireland. March 1998 
 *
 * Full MIRACL source is available from 
 * ftp.computing.dcu.ie/pub/crypto/miracl.zip
 *
 * MIRACL is a shareware source code product.
 * However it is free for educational and non-profit making use
 * Queries to mike@computing.dcu.ie
 * Web page http://indigo.ie/~mscott
 */

#include <iostream>
#include <fstream>
#include <cmath>
#include <cstring>
#include <elliptic.h>
#include "comflash.h"
#include "fpoly.h"
#include "poly.h"

using namespace std;

miracl *mip;

FPoly T;  // Reduced class Polynomial. 
static char *s;
BOOL fout,suppress;

// F(z) Function A.13.3

Complex Fz(Complex z)
{
    Complex t;
    int sign=1;
    Complex sum=(Flash)1;

    if (z.iszero()) return sum;

    Complex zi=z;
    Complex zj=z*z;
    Complex r=z;
    Complex z3=zj*z;

    forever
    {
        if (zi.iszero() && zj.iszero()) break;   
        t=zi+zj;
        if (sign) sum-=t;
        else      sum+=t;

        r*=z3;        
        zi*=r; zj*=r; zj*=z;

        sign=1-sign;
    }

    return sum;
}

// Fj(A,B,C) function A.13.3

Complex F(int j,Big A,Big B,Big C)
{
    Complex t,theta24,theta,theta2;
    Flash sd;
    Big D=A*C-B*B;
    sd=-sqrt((Flash)D);

    t=Complex(sd*pi()/(24*A),(pi()*B)/(24*A));    
    theta24=exp(t);                                // theta^(1/24)
    theta=pow(theta24,24);                         // theta

    if (j!=2) 
        t=recip(theta24);      // -24th root
    else  
        t=theta24*theta24;     // 12th root

    theta2=theta;
    theta2*=theta2;
    if (j==0) return (t*Fz(-theta)/Fz(theta2));
    if (j==1) return (t*Fz(theta)/Fz(theta2));
    if (j==2) return (sqrt((Flash)2)*t*Fz(theta2*theta2)/Fz(theta2));
    return 0;
}

int geti(Big D)
{
    Big d=D%8;
    if (d==1 || d==2 || d==6 || d==7) return 3;
    if (d==3)
    {
       if (D%3==0) return 2;
       else        return 0;
    } 
    if (d==5) return 6;
    return 0;
}

int getk(Big D)
{
    Big d=D%8;
    if (d==1 || d==2 || d==6) return 2;
    if (d==3 || d==7) return 1;
    if (d==5) return 4;
    return 0; 
}

// A.13.3

void class_poly(Complex& lam,Flash *Fi2,Big A,Big B,Big C,Big D,BOOL conj)
{
    Big ac,l,t;
    int i,j,k,g,e,m,n,dm8,a2,c2;
    Complex cinv;

    g=1;
    if (D%3==0) g=3;

    ac=A*C;
    if (ac%2==1) 
    {
        j=0;
        l=A-C+A*A*C;
    }
    if (C%2==0)  j=1;
    if (A%2==0)  j=2;

    if (A%2==0)
    {
        t=(C*C-1)/8;
        if (t%2==0) m=1;
        else        m=-1;
    }
    else
    {
        t=(A*A-1)/8;
        if (t%2==0) m=1;
        else        m=-1;
    }
    
    dm8=D%8;
    i=geti(D);
    k=getk(D);
    switch (dm8)
    {
    case 1: 
    case 2:    n=m;
               if (C%2==0) l=A+2*C-A*C*C;
               if (A%2==0) l=A-C-A*C*C;
               break;
    case 3:    if (ac%2==1) n=1;
               else         n=-m;
               if (C%2==0) l=A+2*C-A*C*C;
               if (A%2==0) l=A-C+5*A*C*C;
               break;
    case 5:    n=1;
               if (C%2==0) l=A-C+A*A*C;
               if (A%2==0) l=A-C-A*C*C;
               break;
    case 6:    n=m;
               if (C%2==0) l=A+2*C-A*C*C;
               if (A%2==0) l=A-C-A*C*C;
               break;
    case 7:    if (ac%2==0) n=1;
               else         n=m;
               if (C%2==0) l=A+2*C-A*C*C;
               if (A%2==0) l=A-C-A*C*C;
               break;
               
    default: break;
    }

    e=(k*B*l)%48;
    if (e<0) e+=48;
    cinv=pow(lam,e);
    cinv*=(n*Fi2[i]);
    cinv=pow(cinv*pow(F(j,A,B,C),k),g);

 // multiply polynomial by new term(s)
    FPoly F;
    if (conj)
    { // conjugate pair
      // t^2-2a+(a^2+b^2) , where cinv=a+ib
        F.addterm((Flash)1,2);
        F.addterm(-2*real(cinv),1);
        F.addterm(real(cinv)*real(cinv)+imaginary(cinv)*imaginary(cinv),0);
    }
    else 
    { // t-cinv
        F.addterm((Flash)1,1);
        F.addterm(-real(cinv),0);
    }
    T=T*F;    // accumulate Polynomial
}

// A.13.2

int groups(Complex& lam,Flash *Fi2,Big D,BOOL doit,Flash& sigma)
{
    Big s,t,A,C,B,lim;
    int cn=0;
    s=sqrt(D/3);
    sigma=0;
    for (B=0;B<=s;B+=1)
    {
// cout << "B= " << B << " s= " << s << endl;
        t=D+B*B;
        lim=sqrt(t);
        A=2*B;
        if (A==0) A+=1;
        for(;;)
        {
            while (t%A!=0) 
            {
                A+=1;
                if (A>lim) break;
            }

            if (A>lim) break;
            C=t/A;
           
            if (gcd(gcd(A,2*B),C)==1)
            { // output more class group members
                BOOL conj;
                if (2*B>0 && C>A && A>2*B) 
                { 
                    conj=TRUE;
                    cn+=2;
                    if (doit)
                    { 
                        if (!suppress) cout << ".." << flush; 
                    }  
//                    else sigma+=(Flash)2/(Flash)A;
                }
                else
                {
                    conj=FALSE;
                    cn+=1;
                    if (doit)
                    {   
                        if (!suppress) cout << "." << flush; 
                    }
//                    else sigma+=(Flash)1/(Flash)A;
                } 
                if (doit) class_poly(lam,Fi2,A,B,C,D,conj);
            }
            A+=1;
        }        
    }
    return cn;         // class number
}

// check congruence conditions A14.2.1

BOOL isaD(int d,int pm8,Big k)
{
    int i,dm8;
    BOOL sqr;
    dm8=d%8;
    if (k==1 && dm8!=3) return FALSE;
    if ((k==2 || k==3) && dm8==7) return FALSE;
    if (pm8==3 && (dm8==1 || dm8==4 || dm8==5 || dm8==6)) return FALSE;
    if (pm8==5 && dm8%2==0) return FALSE;
    if (pm8==7 && (dm8==1 || dm8==2 || dm8==4 || dm8==5)) return FALSE;
    sqr=FALSE;
    for (i=2;;i++)
    {
        if (d%(i*i)==0)
        {
            sqr=TRUE;
            break;
        }
        if (i*i>d) break;
    }
    if (sqr) return FALSE;
    return TRUE;
}

// Testing for CM discriminants A.14.2.2

Big floor(Big N,Big D)
{
   Big R;
   if (N==0) return 0;
   if (N>0 && D>0) return N/D;
   if (N<0 && D<0) return (-N)/(-D);
   R=N/D;
   if (N%D!=0) R-=1;
   return R;
}

BOOL isacm(Big p,int D,Big &W,Big &V)
{
    Big B2,A,B,C,t,X,Y,ld,delta;
    B=sqrt(p-D,p);
    A=p;
    C=(B*B+D)/p;
    X=1;
    Y=0;
    ld=0;
    while (1)
    {
        if (C>=A)
        {
            B2=2*B;
            if (B2<0) B2=-B2;
            if (A>=B2) break;
        } 
        delta=floor(2*B+C,2*C);

// are we stuck in hopeless loop? This can't happen now - thanks Marcel
        if (delta==0 && ld==0) return FALSE;
        ld=delta;
        t=X;
        X=(delta*X+Y);
        Y=-t;

        t=C;

        C=(A+C*delta*delta-2*B*delta);
        B=(t*delta-B);
        A=t;        
    }
    if (D==11 && A==3)
    {
        t=X;
        X=Y;
        Y=-t;
        B=-B;
        t=C;
        C=A;
        A=t;        
    }      
    if (D==1 || D==3) 
    {
       W=2*X;
       V=2*Y;
       return TRUE;
    }
    else V=0;

    if (A==1) 
    {
        W=2*X;
        return TRUE;
    }

    if (A==4) 
    {
        W=4*X+B*Y;
        return TRUE;
    }

    return FALSE;
}


// Constructing a Curve (and Point in order is prime)
// A.14.4

BOOL get_curve(Complex& lam,Flash *Fi2,ofstream& ofile, Big r, Big other_r,Big ord, int D, Big p, Big W)
{
    Poly polly;
    Big A0,B0,k;
    BOOL unstable;
    char c;
    int i,d,terms,class_number,precision,lh;
    Flash sigma;
    BOOL pord=prime(ord);

    k=r/ord;
    if (!suppress) 
    {
     
        if (D>1000 && D%3==0) cout  << "D= " << D << " (Divisible by 3 - might need extra precision)" << endl;
        else                  cout  << "D= " << D << endl;
        cout << "k= " << k << endl;
    }

    class_number=groups(lam,Fi2,D,FALSE,sigma);
//  get_mip()->RPOINT=ON;
//  cout << "sigma= " << sigma << endl;
//    precision=(int)3.322*((1.364*todouble(sigma)*sqrt((double)D))+class_number/4+5);
//    if (D%2!=0)
//    {
//        lh=0; d=D; while ((d/=2)!=0) lh++; precision=(precision+class_number*lh)/2;         
//    }
//    else if (D%3!=0)
//    {
//        if (D%8==7) {precision/=47; precision+=1;}
//    }
//    precision/=MIRACL;
//    if (precision<32) precision=32;
    
    cout << "class number= " << class_number << endl;

//    cout << "over(?)-estimated precision= " << precision << endl;
 
    cout << "Group order= " << ord << endl;
    cout << "do you want to proceed with this one (Y/N)? " ;
    cin >> c;
    if (c=='N' || c=='n') 
    {
        if (!suppress) cout << "finding a curve..." << endl;
        return FALSE;
    }

    modulo(p);

// A.14.4.1
    
    if (D==1)
    {
        A0=1; B0=0;
    }
    if (D==3)
    {
        A0=0; B0=1;
    }

    if (D!=1 && D!=3)
    {
        Flash f,rem;
        T.clear();
        T.addterm(1,0);   
        if (!suppress) cout << "constructing polynomial";
        groups(lam,Fi2,D,TRUE,sigma);
        terms=degree(T);
        unstable=FALSE;
        for (i=terms;i>=0;i--)
        {
            f=T.coeff(i);
            if (f>0)
                 f+=Flash(1,10000);
            else f-=Flash(1,10000);
            polly.addterm((ZZn)f.trunc(&rem),i);
            if (fabs(rem)>Flash(1,100)) 
            {
                unstable=TRUE; 
                break; 
            }
        }
        T.clear();
        if (!suppress) cout << endl;
        if (unstable) 
        {
            if (!suppress) cout << "Curve abandoned - numerical instability!" << endl;
            if (!suppress) cout << "Curve abandoned - double MIRACL precision and try again!" << endl;
            if (!suppress) cout << "finding a curve..." << endl;
            return FALSE;
        }
        if (!suppress) cout << polly << endl;
    }

    ECn pt,G;
    Big a,b,x,y;
    Big w,eps;
    int at;
    Poly g;

    forever
    {
        if (D!=1 && D!=3)
        {
            if (!suppress) cout << "Factoring polynomial of degree " << degree(polly) << " ....." << endl;
            if (W%2==0)
            {
                ZZn V;
                g=factor(polly,1);
                V=-g.coeff(0);
                V=pow(V,24/(igcd(D,3)*getk(D)));
                V*=pow((ZZn)2,(4*geti(D))/getk(D));
                if (D%2!=0) V=-V;
                A0=(Big)((ZZn)(-3)*(V+64)*(V+16));   
                B0=(Big)((ZZn)2*(V+64)*(V+64)*(V-8));
            }
            else
            {
                Poly V,w,w1,w2,w3,a,b;

                g=factor(polly,3);
                if (D%3!=0)
                    w.addterm(-1,24);
                else
                    w.addterm(-256,8);
                V=w%g;
                w.clear();
                w1=V; w2=V; w3=V;
                w1.addterm(64,0);
                w2.addterm(256,0);
                w3.addterm(-512,0);
                a=w1*w2;
                a.multerm(-3,0);
                a=a%g;
                b=w1*w1*w3;
                b.multerm(2,0);
                b=b%g;

                a=((a*a)*a)%g;
                b=(b*b)%g;
                for (int d=degree(g)-1;d>=0;d--)
                {
                    ZZn t,c=a.coeff(d);
                    if (c!=(ZZn)0)
                    {
                        t=b.coeff(d);
                        A0=(Big)(c*t);
                        B0=(Big)(c*t*t);
                        if (d==1) break;
                    }     
                }
            }
        }

// A.14.4.2
// but try -3 first, followed by small positive values for A

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -