Example #1
0
ZZn12 line(ECn2& A,ECn2& C,ECn2& B,ZZn2& slope,ZZn2& extra,BOOL Doubling,ZZn& Qx,ZZn& Qy)
{
    ZZn12 w;
    ZZn4 nn,dd;
    ZZn2 X,Y;

    ZZn2 Z3;

    C.getZ(Z3);

// Thanks to A. Menezes for pointing out this optimization...
    if (Doubling)
    {
        ZZn2 Z,ZZ;
        A.get(X,Y,Z);
        ZZ=Z; ZZ*=ZZ;
		nn.set((Z3*ZZ)*Qy,slope*X-extra);
		dd.set(-(ZZ*slope)*Qx);        
    }
    else
    {
        ZZn2 X2,Y2;
        B.get(X2,Y2);
		nn.set(Z3*Qy,slope*X2-Y2*Z3);
		dd.set(-slope*Qx);       
    }
    w.set(nn,dd);

    return w;
}
Example #2
0
ZZn12 line(ECn2& A,ECn2& C,ZZn2& slope,ZZn& Qx,ZZn& Qy)
{
     ZZn12 w;
     ZZn6 nn,dd;
     ZZn2 X,Y;

#ifdef AFFINE
     A.get(X,Y);

     dd.set(slope*Qx,Y-slope*X);
     nn.set((ZZn2)-Qy);
     w.set(nn,dd);

#endif
#ifdef PROJECTIVE
    ZZn2 Z,Z2,ZZ,ZZZ;

    A.get(X,Y,Z);
    C.getZ(Z2);

    ZZ=Z*Z;
    ZZZ=ZZ*Z;

    dd.set((ZZZ*slope)*Qx,Z2*Y-Z*X*slope);
    nn.set((ZZn2)-(ZZZ*Z2)*Qy);
    w.set(nn,dd);

#endif

     return w;
}
Example #3
0
void SoftExpo(ZZn12 &f3, ZZn2 &X){
  ZZn12 t0;
  int i;

  t0=f3; f3.conj(); f3/=t0;
  f3.mark_as_regular();
  t0=f3; f3.powq(X); f3.powq(X); f3*=t0;
  f3.mark_as_unitary();
}
Example #4
0
GT PFC::miller_loop(const G2& QQ,const G1& PP)
{ 
	GT z;
	Big n;
	int i,j,nb,nbw,nzs;
    ECn2 A,KA,Q;
	ECn P;
	ZZn Px,Py;
	BOOL precomp;
    ZZn12 r;
	Big X=*x;

	Q=QQ.g; P=PP.g;

	precomp=FALSE;
	if (QQ.ptable!=NULL) precomp=TRUE;
	else Q.norm();

	normalise(P);
	extract(P,Px,Py);

	if (X<0) n=-(6*X+2);
    else n=6*X+2;
    A=Q;
    nb=bits(n);
    r=1;
// Short Miller loop
	r.mark_as_miller();
	j=0;
    for (i=nb-2;i>=0;i--)
    {
		r*=r;
		if (precomp) r*=gp(QQ.ptable,j,Px,Py);
		else         r*=g(A,A,Px,Py);
		if (bit(n,i))
		{
			if (precomp) r*=gp(QQ.ptable,j,Px,Py);
            else         r*=g(A,Q,Px,Py);
		}
    }
// Combining ideas due to Longa, Aranha et al. and Naehrig
	KA=Q;
	q_power_frobenius(KA,*frob);
	if (X<0) {A=-A; r.conj();}
	if (precomp) r*=gp(QQ.ptable,j,Px,Py);
	else         r*=g(A,KA,Px,Py);
	q_power_frobenius(KA,*frob); KA=-KA;
	if (precomp) r*=gp(QQ.ptable,j,Px,Py);
	else         r*=g(A,KA,Px,Py);

    z.g=r;
	return z;
}
Example #5
0
ZZn12 gp(ZZn2* ptable,int &j,ZZn& Px,ZZn& Py)
{
	ZZn12 w;
	ZZn4 nn,dd;
	
	nn.set(Py,ptable[j+1]);
	dd.set(ptable[j]*Px);
	j+=2;
	w.set(nn,dd);

	return w;
}
Example #6
0
Big H2(ZZn12 x)
{ // Compress and hash an Fp12 to a big number
    sha256 sh;
    ZZn4 u;
    ZZn2 h,l;
    Big a,hash,p,xx[4];
    char s[HASH_LEN];
    int i,j,m;

    shs256_init(&sh);
    x.get(u);  // compress to single ZZn4
    u.get(l,h);
    xx[0]=real(l); xx[1]=imaginary(l); xx[2]=real(h); xx[3]=imaginary(h);
 
    for (i=0;i<4;i++)
    {
        a=xx[i];
        while (a>0)
        {
            m=a%256;
            shs256_process(&sh,m);
            a/=256;
        }
    }
    shs256_hash(&sh,s);
    hash=from_binary(HASH_LEN,s);
    return hash;
}
Example #7
0
ZZn12 line(ECn2& A,ECn2& C,ECn2&B,ZZn2& slope,ZZn2& extra,BOOL Doubling,ZZn& Qx,ZZn& Qy)
{
     ZZn12 w;
     ZZn6 nn,dd;
     ZZn2 X,Y;

#ifdef AFFINE
     A.get(X,Y);

     dd.set(slope*Qx,Y-slope*X);
     nn.set((ZZn2)-Qy);
     w.set(nn,dd);

#endif
#ifdef PROJECTIVE
    ZZn2 Z3;

    C.getZ(Z3);

// Thanks to A. Menezes for pointing out this optimization...
    if (Doubling)
    {
        ZZn2 Z,ZZ;
        A.get(X,Y,Z);
        ZZ=Z; ZZ*=ZZ;
        dd.set(-(ZZ*slope)*Qx,slope*X-extra);
        nn.set((Z3*ZZ)*Qy);
    }
    else
    {
        ZZn2 X2,Y2;
        B.get(X2,Y2);
        dd.set(-slope*Qx,slope*X2-Y2*Z3);
        nn.set(Z3*Qy);  
    }
    w.set(nn,dd);
#endif
//cout << "w= " << w << endl;
     return w;
}
Example #8
0
BOOL fast_pairing(ECn2& P,ZZn& Qx,ZZn& Qy,Big &x,ZZn2 &X,ZZn12& res)
{ 
    ECn2 A,KA;
    ZZn2 AX,AY;
    int i,nb;
    Big n;
    ZZn12 r;
    ZZn12 t0,t1;
    ZZn12 x0,x1,x2,x3,x4,x5;

#ifdef MR_COUNT_OPS
fpc=fpa=fpx=fpmq=fpsq=fpaq=0;
#endif

	if (x<0) n=-(6*x+2);
    else n=6*x+2;
    A=P;
    nb=bits(n);
    r=1;
// Short Miller loop
	r.mark_as_miller();

    for (i=nb-2;i>=0;i--)
    {
		r*=r;
		r*=g(A,A,Qx,Qy);
		if (bit(n,i))
            r*=g(A,P,Qx,Qy);
    }
// Combining ideas due to Longa, Aranha et al. and Naehrig
	KA=P;
	q_power_frobenius(KA,X);
	if (x<0) {A=-A; r.conj();}
	r*=g(A,KA,Qx,Qy);
	q_power_frobenius(KA,X); KA=-KA;
	r*=g(A,KA,Qx,Qy);

#ifdef MR_COUNT_OPS
cout << "Miller fpc= " << fpc << endl;
cout << "Miller fpa= " << fpa << endl;
cout << "Miller fpx= " << fpx << endl;
cout << "Miller fpmq= " << fpmq << endl;
cout << "Miller fpsq= " << fpsq << endl;
cout << "Miller fpaq= " << fpaq << endl;

fpa=fpc=fpx=fpmq=fpsq=fpaq=0;
#endif
    if (r.iszero()) return FALSE;

// The final exponentiation

    t0=r;

    r.conj();

    r/=t0;    // r^(p^6-1)
	r.mark_as_regular();  // no longer "miller"

    t0=r;
    r.powq(X); r.powq(X);
    r*=t0;    // r^[(p^6-1)*(p^2+1)]

    r.mark_as_unitary();  // from now on all inverses are just conjugates !! (and squarings are faster)

	res=r;
// Newer new idea...
// See "On the final exponentiation for calculating pairings on ordinary elliptic curves" 
// Michael Scott and Naomi Benger and Manuel Charlemagne and Luis J. Dominguez Perez and Ezekiel J. Kachisa 


    t0=res;    t0.powq(X);
    x0=t0;   x0.powq(X);

    x0*=(res*t0);
    x0.powq(X);

    x1=inverse(res);  // just a conjugation!

    x4=pow(res,-x);  // x is sparse..
    x3=x4; x3.powq(X);

    x2=pow(x4,-x);
    x5=inverse(x2);
	t0=pow(x2,-x);

	x2.powq(X); 
    x4/=x2;
   
    x2.powq(X);
   
    res=t0; res.powq(X); t0*=res;

    t0*=t0;
    t0*=x4;
    t0*=x5;
    res=x3*x5;
    res*=t0;
    t0*=x2;
    res*=res;
    res*=t0;
    res*=res;
    t0=res*x1;
    res*=x0;
    t0*=t0;
    t0*=res;

#ifdef MR_COUNT_OPS
cout << "FE fpc= " << fpc << endl;
cout << "FE fpa= " << fpa << endl;
cout << "FE fpx= " << fpx << endl;
cout << "FE fpmq= " << fpmq << endl;
cout << "FE fpsq= " << fpsq << endl;
cout << "FE fpaq= " << fpaq << endl;
fpa=fpc=fpx=fpmq=fpsq=fpaq=0;
#endif

    res= t0; 
    return TRUE;
}
Example #9
0
ZZn12 line(ECn2& A,ECn2& C,ECn2& B,ZZn2& slope,ZZn2& extra,BOOL Doubling,ZZn& Qx,ZZn& Qy)
{
    ZZn12 w;
    ZZn4 nn,dd,cc;
    ZZn2 X,Y;

#ifdef AFFINE
    A.get(X,Y);

	if (get_mip()->TWIST==MR_SEXTIC_M)
	{
		nn.set(txx((ZZn2)-Qy),Y-slope*X);
		cc.seth(slope*Qx);
	}
	if (get_mip()->TWIST==MR_SEXTIC_D)
	{
		nn.set((ZZn2)-Qy,Y-slope*X);
		dd.set(slope*Qx);
	}
    w.set(nn,dd,cc);

#endif
#ifdef PROJECTIVE
    ZZn2 Z3;

    C.getZ(Z3);

// Thanks to A. Menezes for pointing out this optimization...
    if (Doubling)
    {
        ZZn2 Z,ZZ;
        A.get(X,Y,Z);
        ZZ=Z; ZZ*=ZZ;
		if (get_mip()->TWIST==MR_SEXTIC_M)
		{ // "multiplied across" by i to simplify
			nn.set((Z3*ZZ)*txx((ZZn2)Qy),slope*X-extra);
			cc.seth(-(ZZ*slope)*Qx);
		}
		if (get_mip()->TWIST==MR_SEXTIC_D)
		{
			nn.set((Z3*ZZ)*Qy,slope*X-extra);
			dd.set(-(ZZ*slope)*Qx);
		}
    }
    else
    {
        ZZn2 X2,Y2;
        B.get(X2,Y2);
		if (get_mip()->TWIST==MR_SEXTIC_M)
		{
			nn.set(Z3*txx((ZZn2)Qy),slope*X2-Y2*Z3);
			cc.seth(-slope*Qx);
		}
		if (get_mip()->TWIST==MR_SEXTIC_D)
		{
			nn.set(Z3*Qy,slope*X2-Y2*Z3);
			dd.set(-slope*Qx);
		}
    }
    w.set(nn,dd,cc);
#endif

     return w;
}
Example #10
0
GT PFC::multi_miller(int n,G2** QQ,G1** PP)
{
	GT z;
    ZZn *Px,*Py;
	int i,j,*k,nb;
    ECn2 *Q,*A;
	ECn P;
    ZZn12 res;
	Big m;
	Big X=*x;

	Px=new ZZn[n];
	Py=new ZZn[n];
	Q=new ECn2[n];
	A=new ECn2[n];
	k=new int[n];

	if (X<0) m=-(6*X+2);
    else m=6*X+2;

    nb=bits(m);
	res=1;

	for (j=0;j<n;j++)
	{
		k[j]=0;
		P=PP[j]->g; normalise(P); Q[j]=QQ[j]->g; Q[j].norm();
		extract(P,Px[j],Py[j]);
	}

	for (j=0;j<n;j++) A[j]=Q[j];

	for (i=nb-2;i>=0;i--)
	{
		res*=res;
		for (j=0;j<n;j++)
		{
			if (QQ[j]->ptable==NULL)
				res*=g(A[j],A[j],Px[j],Py[j]);
			else
				res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]);
		}
		if (bit(m,i)==1)
			for (j=0;j<n;j++) 
			{
				if (QQ[j]->ptable==NULL)
					res*=g(A[j],Q[j],Px[j],Py[j]);
				else
					res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]);
			}
		if (res.iszero()) return 0;  
	}

	if (X<0) res.conj();
	for (j=0;j<n;j++) 
	{	
		q_power_frobenius(Q[j],*frob);
		
		if (QQ[j]->ptable==NULL)
		{
			if (X<0) A[j]=-A[j];
			res*=g(A[j],Q[j],Px[j],Py[j]);
		}
		else
			res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]);
		q_power_frobenius(Q[j],*frob); 
		
		if (QQ[j]->ptable==NULL)
		{
			Q[j]=-Q[j];
			res*=g(A[j],Q[j],Px[j],Py[j]);
		}
		else
			res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]);
	}

	delete [] k;
	delete [] A;
	delete [] Q;
	delete [] Py;
	delete [] Px;

	z.g=res;
	return z;
}
Example #11
0
int main()
{
	for(int bits = 8; bits < 65536; bits++)
	{
		miracl* mip=&precisionBits;

		ECn P1;
		ECn2 Ppub_s,P2;
		ZZn2 X;
		Big q,N;
		// SM9
		Big t,tr;
		Big b = 5;      //方程参数
		Big cf = 1;     //余因子
		Big k = 12;     //嵌入次数
		Big _b;         //扭曲线的参数 sqrt(-2)
		Big d1 = 1;     //k 的因子 d1=1, d2=2 
		Big d2 = 2;     //k 的因子 d1=1, d2=2 
		Big cid = 0x12; //曲线识别符
		Big ks;
		Big xp1,yp1;
		ZZn2 xp2,yp2;
		Big eid = 0x04; //双线性对的识别符

		char * b_str = "05";
		char * xp1_str =       "93DE051D62BF718FF5ED0704487D01D6E1E4086909DC3280E8C4E4817C66DDDD";
		char * yp1_str =       "21FE8DDA4F21E607631065125C395BBC1C1C00CBFA6024350C464CD70A3EA616";
		char * xp2_part1_str = "85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141";
		char * yp2_part1_str = "17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96";
		char * xp2_part2_str = "3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B";
		char * yp2_part2_str = "A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7";
		char * ks_str =          "0130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4";
		char * ke_str =          "01EDEE3778F441F8DEA3D9FA0ACC4E07EE36C93F9A08618AF4AD85CEDE1C22";

		Big x0,y0;
		Big hid = 0x01;

		Big IDA;

		ZZn4 w1, w2, w3;
		ZZn2 w11, w12, w21, w22,w31,w32;
		ZZn w111,w112, w121,w122, w211,w212,w221,w222,w311,w312,w321,w322;


		mip->IOBASE=16;
		mip->TWIST=MR_SEXTIC_M;

		//  Curve 2.
		t= (char *)"600000000058F98A";  //参数t

		q=36*pow(t,4)+36*pow(t,3)+24*t*t+6*t+1; // 基域特征
		tr=6*t*t+1; // 迹
		N=q+1-tr;   // 
		cf=1;

		ks = ks_str;


		cout<<"t:"<<t<<endl;
		cout<<"q:"<<q<<endl;
		cout<<"N:"<<N<<endl;
		cout<<"cf:"<<cf<<endl;
		cout<<"k:"<<k<<endl;
		cout<<"ks:"<<ks<<endl;

		IDA = from_binary(strlen("Alice"),"Alice");
		mip->IOBASE=16;

		cout<<"IDA:"<<IDA<<endl;

#ifdef AFFINE
		ecurve((Big)0,(Big)b,q,MR_AFFINE);
#endif
#ifdef PROJECTIVE
		ecurve((Big)0,(Big)b,q,MR_PROJECTIVE);
#endif

		xp1 = xp1_str;
		yp1 = yp1_str;

		P1.set(xp1,yp1);

		cout<<"P1:"<<P1<<endl;

		{
			bool bFlag = false;

			xp2.set((Big)xp2_part2_str, xp2_part1_str);
			yp2.set((Big)yp2_part2_str, yp2_part1_str);
			bFlag = P2.set(xp2,yp2);

			cout<<"bFlag:"<<bFlag<<endl;
			cout<<"P2:"<<P2<<endl;
			if (bFlag)
			{
				cout<<"success:bits=="<<bits<<endl;
				Ppub_s = ks*P2;
				cout<<"Ppub_s:"<<Ppub_s<<endl;
			}
		}

#if 0

		Big IDA_union_hid;
		char buffer[1024];
		int pos = 0;

		pos += to_binary(IDA,1024,buffer+pos);

		pos += to_binary(hid,1024,buffer+pos);

		IDA_union_hid = from_binary(pos, buffer);

		// SM9_H1 param calc success

		cout<<"IDA_union_hid:"<<IDA_union_hid<<endl;

		Big t1 = 0;

		//calc t1

		char h1_str[1024] = {0};
		int h1_len = 1024;

		char n_str[1024];
		int n_len = 1024;

		n_len = to_binary(N,n_len, n_str);

		SM9_H1(buffer, pos,n_str,n_len, h1_str,&h1_len);

		Big h1 = from_binary(h1_len,h1_str);

		t1 = h1 + ks;

		// SM9_H1 calc success

		cout<<"t1:"<<t1<<endl;

		// t1 calc success

		Big t2 =  pow(ks * inverse(t1,N),1,N);

		cout <<"t2:"<<t2<<endl;

		// t2 calc success

		cout <<"xp1:"<<xp1<<endl;
		cout <<"yp1:"<<yp1<<endl;

		//P1.set(yp1,xp1);

		cout <<"P1:"<<P1<<endl;


		ECn dsa = t2*P1;

		cout <<"dsa:"<<dsa<<endl;

		// dsa calc success

		Big M;

		M = from_binary(strlen("Chinese IBS standard"),"Chinese IBS standard");
		cout <<"M:"<<M<<endl;
		// M calc success

		ZZn12 g;

		// R-Ate 对

		set_frobenius_constant(X);

		cout <<"X:"<<X<<endl;

		ecap(Ppub_s,P1,t,X,g);

		cout <<"g:"<<g<<endl;

		Big ww = 0;//"81377B8FDBC2839B4FA2D0E0F8AA6853BBBE9E9C4099608F8612C6078ACD7563815AEBA217AD502DA0F48704CC73CABB3C06209BD87142E14CBD99E8BCA1680F30DADC5CD9E207AEE32209F6C3CA3EC0D800A1A42D33C73153DED47C70A39D2E8EAF5D179A1836B359A9D1D9BFC19F2EFCDB829328620962BD3FDF15F2567F58A543D25609AE943920679194ED30328BB33FD15660BDE485C6B79A7B32B013983F012DB04BA59FE88DB889321CC2373D4C0C35E84F7AB1FF33679BCA575D67654F8624EB435B838CCA77B2D0347E65D5E46964412A096F4150D8C5EDE5440DDF0656FCB663D24731E80292188A2471B8B68AA993899268499D23C89755A1A89744643CEAD40F0965F28E1CD2895C3D118E4F65C9A0E3E741B6DD52C0EE2D25F5898D60848026B7EFB8FCC1B2442ECF0795F8A81CEE99A6248F294C82C90D26BD6A814AAF475F128AEF43A128E37F80154AE6CB92CAD7D1501BAE30F750B3A9BD1F96B08E97997363911314705BFB9A9DBB97F75553EC90FBB2DDAE53C8F68E42";

		cout <<"ww:"<<ww<<endl;

		Big r = "033C8616B06704813203DFD00965022ED15975C662337AED648835DC4B1CBE";

		ZZn12 w = pow(g,r);

		w.get(w1,w2,w3);

		w1.get(w11,w12);
		w2.get(w21,w22);
		w3.get(w31,w32);

		w11.get(w111,w112);
		w21.get(w211,w212);
		w31.get(w311,w312);
		w12.get(w121,w122);
		w22.get(w221,w222);
		w32.get(w321,w322);

		cout <<"w:"<<w<<endl;

		{
			char w_item[32] = {0};

			pos = 0;

			int w_item_len = 0;

			w_item_len = 32;
			w_item_len = to_binary(w322,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w321,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w312,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w311,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w222,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w221,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w212,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w211,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w122,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w121,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w112,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w111,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			ww = from_binary(pos,buffer);

			cout <<"ww:"<<ww<<endl;
		}

		pos = 0;

		char buffer2[1024] = {0};

		pos += to_binary(M,1024,buffer2 + pos);

		memcpy(buffer2+pos, buffer, 12 * 32);

		pos += 12 * 32;

		Big m_and_w = from_binary(pos,buffer2);

		cout <<"m_and_w:"<<m_and_w<<endl;

		char h2_str[1024] = {0};
		int h2_len = 1024;

		SM9_H2(buffer2, pos,n_str,n_len, h2_str,&h2_len);

		Big h = from_binary(h2_len,h2_str);

		cout <<"h:"<<h<<endl;

		Big l = (r-h + N)%N;

		cout <<"l:"<<l<<endl;


		ECn S = l * dsa;

		cout <<"S:"<<S<<endl;

		// from here verify sign 
		{
			cout <<"h1:"<<h1<<endl;
			cout <<"g"<<g<<endl;

			ECn2 P = h1 * P2 + Ppub_s;

			cout <<"P:"<<P<<endl;

			ZZn12 tv = pow(g,h);

			cout <<"tv"<<tv<<endl;

			w = tv;
			w.get(w1,w2,w3);

			w1.get(w11,w12);
			w2.get(w21,w22);
			w3.get(w31,w32);

			w11.get(w111,w112);
			w21.get(w211,w212);
			w31.get(w311,w312);
			w12.get(w121,w122);
			w22.get(w221,w222);
			w32.get(w321,w322);
			{
				char w_item[32] = {0};

				pos = 0;

				int w_item_len = 0;

				w_item_len = 32;
				w_item_len = to_binary(w322,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w321,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w312,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w311,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w222,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w221,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w212,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w211,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w122,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w121,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w112,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w111,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				Big tv2 = from_binary(pos,buffer);

				cout <<"tv2:"<<tv2<<endl;
			}

			ZZn12 u;

			ecap(P,S,t,X,u);

			cout <<"u:"<<u<<endl;

			w = u;
			w.get(w1,w2,w3);

			w1.get(w11,w12);
			w2.get(w21,w22);
			w3.get(w31,w32);

			w11.get(w111,w112);
			w21.get(w211,w212);
			w31.get(w311,w312);
			w12.get(w121,w122);
			w22.get(w221,w222);
			w32.get(w321,w322);
			{
				char w_item[32] = {0};

				pos = 0;

				int w_item_len = 0;

				w_item_len = 32;
				w_item_len = to_binary(w322,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w321,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w312,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w311,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w222,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w221,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w212,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w211,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w122,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w121,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w112,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w111,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				Big uu = from_binary(pos,buffer);

				cout <<"uu:"<<uu<<endl;
			}

			ZZn12 w_ = u * tv;

			cout <<"w_:"<<w_<<endl;

			w = w_; // w_ to string
			w.get(w1,w2,w3);

			w1.get(w11,w12);
			w2.get(w21,w22);
			w3.get(w31,w32);

			w11.get(w111,w112);
			w21.get(w211,w212);
			w31.get(w311,w312);
			w12.get(w121,w122);
			w22.get(w221,w222);
			w32.get(w321,w322);
			{
				char w_item[32] = {0};

				pos = 0;

				int w_item_len = 0;

				w_item_len = 32;
				w_item_len = to_binary(w322,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w321,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w312,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w311,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w222,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w221,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w212,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w211,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w122,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w121,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w112,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				w_item_len = 32;
				w_item_len = to_binary(w111,w_item_len,w_item);
				pos += 32 - w_item_len;
				memcpy(buffer+pos, w_item, w_item_len);
				pos += w_item_len;

				Big ww_ = from_binary(pos,buffer);

				cout <<"ww_:"<<ww_<<endl;
			}

			pos = 0;

			char buffer3[1024] = {0};

			pos += to_binary(M,1024,buffer3 + pos);

			memcpy(buffer3+pos, buffer, 12 * 32);

			pos += 12 * 32;

			Big m_and_w = from_binary(pos,buffer3);

			cout <<"m_and_w:"<<m_and_w<<endl;

			SM9_H2(buffer3, pos,n_str,n_len, h2_str,&h2_len);

			Big h2 = from_binary(h2_len,h2_str);

			cout <<"h2:"<<h2<<endl;
			cout <<"h:"<<h<<endl;

			cout <<"h2-h:"<< h2-h <<endl;
			cout <<"h-h2:"<< h-h2 <<endl;

		}



		// success for verfify
#else
		Big ke = ke_str;

		cout <<"ke:"<<ke<<endl;

		ECn Ppub_e;

		Ppub_e = ke * P1;

		cout <<"Ppub_e:"<<Ppub_e<<endl;

		// Ppub_e ok

		hid = 0x03;

		Big IDB;

		IDB = from_binary(strlen("Bob"),"Bob");

		cout <<"IDB:"<<IDB<<endl;

		Big IDB_union_hid;
		char buffer[1024];
		int pos = 0;

		pos += to_binary(IDB,1024,buffer+pos);

		pos += to_binary(hid,1024,buffer+pos);

		IDB_union_hid = from_binary(pos, buffer);

		// SM9_H1 param calc success

		cout<<"IDB_union_hid:"<<IDB_union_hid<<endl;

		Big t1 = 0;

		//calc t1

		char h1_str[1024] = {0};
		int h1_len = 1024;

		char n_str[1024];
		int n_len = 1024;

		n_len = to_binary(N,n_len, n_str);

		SM9_H1(buffer, pos,n_str,n_len, h1_str,&h1_len);

		Big h1 = from_binary(h1_len,h1_str);

		t1 = h1 + ke;

		// SM9_H1 calc success

		cout<<"t1:"<<t1<<endl;

		Big t2 =  pow(ke * inverse(t1,N),1,N);
		cout<<"t2:"<<t2<<endl;

		ECn2 deB;

		deB = t2 * P2;

		cout<<"deB:"<<deB<<endl;

		int key_wrap_len = 0x0100;

		ECn QB = h1 * P1;

		QB += Ppub_e;

		cout <<"QB:"<<QB<<endl;



		// wrapper
		Big r = "74015F8489C01EF4270456F9E6475BFB602BDE7F33FD482AB4E3684A6722";

		ECn C= r*QB;

		cout <<"C:"<<C<<endl;

		set_frobenius_constant(X);

		ZZn12 g ;

		ecap(P2,Ppub_e,t,X,g);

		cout <<"g:"<<g<<endl;

		ZZn12 w = pow(g,r);

		cout <<"w:"<<w<<endl;

		w = w;
		w.get(w1,w2,w3);

		w1.get(w11,w12);
		w2.get(w21,w22);
		w3.get(w31,w32);

		w11.get(w111,w112);
		w21.get(w211,w212);
		w31.get(w311,w312);
		w12.get(w121,w122);
		w22.get(w221,w222);
		w32.get(w321,w322);
		{
			char w_item[32] = {0};

			pos = 0;

			int w_item_len = 0;

			w_item_len = 32;
			w_item_len = to_binary(w322,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w321,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w312,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w311,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w222,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w221,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w212,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w211,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w122,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w121,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w112,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w111,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			Big ww = from_binary(pos,buffer);

			cout <<"ww:"<<ww<<endl;
		}

		pos = 0;

		char buffer2[1024] = {0};

		Big cx,cy;

		C.get(cx,cy);

		pos += to_binary(cx,1024,buffer2 + pos);

		pos += to_binary(cy,1024,buffer2 + pos);

		memcpy(buffer2+pos, buffer, 12 * 32);

		pos += 12 * 32;

		pos += to_binary(IDB,1024,buffer2 + pos);

		Big value_union = from_binary(pos,buffer2);

		cout <<"value_union:"<<value_union<<endl;

		char key_wrap_data[0x100];

		tcm_kdf((unsigned char *)key_wrap_data,key_wrap_len,(unsigned char *)buffer2,pos);

		Big K = from_binary(key_wrap_len/8, key_wrap_data);

		cout <<"K:"<<K<<endl;

		// unwrapper

		ZZn12 w_;

		ecap(deB, C,t,X,w_);

		cout <<"w_:"<<w_<<endl;

		Big ww;

		w = w_;
		w.get(w1,w2,w3);

		w1.get(w11,w12);
		w2.get(w21,w22);
		w3.get(w31,w32);

		w11.get(w111,w112);
		w21.get(w211,w212);
		w31.get(w311,w312);
		w12.get(w121,w122);
		w22.get(w221,w222);
		w32.get(w321,w322);
		{
			char w_item[32] = {0};

			pos = 0;

			int w_item_len = 0;

			w_item_len = 32;
			w_item_len = to_binary(w322,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w321,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w312,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w311,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w222,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w221,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w212,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w211,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w122,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w121,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w112,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			w_item_len = 32;
			w_item_len = to_binary(w111,w_item_len,w_item);
			pos += 32 - w_item_len;
			memcpy(buffer+pos, w_item, w_item_len);
			pos += w_item_len;

			Big ww_ = from_binary(pos,buffer);

			cout <<"ww_:"<<ww_<<endl;
		}

		pos = 0;

		pos += to_binary(cx,1024,buffer2 + pos);

		pos += to_binary(cy,1024,buffer2 + pos);

		memcpy(buffer2+pos, buffer, 12 * 32);

		pos += 12 * 32;

		pos += to_binary(IDB,1024,buffer2 + pos);

		value_union = from_binary(pos,buffer2);

		cout <<"value_union:"<<value_union<<endl;

		tcm_kdf((unsigned char *)key_wrap_data,key_wrap_len,(unsigned char *)buffer2,pos);

		Big K_ = from_binary(key_wrap_len/8, key_wrap_data);

		cout <<"K_:"<<K_<<endl;

		cout <<"K_-K:"<<K_-K<<endl;
		cout <<"K-K_:"<<K-K_<<endl;
#endif

		cout <<"success:"<<bits<<endl;

	}

	return 0;
}