MD5算法的编程实现

【实验目的】

1、理解Hash函数的计算原理和特点。
2、理解MD5算法原理。
3、了解MD5值的生成过程。

【实验环境】

windows虚拟机
在目录C:\Program Files\Microsoft Visual Studio\MyProjects\MD5下打开MD5.dsw,在VC6.0环境下编译代码。

【实验预备知识点】

MD5是一种常见的单项散列算法,用以提供消息的完整性保护,计算机界广泛使用的散列算法之一。
算法以512位分组来处理输入的信息,每一分组又被划分为16个32位子分组,经过一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后产生一个128位的散列值。

【实验内容】

MD5是输入不定长度信息,输出固定长度128bits的演算法。经过程序流程,生产四个32bit数据,最后联合起来为一个128bit散列。

【实验步骤】

MD5算法包括以下五个步骤。
1、 附加填充位
首先填充消息,使其长度为一个比512的倍数小64位的数。填充方法:在消息后面填充一位1,然后填充所需数量的0。填充位的位数从1~512。
2、 附加长度
将原消息长度的64位表示附加在填充后的消息后面。当原消息长度大于2^64时,用消息长度mod 2^64填充。这时,消息长度恰好是512的整数倍。令M[0 1…N−1]为填充后消息的各个字(每字为32位),N是16的倍数。
3、 初始化MD缓冲区
初始化用于计算消息摘要的128位缓冲区。这个缓冲区由四个32位寄存器A、B、C、D表示。寄存器的初始化值为(按低位字节在前的顺序存放):
A: 01234567
B: 89abcdef
C: fedcba98
D: 76543210
4、 按512位的分组处理输入消息
这一步为MD5的主循环,一个压缩函数是本算法的核心。它包括4轮处理。四轮处理具有相似的结构,但每次使用不同的基本逻辑函数,记为F,G,H,I。
F(X,Y,Z)=(X&Y)|((~X)&Z)
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=XYZ
I(X,Y,Z)=Y^(X|(~Z))
  这四个函数的说明:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。
   假设Mj表示消息的第j个子分组(从0到15),
  (x)<<(n)表示把x循环左移n位
   FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti))<<s)
   GG(a,b,c,d,Mj,s,ti)表示a=b+((a+(G(b,c,d)+Mj+ti))<<s)
   HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti))<<s)
   II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti))<<s)
  这四轮(64步)是:
第一轮


   FF(a,b,c,d,M0,7,0xd76aa478) 
   FF(d,a,b,c,M1,12,0xe8c7b756)
   FF(c,d,a,b,M2,17,0x242070db)
   FF(b,c,d,a,M3,22,0xc1bdceee)
   FF(a,b,c,d,M4,7,0xf57c0faf)
   FF(d,a,b,c,M5,12,0x4787c62a)
   FF(c,d,a,b,M6,17,0xa8304613)
   FF(b,c,d,a,M7,22,0xfd469501)
   FF(a,b,c,d,M8,7,0x698098d8)
   FF(d,a,b,c,M9,12,0x8b44f7af)
   FF(c,d,a,b,M10,17,0xffff5bb1)
   FF(b,c,d,a,M11,22,0x895cd7be)
   FF(a,b,c,d,M12,7,0x6b901122)
   FF(d,a,b,c,M13,12,0xfd987193)
   FF(c,d,a,b,M14,17,0xa679438e)
   FF(b,c,d,a,M15,22,0x49b40821)
     第二轮
   GG(a,b,c,d,M1,5,0xf61e2562) 
   GG(d,a,b,c,M6,9,0xc040b340)
   GG(c,d,a,b,M11,14,0x265e5a51)
   GG(b,c,d,a,M0,20,0xe9b6c7aa)
   GG(a,b,c,d,M5,5,0xd62f105d)
   GG(d,a,b,c,M10,9,0x02441453)
   GG(c,d,a,b,M15,14,0xd8a1e61)
   GG(b,c,d,a,M4,20,0xe7d3fbc8)
   GG(a,b,c,d,M9,5,0x21e1cde6)
   GG(d,a,b,c,M14,9,0xc33707d6)
   GG(c,d,a,b,M3,14,0xf4d50d87)
   GG(b,c,d,a,M8,20,0x455a14ed)
   GG(a,b,c,d,M13,5,0xa9e3e905)
   GG(d,a,b,c,M2,9,0xfcefa3f8)
   GG(c,d,a,b,M7,14,0x676f02d9)
   GG(b,c,d,a,M12,20,0x8d2a4c8a)
    第三轮
   HH(a,b,c,d,M5,4,0xfffa3942) 
   HH(d,a,b,c,M8,11,0x8771f681)
   HH(c,d,a,b,M11,16,0x6d9d6122)
   HH(b,c,d,a,M14,23,0xfde5380c)
   HH(a,b,c,d,M1,4,0xa4beea44)
   HH(d,a,b,c,M4,11,0x4bdecfa9)
   HH(c,d,a,b,M7,16,0xf6bb4b60)
   HH(b,c,d,a,M10,23,0xbebfbc70)
   HH(a,b,c,d,M13,4,0x289b7ec6)
   HH(d,a,b,c,M0,11,0xeaa127fa)
   HH(c,d,a,b,M3,16,0xd4ef3085)
   HH(b,c,d,a,M6,23,0x04881d05)
   HH(a,b,c,d,M9,4,0xd9d4d039)
   HH(d,a,b,c,M12,11,0xe6db99e5)
   HH(c,d,a,b,M15,16,0x1fa27cf8)
   HH(b,c,d,a,M2,23,0xc4ac5665)
    第四轮
   II(a,b,c,d,M0,6,0xf4292244) 
   II(d,a,b,c,M7,10,0x432aff97)
  II(c,d,a,b,M14,15,0xab9423a7)
   II(b,c,d,a,M5,21,0xfc93a039)
   II(a,b,c,d,M12,6,0x655b59c3)
   II(d,a,b,c,M3,10,0x8f0ccc92)
   II(c,d,a,b,M10,15,0xffeff47d)
   II(b,c,d,a,M1,21,0x85845dd1)
   II(a,b,c,d,M8,6,0x6fa87e4f)
   II(d,a,b,c,M15,10,0xfe2ce6e0)
   II(c,d,a,b,M6,15,0xa3014314)
   II(b,c,d,a,M13,21,0x4e0811a1)
   II(a,b,c,d,M4,6,0xf7537e82)
   II(d,a,b,c,M11,10,0xbd3af235)
   II(c,d,a,b,M2,15,0x2ad7d2bb)
   II(b,c,d,a,M9,21,0xeb86d391)

