BOOL power_tate(ECn& P,ECn4 Q,Big& q,Big *cf,ZZn2 &Fr,Big &e,ZZn4& r) { int i,nb; ECn A; ZZn8 w,res,a[4]; ZZn4 Qx,Qy; ZZn2 x,y; Big carry,ex[4]; Big p=get_modulus(); Q.get(Qx,Qy); Qx=txd(Qx); Qy=txd(txd(Qy)); res=1; /* Left to right method */ A=P; nb=bits(q); for (i=nb-2;i>=0;i--) { res*=res; res*=g(A,A,Qx,Qy); if (bit(q,i)) res*=g(A,P,Qx,Qy); } if (!A.iszero() || res.iszero()) return FALSE; w=res; w.powq(Fr); w.powq(Fr); // ^(p^4-1) w.powq(Fr); w.powq(Fr); res=w/res; res.mark_as_unitary(); a[3]=res; a[2]=a[3]; a[2].powq(Fr); a[1]=a[2]; a[1].powq(Fr); a[0]=a[1]; a[0].powq(Fr); if (e.isone()) for (i=0;i<4;i++) ex[i]=cf[i]; else { // cf *= e carry=0; for (i=3;i>=0;i--) carry=mad(cf[i],e,carry,p,ex[i]); } res=pow(4,a,ex); r=real(res); // compression // r=powl(real(res),cf); // ^(p*p*p*p+1)/q if (r.isunity()) return FALSE; return TRUE; }
ECn4 hash4(char *ID) { ECn4 T; ZZn4 x; ZZn2 X,Y=0; Big x0,y0=0; x0=H1(ID); do { X.set(x0,y0); x.set(X,Y); x0+=1; } while (!is_on_curve(x)); T.set(x); return T; }
int main(int argc, char **argv) { miracl *mip=&precision; Big p,R,B,mc,curve_b,cru,cof,tau[9]; Big m,x,y,w,t,c,n,r,a,b,gx,gy,r2modp; Big np,PP,TT,FF; int i,A,curve,bb,chunk,words,mbits,bytes,ip=0; int modtype,curvetype,curve_a,curve_b_i,cof_i,lang=0; ZZn2 X; ECn P; ECn2 Q; ECn4 QQ; ECn8 Q8; ZZn4 XA,YA,AA,BB; ZZn8 X8,Y8; ZZn2 Aa,Ab,Ba,Bb; ZZn2 Xa,Ya; ZZn zcru; char pre0[50],pre1[50],pre2[50],pre3[50],pre4[50],pre5[50],pre6[50]; char post0[50],post1[50],post2[50],post3[50],post4[50],post5[50],post6[50]; char pre7[50],post7[50],lg[50]; char xxx[20],yyy[20],zzz[20]; char curvename[30],fieldname[30]; argv++; argc--; if (argc<4) { help(); return 0; } strcpy(curvename,argv[0]); // curve=atoi(argv[ip++]); for (i=0;;i++) { if (curvename[i]==0) break; curvename[i]=toupper(curvename[i]); } //cout << "curvename= " << curvename << " " << strlen(curvename) << endl; curve=0; ip++; chunk=atoi(argv[ip++]); bb=atoi(argv[ip++]); strcpy(lg,argv[ip]); if (chunk !=16 && chunk!=32 && chunk!=64) {help(); return 0;} if (bb<0 || bb>=chunk) {help(); return 0;} // Specify curve constants if (strcmp(curvename,"ED25519")==0) { // ED25519 curve=1; printf("Curve= ED25519\n"); strcpy(fieldname,"25519"); mbits=255; // bits in modulus words=(1+((mbits-1)/bb)); // words per Big curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=-1; // Curve A parameter cof=8; p=pow((Big)2,mbits)-19; // Modulus r=pow((Big)2,252)+(char *)"27742317777372353535851937790883648493"; // group order mip->IOBASE=16; curve_b=(char *)"52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3"; // curve B parameter gx=(char *)"216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"; // generator point gy=(char *)"6666666666666666666666666666666666666666666666666666666666666658"; } if (strcmp(curvename,"C25519")==0) { curve=2; printf("Curve= C25519\n"); strcpy(fieldname,"25519"); mbits=255; words=(1+((mbits-1)/bb)); curvetype=MONTGOMERY; modtype=PSEUDO_MERSENNE; curve_a=486662; cof=8; p=pow((Big)2,mbits)-19; r=pow((Big)2,252)+(char *)"27742317777372353535851937790883648493"; curve_b=0; mip->IOBASE=16; gx=(char *)"9"; gy=0; } if (strcmp(curvename,"NIST256")==0) { curve=3; printf("Curve= NIST256\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"115792089210356248762697446949407573530086143415290314195533631308867097853951"; r=(char *)"115792089210356248762697446949407573529996955224135760342422259061068512044369"; mip->IOBASE=16; curve_b=(char *)"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"; gx=(char *)"6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"; gy=(char *)"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"; } if (strcmp(curvename,"BRAINPOOL")==0) { curve=4; printf("Curve= BRAINPOOL\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"76884956397045344220809746629001649093037950200943055203735601445031516197751"; mip->IOBASE=16; r=(char *)"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7"; mip->IOBASE=10; curve_b=(char *)"46214326585032579593829631435610129746736367449296220983687490401182983727876"; mip->IOBASE=16; gx=(char *)"a3e8eb3cc1cfe7b7732213b23a656149afa142c47aafbc2b79a191562e1305f4"; gy=(char *)"2d996c823439c56d7f7b22e14644417e69bcb6de39d027001dabe8f35b25c9be"; } if (strcmp(curvename,"ANSSI")==0) { curve=5; printf("Curve= ANSSI\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"109454571331697278617670725030735128145969349647868738157201323556196022393859"; mip->IOBASE=16; r=(char *)"F1FD178C0B3AD58F10126DE8CE42435B53DC67E140D2BF941FFDD459C6D655E1"; mip->IOBASE=10; curve_b=(char *)"107744541122042688792155207242782455150382764043089114141096634497567301547839"; mip->IOBASE=16; gx=(char *)"b6b3d4c356c139eb31183d4749d423958c27d2dcaf98b70164c97a2dd98f5cff"; gy=(char *)"6142e0f7c8b204911f9271f0f3ecef8c2701c307e8e4c9e183115a1554062cfb"; } if (strcmp(curvename,"HIFIVE")==0) { curve=6; printf("Curve= HIFIVE\n"); strcpy(fieldname,curvename); mbits=336; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=8; p=pow((Big)2,336)-3; mip->IOBASE=16; r=(char *)"200000000000000000000000000000000000000000071415FA9850C0BD6B87F93BAA7B2F95973E9FA805"; mip->IOBASE=10; curve_b=(char *)"11111"; mip->IOBASE=16; gx=(char *)"C"; gy=(char *)"C0DC616B56502E18E1C161D007853D1B14B46C3811C7EF435B6DB5D5650CA0365DB12BEC68505FE8632"; } if (strcmp(curvename,"GOLDILOCKS")==0) { curve=7; printf("Curve= GOLDILOCKS\n"); strcpy(fieldname,curvename); mbits=448; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=GENERALISED_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,448)-pow((Big)2,224)-1; r=(p+1-(char *)"28312320572429821613362531907042076847709625476988141958474579766324")/4; mip->IOBASE=10; curve_b=p-39081; mip->IOBASE=16; gx=(char *)"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa955555555555555555555555555555555555555555555555555555555"; gy=(char *)"ae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed"; } if (strcmp(curvename,"NIST384")==0) { curve=8; printf("Curve= NIST384\n"); strcpy(fieldname,curvename); mbits=384; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=(char *)"39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319"; r=p+1-(char *)"1388124618062372383606759648309780106643088307173319169677"; curve_b=(char *)"27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575"; mip->IOBASE=16; gx=(char *)"aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"; gy=(char *)"3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"; } if (strcmp(curvename,"C41417")==0) { curve=9; printf("Curve= C41417\n"); strcpy(fieldname,curvename); mbits=414; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; p=pow((Big)2,mbits)-17; cof=8; r=pow((Big)2,411)-(char *)"33364140863755142520810177694098385178984727200411208589594759"; // Group Order curve_b=(char *)"3617"; mip->IOBASE=16; gx=(char *)"1a334905141443300218c0631c326e5fcd46369f44c03ec7f57ff35498a4ab4d6d6ba111301a73faa8537c64c4fd3812f3cbc595"; gy=(char *)"22"; } if (strcmp(curvename,"NIST521")==0) { curve=10; printf("Curve= NIST521\n"); strcpy(fieldname,curvename); mbits=521; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=-3; cof=1; p=pow((Big)2,mbits)-1; mip->IOBASE=16; r=(char *)"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; // Group Order curve_b=(char *)"51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"; gx=(char *)"C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"; gy=(char *)"11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; } if (strcmp(curvename,"NUMS256W")==0) { curve=11; printf("Curve= NUMS256W\n"); strcpy(fieldname,"256PMW"); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=PSEUDO_MERSENNE; curve_a=-3; cof=1; p=pow((Big)2,mbits)-189; mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE43C8275EA265C6020AB20294751A825"; // Group Order curve_b=(char *)"25581"; gx=(char *)"BC9ED6B65AAADB61297A95A04F42CB0983579B0903D4C73ABC52EE1EB21AACB1"; gy=(char *)"D08FC0F13399B6A673448BF77E04E035C955C3D115310FBB80B5B9CB2184DE9F"; } if (strcmp(curvename,"NUMS256E")==0) { curve=12; printf("Curve= NUMS256E\n"); strcpy(fieldname,"256PME"); mbits=256; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,mbits)-189; mip->IOBASE=16; r=(char *)"4000000000000000000000000000000041955AA52F59439B1A47B190EEDD4AF5"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC355"; gx=(char *)"8A7514FB6AEA237DCD1E3D5F69209BD60C398A0EE3083586A0DEC0902EED13DA"; gy=(char *)"44D53E9FD9D925C7CE9665D9A64B8010715F61D810856ED32FA616E7798A89E6"; } if (strcmp(curvename,"NUMS384W")==0) { curve=13; printf("Curve= NUMS384W\n"); strcpy(fieldname,"384PM"); mbits=384; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=PSEUDO_MERSENNE; curve_a=-3; cof=1; p=pow((Big)2,mbits)-317; mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD61EAF1EEB5D6881BEDA9D3D4C37E27A604D81F67B0E61B9"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77BB"; gx=(char *)"757956F0B16F181C4880CA224105F1A60225C1CDFB81F9F4F3BD291B2A6CC742522EED100F61C47BEB9CBA042098152A"; gy=(char *)"ACDEE368E19B8E38D7E33D300584CF7EB0046977F87F739CB920837D121A837EBCD6B4DBBFF4AD265C74B8EC66180716"; } if (strcmp(curvename,"NUMS384E")==0) { curve=14; printf("Curve= NUMS384E\n"); strcpy(fieldname,"384PM"); mbits=384; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,mbits)-317; mip->IOBASE=16; r=(char *)"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2471A1CB46BE1CF61E4555AAB35C87920B9DCC4E6A3897D"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD19F"; gx=(char *)"61B111FB45A9266CC0B6A2129AE55DB5B30BF446E5BE4C005763FFA8F33163406FF292B16545941350D540E46C206BDE"; gy=(char *)"82983E67B9A6EEB08738B1A423B10DD716AD8274F1425F56830F98F7F645964B0072B0F946EC48DC9D8D03E1F0729392"; } if (strcmp(curvename,"NUMS512W")==0) { curve=15; printf("Curve= NUMS512W\n"); strcpy(fieldname,"512PM"); mbits=512; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=PSEUDO_MERSENNE; curve_a=-3; cof=1; p=pow((Big)2,mbits)-569; mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B3CA4FB94E7831B4FC258ED97D0BDC63B568B36607CD243CE153F390433555D"; // Group Order curve_b=(char *)"1D99B"; gx=(char *)"3AC03447141D0A93DA2B7002A03D3B5298CAD83BB501F6854506E0C25306D9F95021A151076B359E93794286255615831D5D60137D6F5DE2DC8287958CABAE57"; gy=(char *)"943A54CA29AD56B3CE0EEEDC63EBB1004B97DBDEABBCBB8C8F4B260C7BD14F14A28415DA8B0EEDE9C121A840B25A5602CF2B5C1E4CFD0FE923A08760383527A6"; } if (strcmp(curvename,"NUMS512E")==0) { curve=16; printf("Curve= NUMS512E\n"); strcpy(fieldname,"512PM"); mbits=512; words=(1+((mbits-1)/bb)); curvetype=EDWARDS; modtype=PSEUDO_MERSENNE; curve_a=1; cof=4; p=pow((Big)2,mbits)-569; mip->IOBASE=16; r=(char *)"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4F0636D2FCF91BA9E3FD8C970B686F52A4605786DEFECFF67468CF51BEED46D"; // Group Order curve_b=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFECBEF"; gx=(char *)"DF8E316D128DB69C7A18CB7888D3C5332FD1E79F4DC4A38227A17EBE273B81474621C14EEE46730F78BDC992568904AD0FE525427CC4F015C5B9AB2999EC57FE"; gy=(char *)"6D09BFF39D49CA7198B0F577A82A256EE476F726D8259D22A92B6B95909E834120CA53F2E9963562601A06862AECC1FD0266D38A9BF1D01F326DDEC0C1E2F5E1"; } if (strcmp(curvename,"SECP256K1")==0) { // SECP256K1 curve=17; printf("Curve= SECP256K1\n"); strcpy(fieldname,"SECP256K1"); mbits=256; // bits in modulus words=(1+((mbits-1)/bb)); // words per Big curvetype=WEIERSTRASS; /*if (chunk<64)*/ modtype=NOT_SPECIAL; //modtype=PSEUDO_MERSENNE; curve_a=0; // Curve A parameter cof=1; p=pow((Big)2,mbits)-pow((Big)2,32)-977; // Modulus mip->IOBASE=16; r=(char *)"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"; // group order curve_b=(char *)"7"; // curve B parameter gx=(char *)"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"; // generator point gy=(char *)"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"; } if (strcmp(curvename,"BN254")==0) { curve=18; printf("Curve= BN254\n"); strcpy(fieldname,curvename); mbits=254; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"4080000000000001"; // Fast but not GT_STRONG parameter p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1; // Modulus t=6*x*x+1; r=p+1-t; // Group order curve_b=2; gx=p-1; // generator point in G1 gy=1; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_D; // twist type Xa.set((ZZn)0,(ZZn)-1); Ya.set((ZZn)1,ZZn(0)); Q.set(Xa,Ya); Q=(p-1+t)*Q; // generator point in G2 cru=(18*pow(x,3)-18*x*x+9*x-2); // cube root of unity for GLV method } if (strcmp(curvename,"BN254CX")==0) { curve=19; printf("Curve= BN254CX\n"); strcpy(fieldname,curvename); mbits=254; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"4000000003C012B1"; p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1; t=6*x*x+1; r=p+1-t; curve_b=2; gx=p-1; gy=1; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_D; Xa.set((ZZn)0,(ZZn)-1); Ya.set((ZZn)1,ZZn(0)); Q.set(Xa,Ya); Q=(p-1+t)*Q; // generator point in G2 cru=(18*pow(x,3)-18*x*x+9*x-2); } if (strcmp(curvename,"BLS383")==0) { curve=20; printf("Curve= BLS383\n"); strcpy(fieldname,curvename); mbits=383; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; // x=(char *)"11000001000000040"; x=(char *)"10008000001001200"; // SIGN_OF_X is POSITIVE p=(pow(x,6)-2*pow(x,5)+2*pow(x,3)+x+1)/3; t=x+1; r=pow(x,4)-x*x+1; cof=(p+1-t)/r; // gx=-2; gy=-1; // curve_b=9; gx=1; gy=4; curve_b=15; ecurve((Big)0,curve_b,p,MR_AFFINE); // mip->TWIST=MR_SEXTIC_D; mip->TWIST=MR_SEXTIC_M; P.set(gx,gy); P*=cof; P.get(gx,gy); //cout << "gx= " << gx << endl; //cout << "gy= " << gy << endl; //cout << "y^2= " << (gy*gy)%p << endl; //cout << "x^3+b= " << (gx*gx*gx+15)%p << endl; //while (!Q.set(randn2())) ; // probably not best way to choose this Xa=1; while (!Q.set(Xa)) { Xa=Xa+(ZZn2)1; } TT=t*t-2*p; PP=p*p; FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(-3*FF+TT)/2; // 2 possibilities... Q=(np/r)*Q; zcru=pow((ZZn)2,(p-1)/3); // zcru*=zcru; // right cube root of unity cru=(Big)zcru; } if (strcmp(curvename,"BLS381")==0) { curve=21; printf("Curve= BLS381\n"); strcpy(fieldname,curvename); mbits=381; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"d201000000010000"; // SIGN_OF_X is NEGATIVE p=(pow(x,6)+2*pow(x,5)-2*pow(x,3)-x+1)/3; t=-x+1; r=pow(x,4)-x*x+1; cof=(p+1-t)/r; curve_b=4; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; gx=1; while (!P.set(gx)) { gx=gx+1; } P*=cof; P.get(gx,gy); Xa=1; while (!Q.set(Xa)) { Xa=Xa+(ZZn2)1; } Q.get(Xa,Ya); Ya=-Ya; Q.set(Xa,Ya); TT=t*t-2*p; PP=p*p; FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(-3*FF+TT)/2; // 2 possibilities... Q=(np/r)*Q; zcru=pow((ZZn)2,(p-1)/3); //zcru*=zcru; // right cube root of unity ?? if x>0 do this?? cru=(Big)zcru; } if (strcmp(curvename,"BLS461")==0) { curve=24; printf("Curve= BLS461\n"); strcpy(fieldname,curvename); mbits=461; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"1FFFFFFBFFFE00000000"; // SIGN_OF_X is NEGATIVE p=(pow(x,6)+2*pow(x,5)-2*pow(x,3)-x+1)/3; t=-x+1; r=pow(x,4)-x*x+1; cof=(p+1-t)/r; gx=-2; gy=-1; curve_b=9; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; P.set(gx,gy); P*=cof; P.get(gx,gy); while (!Q.set(randn2())) ; // probably not best way to choose this TT=t*t-2*p; PP=p*p; FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(-3*FF+TT)/2; // 2 possibilities... Q=(np/r)*Q; zcru=pow((ZZn)2,(p-1)/3); //zcru*=zcru; // right cube root of unity cru=(Big)zcru; } if (strcmp(curvename,"FP256BN")==0) { curve=22; printf("Curve= FP256BN\n"); strcpy(fieldname,curvename); mbits=256; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"6882F5C030B0A801"; // Slow! p=36*pow(x,4)-36*pow(x,3)+24*x*x-6*x+1; t=6*x*x+1; r=p+1-t; curve_b=3; gx=1; gy=2; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; Q.set((ZZn2)1); //while (!Q.set(randn2())) ; Q=(p-1+t)*Q; cru=(18*pow(x,3)-18*x*x+9*x-2); cout << pre1 << toupperit((char *)"CURVE_Cru",lang) << post1; output(chunk,words,cru,m); cout << term << endl; } if (strcmp(curvename,"FP512BN")==0) { curve=23; printf("Curve= FP512BN\n"); strcpy(fieldname,curvename); mbits=512; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; x=(char *)"6882F5C030B0F7F010B306BB5E1BD80F"; // Slow! p=36*pow(x,4)+36*pow(x,3)+24*x*x+6*x+1; t=6*x*x+1; r=p+1-t; curve_b=3; gx=1; gy=2; cof=1; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; Q.set((ZZn2)1); //while (!Q.set(randn2())) ; Q=(p-1+t)*Q; cru=p-(18*pow(x,3)+18*x*x+9*x+2); } if (strcmp(curvename,"BLS24")==0) { curve=25; printf("Curve= BLS24\n"); strcpy(fieldname,curvename); mbits=479; words=(1+((mbits-1)/bb)); curvetype=WEIERSTRASS; modtype=NOT_SPECIAL; curve_a=0; mip->IOBASE=16; // Note - this is GT-Strong curve x=(char *)"100020011FF80"; // SIGN_OF_X is POSITIVE //x=-x; p=(1+x+x*x-pow(x,4)+2*pow(x,5)-pow(x,6)+pow(x,8)-2*pow(x,9)+pow(x,10))/3; t=x+1; r=pow(x,8)-pow(x,4)+1; cof=(p+1-t)/r; //x=-x; gx=5; gy=12; curve_b=19; ecurve((Big)0,curve_b,p,MR_AFFINE); mip->TWIST=MR_SEXTIC_M; P.set(gx,gy); P*=cof; P.get(gx,gy); Big x0=0; forever { ZZn4 X; ZZn2 t; x0+=1; t.set((ZZn)0,(ZZn)x0); X.set(t,(ZZn2)0); if (!QQ.set(X)) continue; break; } TT=t*t*t*t-4*p*t*t+2*p*p; PP=pow(p,4); FF=sqrt((4*PP-TT*TT)/3); np=PP+1-(3*FF+TT)/2; QQ=(np/r)*QQ; //cout << "QQ= " << QQ << endl; //cout << "2*QQ= " << QQ+QQ << endl; //cout << "3*QQ= " << (QQ+QQ)+QQ << endl; zcru=pow((ZZn)2,(p-1)/3); //zcru*=zcru; // right cube root of unity - not for M-TYPE cru=(Big)zcru; }
int main() { 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; }