MD5消息摘要算法

既然准备从事信息安全行业,那么就先一步步打牢基础吧。

MD5特点

1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。

2、容易计算:从原数据计算出MD5值很容易。

3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。

4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

MD5原理:

对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

1.填充

  在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448,并且填充必须进行,即使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N*512+448,N为一个非负整数,N可以是零。

填充的方法如下:

  1) 在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。

  2) 在这个结果后面附加一个以64位二进制表示的填充前信息长度(单位为Bit),如果二进制表示的填充前信息长度超过64位,则取低64位。

  经过这两步的处理,信息的位长=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。

2. 初始化变量

  初始的128位值为初试链接变量,这些参数用于第一轮的运算,以大端字节序来表示,他们分别为: A=0x01234567,B=0x89ABCDEF,C=0xFEDCBA98,D=0x76543210。

(每一个变量给出的数值是高字节存于内存低地址,低字节存于内存高地址,即大端字节序。在程序中变量A、B、C、D的值分别为0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476)

3. 处理分组数据

每一分组的算法流程如下:

  第一分组需要将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。从第二分组开始的变量为上一分组的运算结果,即A = a, B = b, C = c, D = d。

主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向左环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。

以下是每次操作中用到的四个非线性函数(每轮一个)。

  F( X ,Y ,Z ) = ( X & Y ) | ( (~X) & Z )

  G( X ,Y ,Z ) = ( X & Z ) | ( Y & (~Z) )

  H( X ,Y ,Z ) =X ^ Y ^ Z

  I( X ,Y ,Z ) =Y ^ ( X | (~Z) )

这四个函数的说明:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。

F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。

假设Mj表示消息的第j个子分组(从0到15),常数ti是4294967296*abs( sin(i) )的整数部分,i 取值从1到64,单位是弧度。(4294967296=232

现定义:

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 ,0xd8a1e681 )

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 )

所有这些完成之后,将a、b、c、d分别在原来基础上再加上A、B、C、D。

即a = a + A,b = b + B,c = c + C,d = d + D

然后用下一分组数据继续运行以上算法。

MD5算法:

  1 #include<iostream>
  2 #include<string>
  3 using namespace std;
  4 #define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位
  5 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  6 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  7 #define H(x, y, z) ((x) ^ (y) ^ (z))
  8 #define I(x, y, z) ((y) ^ ((x) | (~z)))
  9 #define A 0x67452301
 10 #define B 0xefcdab89
 11 #define C 0x98badcfe
 12 #define D 0x10325476
 13 //strBaye的长度
 14 unsigned int strlength;
 15 //A,B,C,D的临时变量
 16 unsigned int atemp;
 17 unsigned int btemp;
 18 unsigned int ctemp;
 19 unsigned int dtemp;
 20 //常量ti unsigned int(abs(sin(i+1))*(2pow32))
 21 const unsigned int k[]={
 22         0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
 23         0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
 24         0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
 25         0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
 26         0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
 27         0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
 28         0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
 29         0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
 30         0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
 31         0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
 32         0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
 33         0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
 34         0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};
 35 //向左位移数
 36 const unsigned int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
 37         12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
 38         4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
 39         15,21,6,10,15,21,6,10,15,21,6,10,15,21};
 40 const char str16[]="0123456789abcdef";
 41 void mainLoop(unsigned int M[])
 42 {
 43     unsigned int f,g;
 44     unsigned int a=atemp;
 45     unsigned int b=btemp;
 46     unsigned int c=ctemp;
 47     unsigned int d=dtemp;
 48     for (unsigned int i = 0; i < 64; i++)
 49     {
 50         if(i<16){
 51             f=F(b,c,d);
 52             g=i;
 53         }else if (i<32)
 54         {
 55             f=G(b,c,d);
 56             g=(5*i+1)%16;
 57         }else if(i<48){
 58             f=H(b,c,d);
 59             g=(3*i+5)%16;
 60         }else{
 61             f=I(b,c,d);
 62             g=(7*i)%16;
 63         }
 64         unsigned int tmp=d;
 65         d=c;
 66         c=b;
 67         b=b+shift((a+f+k[i]+M[g]),s[i]);
 68         a=tmp;
 69     }
 70     atemp=a+atemp;
 71     btemp=b+btemp;
 72     ctemp=c+ctemp;
 73     dtemp=d+dtemp;
 74 }
 75 /*
 76 *填充函数
 77 *处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
 78 *填充方式为先加一个1,其它位补零
 79 *最后加上64位的原来长度
 80 */
 81 unsigned int* add(string str)
 82 {
 83     unsigned int num=((str.length()+8)/64)+1;//以512位,64个字节为一组
 84     unsigned int *strByte=new unsigned int[num*16];    //64/4=16,所以有16个整数
 85     strlength=num*16;
 86     for (unsigned int i = 0; i < num*16; i++)
 87         strByte[i]=0;
 88     for ( i=0; i <str.length(); i++)
 89     {
 90         strByte[i>>2]|=(str[i])<<((i%4)*8);//一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息
 91     }
 92     strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8);//尾部添加1 一个unsigned int保存4个字符信息,所以用128左移
 93     /*
 94     *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
 95     */
 96     strByte[num*16-2]=str.length()*8;
 97     return strByte;
 98 }
 99 string changeHex(int a)
