//通过以下两个函数可获得两个大素数,但增加了计算复杂性,为了方便,直接给定素数
// // }
3.2.2 产生消息摘要的设计实现
计算消息摘要的理论实现流程图如图3-2所示:
初始化MD5所需的常量 m_Prime1 = FindPrime(1); m_Prime2 = FindPrime(m_Prime1);
m_Prime1=47; m_Prime2=71;
计算所需的追加长度 对原始信息进行补位 将输入分成512位的块 循环处理块
得到消息摘要
图3-2 消息摘要计算流程
在以上流程图中其中循环处理块是最重要的一步,也是MD5的核心算法,在这一步中包括了:
(1)把四个连接变量复制到了四个变量a,b,c,d中,使a=A,b =B,c =C,d=D;其中a,b,c,d组合成128位的寄存器,且在实际算法运算中保存中间结果和最终结果;
(2)将当前的512位块分解为16个子块,每个子块为32位;
(3)要循环四轮,每一轮处理一个块中的16个子块,四轮的第一步进行不
第 10 页
同的处理,其他的相同:每一轮有16个输入子块M[0],M[1],…………..M[15],或表示为M[i],其中i为0-15;t是常量数组,包含64个元素,每个元素为32位,数组t表示为t[1],t[2],………t[64],或t[k],k为1-64;
MD5的循环四轮操作过程用下式表示: a=b+((a+proccessP(b,c,d)+M[i]+T[k])<<
int i;int Index; //初始化MD5所需常量 //计算追加长度
Init();
Append(WriteMessage.length()); //对原始信息进行补位
for( i=0;i if(i==0) WriteMessage+=(unsigned char)0x80; else WriteMessage+=(unsigned char)0x0; //将原始信息长度附加在补位后 的数据后面 for( i=0;i<8;i++) WriteMessage+=m_MsgLen[i]; //位块数组 unsigned char x[64]={0}; //循环,将原始信息以64字节为一组拆分进行处理 for( i=0,Index=-1;i x[++Index]=WriteMessage[i]; if(Index==63) { } Index=-1; Transform(x); //将64字节位转换为16个字节 //将寄存器ABCD的最终值转换为16进制返回给用户 第 11 页 return ToHex(UpperCase); 3.2.3 数字签名的设计实现 数字签名的理论实现流程图如图3-3所示,数字签名,就是通过在数据单元上附加数据,或对数据单元进行加密变换,从而使接收者可以确认数据来源和完整性。数字签名是防止他人对传输的文件进行破坏,以及确定发信人的身份的手段。数字签名中的加密算法就是应用的RSA加密原理,而它的验证算法则是应用的RSA解密原理。 开始 得到消息摘要MD 用私钥d 加密MD 得到数字签名 结束 图3-3 数字签名的实现流程 RSA的加密、解密过程都为求一个整数的整数次幂,再取模。如果按其含义直接计算,则中间结果非常大,有可能超出计算机所允许的整数取值范围。为了减小中间结果和提高加、解密运算中指数运算的有效性,本设计采用了快速指数算法。它的运算过程为(假如要算a^m mod n): 1)将m表示为二进制的形式; 2)初始化c=0,d=1,c在这里表示指数的部分结果,它的终值即为指数m, 第 12 页 d是中间结果,它的终值即为所求结果; 3)从二进制数的最高位到最低位开始对每一位都用公式1进行运算,得到的d为该步的结果,公式1:c=2*c;d=fmod(d*d,n); 4)若二进制数是1,则在上面的运算后继续以下运算:c=c+1;d=fmod(d*a,n);得到的结果d才为该步的最终结果。 数字签名主要实现过程的代码如下: //消息摘要,8位为一组 一个字符一组 char message[200]; //从文本框中得到消息摘要 m_message.GetWindowText(message,200); len=strlen(message); char showstr[1000]=\int NO_BITS=32; double c=0,d=1; char bits[100]; double n=(double)m_n; unsigned char ch; double data;//19; long i,k=NO_BITS; int sizeof_d=sizeof(double); //将十进制数私钥d转换为二进制 D_to_B(m_d,32,bits); //得到合适的字节 GetOnlyProperBits(bits); k=NO_BITS = strlen(bits)-1; for(int ii=0;ii // 从message中读取字符放入'data'中 ch=message[ii]; data =(double)ch; //计算 ((data)^d mod n) 快速指数算法的实现 c=0;d=1; for(i=k;i>=0;i--) { 第 13 页 } c=2*c; d=fmod(d*d,n); if(bits[NO_BITS-i] == '1') { c=c+1; d=fmod(data*d,n); } // 从'd'中读取字符放入result中 result[ii]=d; strcat(showstr,longtohex(d)); //把字符串变为十六进制数后连接字符串 }//结束循环 m_result.SetWindowText(showstr); } //显示结果 //字符串变为16进制数的函数的实现 longtohex(long x) { char str[8]; int i=0; int a; int b; long tt=x; while(tt>=16) { a=tt/16; b=tt; switch(b) { case 0 : str[i]='0'; break; case 1 : str[i]='1'; break; //商 //余数 第 14 页