www.pudn.com > RSA.rar > Rsa.cpp


 
// RsaA.cpp : implementation file 
// 
 
#include "stdafx.h" 
 
#include "Rsa.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CRsaA 
 
IMPLEMENT_DYNCREATE(CRsaA, CCmdTarget) 
 
CRsaA::CRsaA() 
{ 
	InitInt(); 
		 
} 
 
CRsaA::~CRsaA() 
{ 
 
} 
 
 
BEGIN_MESSAGE_MAP(CRsaA, CCmdTarget) 
	//{{AFX_MSG_MAP(CRsaA) 
		// NOTE - the ClassWizard will add and remove mapping macros here. 
	//}}AFX_MSG_MAP 
		//ON_MESSAGE(WM_COMPUTING,OnComputing) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CRsaA message handlers 
 
/*---------------------------------------------------------------------------- 
功能:进行相关大数的初始化 
入口参数:无 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::InitInt(void) 
{ 
	SetZero(ZEROVALUE);						//对大数变量zerovalue清零 
	memset(mZEROVALUE,0,MLENGTH); 
	SetZero(ONEVALUE);                      //对大数变量ONEVALUE进行清零 
	ONEVALUE[DATALENGTH-1]=1;				//ONEVALUE的最后一位为1 
	SetZero(TWOVALUE);						//将TOWVALUE进行清零 
    TWOVALUE[DATALENGTH-1]=2;				//TOWVALUE的最后一位为2 
	SetZero(EIGHTVALUE);					//对EIGHTVALUE进行清零 
    EIGHTVALUE[DATALENGTH-1]=8;				//最后一位为8 
	return ; 
} 
 
/*--------------------------------------------------------------------------- 
功能:将一个大数A转换为相应的字符串形式 
入口参数:大数A 
返回值:相对应的字符串 
----------------------------------------------------------------------------*/ 
CString CRsaA::PrtInt(byteint A) 
{ 
	register i=0; 
	int m,n; 
	while(iC 
入口参数:被乘数A和乘数B,结果C 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::Multiply(byteint A,byteint B,byteint C) 
{ 
	register i,j,w; 
	int X,Y,Z; 
	int Avalid=0;								//Avalid=validating bits of A 
	int Bvalid=0;								//Avalid=validating bits of B 
	while (A[Avalid]==0 && Avalid=Avalid;i--) 
		for(j=DATALENGTH-1;j>=Bvalid;j--)       //逐位进行相乘运算 
		{ 
			X=A[i]*B[j];         
			Y=X/10; 
			Z=X-10*Y; 
			w=i+j-(DATALENGTH-1); 
			C[w]=C[w]+Z; 
			C[w-1]=C[w-1]+(C[w]/10)+Y; 
			C[w]=C[w]-(C[w]/10)*10; 
		} 
	return; 
} 
 
/*--------------------------------------------------------------------------- 
功能:将指定的自定义的大数进行0初始化 
入口参数:大数A名 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::SetZero(byteint A)   
{ 
	memset(A,0,DATALENGTH);                    //调用系统函数进行初始化 
} 
 
/*--------------------------------------------------------------------------- 
功能:将大数B拷贝到大数A中 
入口参数:大数A,大数B 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::IntCpy(byteint A,byteint B) 
{ 
	memcpy(A,B,DATALENGTH);                    //调用系统函数完成拷贝 
} 
 
/*--------------------------------------------------------------------------- 
功能:A+B的结果送C 
入口参数:大数A,B,C 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::Plus(byteint A,byteint B,byteint C) 
{ 
	register i;//,w; 
	int X,Y,Z,m,n,valid; 
	m=IntValid(A);                 //计算A的长度          
	n=IntValid(B);                 //计算B的长度 
	valid=(m>n)?m+1:n+1;           //计算时要以最长的数为准 
	SetZero(C);                    //将C清零 
	for(i=DATALENGTH-1;i>=DATALENGTH-valid;i--) 
	{ 
		X=A[i]+B[i];               //按位相加 
		Y=X/10; 
		Z=X-10*Y; 
 
		C[i]=C[i]+Z;               //计算进位 
		C[i-1]=C[i-1]+Y; 
	} 
} 
 
/*--------------------------------------------------------------------------- 
功能:大数SA减去大数SB,结果放入SC 
入口参数:被减数SA,减数SB,差SC 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::Substract(byteint SA,byteint SB,byteint SC) 
{ 
	byteint buf; 
	register i,j; 
	int X; 
	IntCpy(buf,SA);                  //将SA的内容拷贝到buf中 
	SetZero(SC);                 //SC清零初始化 
	for(i=DATALENGTH-1;i>=0;i--)	 
	{ 
		if(buf[i]0)           //如果高位够减,直接减1 
				(buf[i-1])--;     
			else                     //否则一直找到够减的位 
			{ 
				j=i-1; 
				while(buf[j]==0)     //j不会出现越界,是因为保证了最高位不为0 
					buf[j--]=9; 
				buf[j]=buf[j]-1; 
			} 
		} 
		X=buf[i]-SB[i];              //将各位减的结果存入SC中 
		SC[i]=X; 
	} 
} 
 
/*--------------------------------------------------------------------------- 
功能:比较两个大数A和B的大小 
入口参数:大数A和大数B 
返回值:A>B:return 1 ; A=B:return 0 ; A0) 
		return 1; 
	return -1; 
} 
 
/*--------------------------------------------------------------------------- 
功能:得到一个大数的非零位数 
入口参数:大数validtemp 
返回值:大数中非零的位数 
----------------------------------------------------------------------------*/ 
int CRsaA::IntValid(byteint validtemp) 
{ 
	register i=0; 
	while(validtemp[i]==0 && i0)     //变除法为减法,每减一次就判断是否有C>B,如果满足就继续减。 
	{ 
		valid_1=IntValid(C);          //计算C(被除数)的位数,因为它的位数在循环过程中是变化的 
		                              //做减法后(C-B)仍然存放在C中 
		valid=valid_1-valid_2;        //C的长度与B的长度的差(该值最小为0) 
		if(valid>0)                   //如果被除数比除数的位数多 
		{ 
			i=DATALENGTH-valid_1;     //被除数前导零的个数 
			j=DATALENGTH-valid_2;     //除数前导零的个数,作下标指示器 
			sbits=0; 
			for(k=j;kB[j])         //从C和B的最高位开始依次比较对应位的大小,判断是否够减 
					break; 
				if(C[i]=DATALENGTH-num+1)            //循环产生从次低位开始到次高位的所有位上的数 
		RandomA[i--]=rand()%10; 
} 
 
/*--------------------------------------------------------------------------- 
功能:将质数类型B拷贝到A中,实现类型转换 
入口参数:大数A,质数类型B 
返回值:无 
----------------------------------------------------------------------------*/ 
//功能:将数B拷贝到大数A,实现类型转换 
void CRsaA::LoadInt(byteint A,mtype B) 
{ 
	register i,j; 
	SetZero(A);                  //A进行清零初始化 
	i=DATALENGTH-1; 
	j=MLENGTH-1; 
	while(j>0)                   //循环拷贝各位数字 
	{ 
		A[i--]=B[j--]; 
	} 
} 
 
/*--------------------------------------------------------------------------- 
功能:该函数用来从集合[1,b-1]中产生若干个用于检测的数,存放在Model[]中 
入口参数:无 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::Mdata() 
{ 
	register i,j;                     //Randomly choose a set of 100 numbers in [1,b-1] 
	int k=MLENGTH-2; 
	 
	memset(Model,0,TESTNUM*MLENGTH);  //这个函数在这里用来将整个数组清零,进行初始化 
	srand( (unsigned)time( NULL ) );  //进行随机函数的初始化 
	for(i=0;i=k;j--) 
		{ 
			Model[i][j]=rand()%10;    //注意这里与测试素数的程序中的区别, 
		} 
		if((memcmp(Model[i],mZEROVALUE,MLENGTH))==0)   
			i--; 
		k--;                          //保证所产生的数不为0 
		if (k<0) k=MLENGTH-2; 
	} 
	 
} 
 
/*--------------------------------------------------------------------------- 
功能:该函数用来将十进制的大整数转换成二进制的数 
入口参数:需转换的大数B,二进制结果flag[400] 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::TransBi(byteint B,signed char flag[400]) 
{ 
	byteint buf; 
	byteint result; 
	byteint temp; 
	register i; 
	SetZero(buf);  SetZero(result);  SetZero(temp); 
	memset(flag,0,400);                     //将flag数组清零 
 
	i=399; 
	IntCpy(buf,B);                          //将B拷贝到buf中 
	while(IntCmp(buf,ZEROVALUE)==1)         //如果buf内容为0 
	{ 
		SetMode(buf,TWOVALUE,temp,result);  //将buf进行大数的模2运算,商在result中,余数temp 
		flag[i]=temp[DATALENGTH-1];          
		IntCpy(buf,result);                 //对商继续进行模2运算 
		i--; 
	} 
	flag[i]=-1;                             //设置一个标志位,表明二进制数的开始 
} 
 
/*--------------------------------------------------------------------------- 
功能:该函数用来进行模幂算法,A为底数,模为c,二进制的指数B存放在数组flag中 
入口参数:底数A,模C,结果D,二进制质数flag[400] 
返回值:A^B=1(mod C),返回1;A^B=p-1(mod C),返回2;否则返回0 
----------------------------------------------------------------------------*/ 
int CRsaA::PowerMode(byteint A,byteint C,byteint D,signed char flag[400]) 
{ 
	byteint buf; 
	byteint result; 
	byteint temp,P; 
	register i; 
	SetZero(D);   SetZero(buf); SetZero(result); SetZero(temp); SetZero(P);  //将D清零 
 
	IntCpy(temp,A);                       //将A的值拷贝到temp中 
	if(flag[399]==1)                      //最低位为1,拷贝本身,flag[i]只有1或者0两种情况 
		IntCpy(result,A); 
	else								  //最低位为0,则幂为1 
		IntCpy(result,ONEVALUE); 
	i=398; 
	while(flag[i]!=-1)                    //判断是否已经到达指数尽头 
	{ 
		Multiply(temp,temp,buf);          //temp*temp->buf  
		SetMode(buf,C,temp,P);            //buf%c余数->temp,商->p 
		if(flag[i]!=0)                    //如果该位不是0,则将其和前一步低一位的结果进行乘法运算 
		{                                 //否则,将其作为该位的模,在高一位的运算中,只要进行一次 
			Multiply(temp,result,buf);    //平方运算,就可以得到高一位的模 
			SetMode(buf,C,result,P); 
		} 
		i--; 
	}                                     //result中存放的是最终结果 
	IntCpy(buf,C); 
	IntCpy(D,result); 
	Substract(buf,ONEVALUE,temp); 
	if(IntCmp(result,ONEVALUE)==0)        //p mod n=1,判断是否有A^B=1(mod C) 
		return 1; 
	if(IntCmp(result,temp)==0)            //p mod n=-1[p-1=-1(mod p)],判断是否有A^B=p-1(mod C) 
		return 2; 
	return 0; 
} 
 
/*--------------------------------------------------------------------------- 
功能:产生一个质数 
入口参数:大数Prm 
返回值:产生成功,返回0 
----------------------------------------------------------------------------*/ 
int CRsaA::Prime(byteint Prm) 
{ 
	int i,k,ok; 
	signed char flag[400]; 
	byteint A,B,D,buf1,buf2; 
	SetZero(A); SetZero(B); SetZero(D); SetZero(buf1); SetZero(buf2); 
	 
	while(1)                                 //一直循环直到找到一个素数为止 
	{ 
		int pass=0; 
		srand( (unsigned)time( NULL ) );     //初始化srand 
		IntRandom(B,MLENGTH);                //随机产生一个大数B  try b if prime,B是一个奇数 
 
		IntCpy(Prm,B);                       //将B拷贝到prm中 C=N result prime 
		Substract(B,ONEVALUE,buf1);          //将B-ONEVALUE的结果放到buf1中 
		SetMode(buf1,TWOVALUE,buf2,B);       //B=(B-1)/2的商,buf2=(B-1)/2的余数=0 
		TransBi(B,flag);                     //将B转换为二进制大数 
		ok=1; 
		for(i=0;iD 
			if(k!=1 && k!=2)                 //不符合判定规则 
			{ 
				ok=0; 
				break; 
			} 
			if(k==1)                         //判定条件1,G=A^(n-1)/2=1 
			{ 
			} 
			if(k==2)                         //判定条件2,G=A^(n-1)/2=p-1 
			{ 
			} 
		 
		} 
		if (ok)//if(ok && pass_2) 
		{ 
			return 0; 
		}//for循环用来检测IntRandom(B,MLENGTH)产生的数B是否是一个素数	 
	} 
} 
 
/*--------------------------------------------------------------------------- 
功能:计算公钥PK 
入口参数:$(r)的值在Rvalue中,私钥SK,公钥PK 
返回值:成功找到,返回1 
----------------------------------------------------------------------------*/ 
int CRsaA::ComputingPK(byteint Rvalue,byteint SK,byteint PK) 
{ 
	register i; 
	byteint PA,PB,PC,buf1,temp,buf2; 
	SetZero(PK); SetZero(PA); SetZero(PB); SetZero(PC); SetZero(buf1);   //清零初始化 
	SetZero(temp); SetZero(buf2); 
	while(1) 
	{ 
		IntRandom(SK,SKLENGTH);        //随机产生一个大数奇数作为Generated secret key 
 
		IntCpy(PB,SK); 
		IntCpy(PA,Rvalue); 
		while(1) 
		{ 
			SetMode(PA,PB,PC,PK);     //PA=PB*PK+PC 
			i=IntCmp(PC,ONEVALUE); 
			if(i==0)                  //PC=1, i=0 
				break;                //满足条件,是互质的 
			i=IntCmp(PC,ZEROVALUE); 
			if(i==0) 
			{ 
				i=-1;                 //PC=0,i=-1 
				break;                //不满足互质条件,跳出循环,从新生成一个随机数 
			} 
			IntCpy(PA,PB);            //按照欧几里的定理继续判断 
 
			IntCpy(PB,PC); 
		} 
		if(i==0)                      //满足,跳出查找循环 
			break; 
	} 
 
	IntCpy(temp,ONEVALUE); 
	IntCpy(PA,Rvalue); 
	IntCpy(PB,SK); 
	while(1) 
	{ 
		Multiply(PA,temp,buf1);  //buf1=PA*temp 
		Plus(buf1,ONEVALUE,buf2);//buf2=(PA*temp)+1 
		SetMode(buf2,PB,buf1,PK);//buf=((PA*temp)+1)%PB 
		if(IntCmp(buf1,ZEROVALUE)==0) 
			break; 
		Plus(temp,ONEVALUE,buf1); 
		IntCpy(temp,buf1); 
	} 
	return 1;                   //SK and PK found 
} 
 
 
/*--------------------------------------------------------------------------- 
功能:计算模R 
入口参数:产生的质数p,q,模R 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::ComputingR(byteint p,byteint q,byteint R) 
{ 
	Multiply(p,q,R);              // R=p*q, public mode number 
} 
 
/*--------------------------------------------------------------------------- 
功能:计算$(r) 
入口参数:质数p,质数q,模$(r)放在Rvalue 
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::ComputingRvalue(byteint p,byteint q,byteint Rvalue) 
{ 
	byteint buf1,buf2; 
	SetZero(buf1); SetZero(buf2); 
 
	Substract(p,ONEVALUE,buf1);   // buf1=p-1 
	Substract(q,ONEVALUE,buf2);   // buf2=q-1 
	Multiply(buf1,buf2,Rvalue);   // Rvalue=(p-1)*(q-1) 
} 
 
/*--------------------------------------------------------------------------- 
功能:将接受的字符串转换为大数类型 
入口参数:大数result,字符串input 
返回值:数的长度 
----------------------------------------------------------------------------*/ 
int CRsaA::Getinput(byteint result,CString input) 
{ 
	int i=DATALENGTH,m=0; 
	long strlen; 
	strlen=input.GetLength(); 
	 
	if(strlen==0) return 0; 
	else 
	{ 
		for(int j=0;j='0'&&(*(pstr+3-i))<='9') 
			j = (*(pstr+3-i)) - '0'; 
		if( (*(pstr+3-i))>='a'&&(*(pstr+3-i))<='f')  
			j = (*(pstr+3-i)) - 'a'+10; 
		if( (*(pstr+3-i))>='A'&&(*(pstr+3-i))<='F') 
			j = (*(pstr+3-i)) - 'A'+10;*/ 
		ch += j*k; 
		k*=256; 
	} 
	return ch; 
}  
 
/*--------------------------------------------------------------------------- 
功能:将数串转换为相应的字符串 
入口参数:字符串str 
返回值:返回转换的结果; 
----------------------------------------------------------------------------*/ 
CString CRsaA::Ip2os(CString str) 
{ 
	int strlen=str.GetLength(),quotient=0,remainder=0; 
	unsigned long num=0,temp=0; 
	unsigned int k=1; 
	CString strResult=""; 
 
	for(int i=strlen;i>0;i--)  //得到相应的数字串,存放在num中 
	{ 
		temp = (str.GetAt(i-1) - '0'); 
			num += temp*k; 
		k *= 10; 
	} 
	//采用模除的方式,求得相应的十六进制数 
	for(int j=0;j<4;j++) 
	{ 
		quotient = num/256; 
		remainder = num - quotient*256; 
		/*if(remainder>=0&&remainder<=9) 
			strResult.Insert(0,(remainder+'0')); 
		if(remainder>=10&&remainder<=15) 
			strResult.Insert(0,(remainder-10+'a'));*/ 
		strResult.Insert(0,(unsigned char)remainder); 
		num = quotient; 
	} 
	 
	return strResult;  
} 
 
/*--------------------------------------------------------------------------- 
功能:产生RSA秘钥对 
入口参数:存放结果的字符串地址  
返回值:无 
----------------------------------------------------------------------------*/ 
void CRsaA::GenKeys(CString& pk,CString& sk,CString& R) 
{ 
	byteint m_p,m_q,m_R,m_Rvalue,m_PK,m_SK; 
	SetZero(m_p);      //对大数变量进行清零初始化 
	SetZero(m_q); 
    SetZero(m_R); 
    SetZero(m_Rvalue); 
    SetZero(m_PK); 
    SetZero(m_SK); 
 
	///Mdata();         //生成比较数表 
	/*AfxMessageBox("开始计算质数P..."); 
	Prime(m_p);        //生成素数p q 
	AfxMessageBox("开始计算质数Q..."); 
	Prime(m_q);*/ 
    int i; 
	int k_p[]={3,4,0,2,8,2,3,6,6,9,2,0,9,3,8,4,6,3,4,6,3,3,7,4,6,0,7,4,3,1,7,6,8,2,1,1,2,9,7}; 
	int k_q[]={2,5,5,2,1,1,7,7,5,1,9,0,7,0,3,8,4,7,5,9,7,5,3,0,9,5,5,5,7,3,8,2,6,1,5,8,5,7,9}; 
	 
	 
	 
	for(i = 0; i< 39; i++) 
	{ 
		m_p[256-i] = k_p[38-i]; 
		m_q[256-i] = k_q[38-i]; 
	} 
 
 
	AfxMessageBox("开始计算模R..."); 
	ComputingR(m_p,m_q,m_R); //计算模R 
	AfxMessageBox("开始计算模r"); 
	ComputingRvalue(m_p,m_q,m_Rvalue);  //计算r 
	AfxMessageBox("开始计算秘钥SK,PK"); 
	ComputingPK(m_Rvalue,m_PK,m_SK);    // Generate PK and SK 
	 
	//CGenKeyBusyDlg dlg1; 
	//g1.DoModal(); 
	R=PrtInt(m_R); 
	pk=PrtInt(m_PK); 
	sk=PrtInt(m_SK); 
	return ; 
 
} 
 
/*--------------------------------------------------------------------------- 
功能:实现加密功能接口 
入口参数:明文字符串source,模字符串R,秘钥字符串key,结果字符串数组result 
返回值:无 
----------------------------------------------------------------------------*/ 
int CRsaA::RsaEncrypt(CString& source,const char *key,const char *R,CStringArray& result) 
{ 
	unsigned char* pstr; 
	int j;//sourcelen,j; 
	byteint m_key,m_R,desti,aa; 
	SetZero(desti);                         //将大数变量清零初始化 
	SetZero(aa); 
	//SetZero(bb); 
	SetZero(m_key); 
	SetZero(m_R); 
 
	pstr = (unsigned char*)(LPCTSTR)source; //得到字符串数据的指针 
	j = source.GetLength()/4;               //得到数组的元素个数 
 
	result.SetSize(j,1); 
	Getinput(m_key,key);                    //将字符串转换为大数类型 
	Getinput(m_R,R); 
	 
	for(int i=0;i