100 {
101     int b;
102     string str1;
103     string str="";
104     for(int i=0;i<4;i++)
105     {
106         str1="";
107         b=((a>>i*8)%(1<<8))&0xff;   //逆序处理每个字节
108         for (int j = 0; j < 2; j++)
109         {
110             str1.insert(0,1,str16[b%16]);
111             b=b/16;
112         }
113         str+=str1;
114     }
115     return str;
116 }
117 string getMD5(string source)
118 {
119     atemp=A;    //初始化
120     btemp=B;
121     ctemp=C;
122     dtemp=D;
123     unsigned int *strByte=add(source);
124     for(unsigned int i=0;i<strlength/16;i++)
125     {
126         unsigned int num[16];
127         for(unsigned int j=0;j<16;j++)
128             num[j]=strByte[i*16+j];
129         mainLoop(num);
130     }
131     return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));
132 }
133 unsigned int main()
134 {
135     string ss;
136 //    cin>>ss;
137     string s=getMD5("abc");
138     cout<<s;
139     return 0;
140 }

MD5总结:

时间: 2024-10-10 12:35:59

MD5消息摘要算法的相关文章

MD5 消息摘要算法5

一.MD5定义 MD5即Message-Digest Algorithm 5(消息-摘要算法5),为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护(又译摘要算法.哈希算法),主流编程语言普遍已有MD5实现.将数据运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2.MD3和MD4. 也有说法MD5不是加密算法, 因为如果目的是加密,必须满足的一个条件是加密过后可以解密.但是MD5是无法从结果还原出原始数据的. 二.MD5特点 1.压缩性:任意长度的数据,算出的MD5值

【转】使用C语言实现MD5消息摘要算法

md5.h文件 // // Created by Alex on 2015/11/24. // #ifndef CLION_WORK_MD5_H #define CLION_WORK_MD5_H typedef struct { unsigned int count[2]; unsigned int state[4]; unsigned char buffer[64]; }MD5_CTX; #define F(x,y,z) ((x & y) | (~x & z)) #define G(x,

密码学4——Java 加密解密之消息摘要算法(MD5 SHA MAC)

Java 加密解密之消息摘要算法(MD5 SHA MAC) 消息摘要 消息摘要(Message Digest)又称为数字摘要(Digital Digest).它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了.因此消息摘要保证了消息的完整性.消息摘要采用单向Hash 函数将需加密 的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(

97 加密算法与消息摘要算法

一 加密算法 应用于数据传输 通过算法,可以得到加密前的数据 二 消息摘要算法 应用于数据校验,比如文件完整性验证,存储密码 根据算法获得的结果长度是固定的,不同的算法有不同的数据长度 有不同消息获得同样运算结果,但概率极低 相同的数据通过同一个算法获得的结果一定相同 所以我们在说数据库存储用户密码时,要使用消息摘要算法而不是加密算法, 因为加密算法是可逆的,而消息摘要算法是不可逆的.这样,即使在数据库泄漏时,也不会暴露密码. 我们存储用户通过算法后得到的数据,当用户登录时,通过此算法对用户输入

第三章 消息摘要算法--MD5

注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第6章“验证数据完整性--消息摘要算法” 3.1.消息摘要算法:防止消息在传递过程中被篡改. 原理:任何消息经过消息摘要算法后,都会产生唯一的散列值(即“数据指纹”)(同一段消息无论经过多少次相同的消息摘要算法加密,结果都相同),所以如果消息在传送过程中被修改,那么算出来的数据指纹也与原本的消息算出来的不同了,如果没有被修改,则数据指纹是相同的. 特点:单向性(即只有加密,没有解密) 3.2.MD5(算法已被破解,应用于安全程度要求

MD5 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)

MD5 编辑 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992). MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑

第四章 消息摘要算法--SHA

注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第6章“验证数据完整性--消息摘要算法” 4.1.SHA 原理:消息摘要长度(可以定量为加密后的字符串的长度)越长,安全性越高 MD5:128位二进制摘要(32位16进制字符串)(已破解) SHA1:160位二进制摘要(40位16进制字符串)(已破解) SHA256:256位二进制摘要(64位16进制字符串)(常用,在spring security中也有使用到) 实现方式: Commons Codec(“CC”,最推荐,因为封装了J

Apache Commons Codec 与消息摘要算法(hash算法)

首先我们要明白 Codec 是什么含义.它是 Coder + decoder = Codec,也就是编码器解码器.即是编码器,也是解码器. 官网地址:http://commons.apache.org/proper/commons-codec/ Apache Commons Codec (TM) software provides implementations of common encoders and decoders such as Base64, Hex, Phonetic and U

常用消息摘要算法介绍

消息摘要算法 介绍: 数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名.数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密.数据摘要算法也被称为哈希(Hash)算法或散列算法. 消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文.(摘要可以比方为指纹,消息摘要算法就是要得到文件的唯一职位) 特点: 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的.