5、 常数ti的选择
  在第i步中,ti是4294967296*abs(sin(i))的整数部分,i的单位是弧度。(4294967296等于2的32次方)
  所有这些完成之后,将A、B、C、D分别加上a、b、c、d。然后用下一分组数据继续运行算法,最后的输出是A、B、C和D的级联。
6、 以下是程序的关键代码:

//MD5.c 
//MD5.c
#include<stdio.h> 
#include<Windows.h>
void dectobina(int in, int n, int *md5); 
void dectobina_tail(int in, int *md5); 
void hextobina(char *t, int *temp); 
void c_out(int *a); 
void abcd_out(int *a); 
void F(int *b, int *c, int *d, int *temp1, int *temp2); 
void G(int *b, int *c, int *d, int *temp1, int *temp2); 
void H(int *b, int *c, int *d, int *temp); 
void I(int *b, int *c, int *d, int *temp); 
void and(int *a, int *b, int *temp); 
void or(int *a, int *b, int *temp); 
void no(int *a, int *temp); 
void xor(int *a, int *b, int *temp); 
void addto(int *a, int *b, int *temp); 
void dectobina(int in, int n, int *md5) 
{
    
    int j, s, w;   
    s = n / 4 + 1; 
    w = n % 4; 
    j = 1; 
    do 
    {
    
        md5[32 * s - 8 * w - j] = in % 2; 
        in = in / 2; 
        j++; 
    } while (in != 0); 
    while (j <=8)   
    {
    
        md5[32 * s - 8 * w - j] = 0; 
        j++; 
    } 
} 
void dectobina_tail(int in, int *md5) 
{
    
    int i,j,temp, a[64]; 
    for (i = 0; in!= 0; i++) 
    {
    
        a[i] = in % 2; 
        in = in / 2; 
    } 
    while (i % 8 != 0) 
    {
    
        a[i] = 0; 
        i++; 
    } 
    for (j = 0; j <i/2; j++) 
    {
    
        temp = a[i - j - 1]; 
        a[i - j-1] = a[j]; 
        a[j] = temp; 
    } 
    temp = i/8; 
    for (i=i-1; i < 64; i++) 
        a[i] = 0; 
    for (i = 0; i < 4; i++)  
    {
    
        for (j = 0; j < 8; j++) 
            md5[512 - temp * 8 + j - 32] = a[i * 8 + j]; 
        temp = temp - 1; 
    } 
    for (i = 0; i < 4; i++) 
    {
    
        for (j = 0; j < 8; j++) 
            md5[512 - (i + 1) * 8 + j ] = a[i * 8 + j+32]; 
    } 
} 
void hextobina(char *t, int *temp) 
{
    
    int i; 
    for (i = 0; i < 8; i++) 
    {
    
        switch (t[i]) 
        {
    
        case '0':{
   temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 0; }break; 
        case '1':{
   temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 1; }break; 
        case '2':{
   temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 1; temp[4 * i + 3] = 0; }break; 
        case '3':{
   temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 1; temp[4 * i + 3] = 1; }break; 
        case '4':{
   temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 0; temp[4 * i + 3] = 0; }break; 
        case '5':{
   temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 0; temp[4 * i + 3] = 1; }break; 
        case '6':{
   temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 1; temp[4 * i + 3] = 0; }break;  
        case '7':{
   temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 1; temp[4 * i + 3] = 1; }break; 
        case '8':{
   temp[4 * i] = 1; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 0; }break; 
        case '9':{
   temp[4 * i] = 1; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 1; }break; 
        case 'a':{
   temp[4 * i] = 1; temp[4 * i + 1<
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值