String CvSakke::to_string( const ECn& point ) { Big x, y; point.get(x, y); return "[" + to_string(x) + "," + to_string(y) + "]"; }
int main() { ifstream common("mnt.ecs"); // MNT elliptic curve parameters ifstream private_key("bls_private.key"); ofstream signature("bls_signature.sig"); miracl* mip=&precision; ECn PM; Big x,s,p,q,B; int bits,A,lsb; common >> bits; mip->IOBASE=16; common >> p; common >> A; common >> B >> q; private_key >> s; ecurve(A,B,p,MR_PROJECTIVE); PM=hash_and_map((char *)"This a quick test of the method",32); cout << "Short message has been signed - signature in bls_signature.sig " << endl; PM*=s; lsb=PM.get(x); signature << x << endl; signature << lsb << endl; return 0; }
int signatureofshorthash(unsigned char *sm,mr_unsign64 *smlen,const unsigned char *m,mr_unsign64 mlen,const unsigned char *sk,mr_unsign64 sklen) { miracl* mip=mirsys(40,16); ECn PM; Big x,y,s,p,B; int lsb,bits; mip->IOBASE=16; p=ptext; B=Btext; ecurve((Big)-3,B,p,MR_PROJECTIVE); s=from_binary((int)sklen,(char *)sk); PM=hash_and_map((char *)m,32); PM*=s; lsb=PM.get(x); to_binary(x,20,(char *)sm,TRUE); *smlen=20; if (lsb) sm[0]|=0x80; return 0; }
int main() { ifstream common("common.ecs"); /* construct file I/O streams */ ifstream private_key("private.ecs"); ifstream message; ofstream signature; char ifname[50],ofname[50]; ECn G; Big a,b,p,q,x,y,h,r,s,d,k; long seed; int bits; miracl *mip=&precision; /* randomise */ cout << "Enter 9 digit random number seed = "; cin >> seed; irand(seed); /* get common data */ common >> bits; mip->IOBASE=16; common >> p >> a >> b >> q >> x >> y; mip->IOBASE=10; /* calculate r - this can be done off-line, and hence amortized to almost nothing */ ecurve(a,b,p,MR_PROJECTIVE); G=ECn(x,y); // k="702232148019446860144825009548118511996283736794"; // test vector from http://www.secg.org/collateral/gec2.pdf k=rand(q); G*=k; /* see ebrick.cpp for technique to speed this up */ G.get(r); r%=q; /* get private key of recipient */ private_key >> d; /* get message */ cout << "file to be signed = " ; cin >> ifname; strcpy(ofname,ifname); strip(ofname); strcat(ofname,".ecs"); message.open(ifname,ios::binary|ios::in); if (!message) { cout << "Unable to open file " << ifname << "\n"; return 0; } h=Hash(message); /* calculate s */ k=inverse(k,q); s=((h+d*r)*k)%q; signature.open(ofname); signature << r << endl; signature << s << endl; return 0; }
ECn map_f(ECn& P,ZZn& zeta) { ECn R; Big x,y; P.get(x,y); ZZn X=x; X=zeta*X; x=Big(X); if (!R.set(x,y)) cout << "something wrong in map_f" << endl; return R; }
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; }
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(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; }
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); }
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(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; }
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; }
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; }
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; }