MD5算法
来源:互联网 发布:360网络电视直播 编辑:程序博客网 时间:2024/06/16 00:08
MD5算法
MD5算法简介
MD5
MD5为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。
MD5即Message Digest Algorithm (信息-摘要算法5),一种被广泛使用的密码散列函数, 使用 little-endian,输入任意不定长度信息,以512位长进行分组,生成四个32位数据,最后联合起来输出固定128位长的信息摘要可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5 不是足够安全的,因为Hans Dobbertin 在1996年找到了两个不同的 512-bit 块,它们在 MD5 计算下产生相同的 hash 值。
MD5算法特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
MD5基本实现
输入不定长度信息,输出固定长度128-bits的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。
MD5算法实现
算法过程
1. 填充padding
在原始消息数据尾部填充标识 100…0,填充后的消息位数 L≡ 448 (mod 512)。至少要填充1个位,所以标识长度 1~512位。 再向上述填充好的消息尾部附加原始消息的位数的低64位,最后得到一个长度 L 是512位整数倍的消息。
填充的方法如下:
- 在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。
- 在这个结果后面附加一个以64位二进制表示的填充前信息长度(单位为Bit),如果二进制表示的填充前信息长度超过64位,则取低64位。经过这两步的处理,信息的位长=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。
2. 分块
把填充后的消息结果分割为 L 个512位的分组:Y0, Y1, …, YL-1。
结果也表示成 N 个32位长的字 M0, M1, …, MN-1,N = L ×16。
3. 初始化变量
初始化一个128位的 MD 缓冲区,记为 CVq,也表示为4个32位
寄存器 (A, B, C, D);CV0 = IV。迭代在 MD 缓冲区进行,最后一
步的128位输出即为算法结果
寄存器 (A, B, C, D) 置16进制初值作为初始向量 IV,并采用小端
存储 (little-endian) 的存储结构:
A = 0x67452301
B = 0xEFCDAB89
C = 0x98BADCFE
D = 0x10325476
Little-Endian 将低位字节排放在内存的低地址端,高位字节排放在
内存的高地址端。相反 Big-Endian 将高位字节排放在内存的低地
址端,低位字节排放在内存的高地址端。存储结构与 CPU 体系结
构和语言编译器有关。PowerPC 系列采用 big endian 方式存储数据
,而 Intel x86系列则采用 little endian 方式存储。
4. 压缩函数
- MD5 压缩函数
H(MD5) MD5从 CV 输入128位,从消息分组输入512位,完成4轮循环后,输出128位,用于下一轮输入的 CV 值。- 每轮循环分别固定不同的生成函数 F, G, H, I,结合指定的 T 表元素 T[] 和消息分组的不同部分 X[] 做16 次运算,生成下一轮循环的输入。
- 总共有64次迭代运算。
- 4轮循环中使用的生成函数 (轮函数) g 是一个32位非线性逻辑函数,
MD5 第 q 分组的4轮循环逻辑 (压缩函数)
在相应各轮的定义如下:
每轮循环中的一步运算逻辑
a <- b + ((a + g(b,c,d) + X[k] + T[i]) <<
C++算法代码
#include<iostream>#include<cstring>using namespace std;#define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//定义四轮操作#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))#define H(x, y, z) ((x) ^ (y) ^ (z))#define I(x, y, z) ((y) ^ ((x) | (~z)))// 定义寄存器初始值#define A 0x67452301#define B 0xefcdab89#define C 0x98badcfe#define D 0x10325476//各轮循环左移位数const unsigned int s[] = { 7,12,17,22,7,12,17, 22,7,12,17,22,7,12, 17,22,5,9,14,20,5, 9,14,20,5,9,14,20,5, 9,14,20,4,11,16,23, 4,11,16,23,4,11,16, 23,4,11,16,23,6,10, 15,21,6,10,15,21,6, 10,15,21,6,10,15,21};//各次迭代运算采用的 T 值const unsigned int k[]={ 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee, 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501, 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be, 0x6b901122,0xfd987193,0xa679438e,0x49b40821, 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa, 0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8, 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed, 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a, 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c, 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70, 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05, 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665, 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039, 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1, 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1, 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};const char str16[]="0123456789abcdef";unsigned int strlength;unsigned int atemp;unsigned int btemp;unsigned int ctemp;unsigned int dtemp;//迭代void iteration(unsigned int M[]) { unsigned int f,g; unsigned int a = atemp; unsigned int b = btemp; unsigned int c = ctemp; unsigned int d = dtemp; for (unsigned int i = 0; i < 64; i++) { if(i < 16) { f = F(b, c, d); g = i; } else if (i < 32) { f = G(b, c, d); g = (5 * i + 1) % 16; } else if(i < 48) { f = H(b, c, d); g = (3 * i + 5) % 16; }else{ f = I(b, c, d); g = (7 * i) % 16; } unsigned int tmp = d; d = c; c = b; b = b + shift((a+f + k[i] + M[g]), s[i]); a = tmp; } atemp = a + atemp; btemp = b + btemp; ctemp = c + ctemp; dtemp = d + dtemp;}//填充函数unsigned int* add(string str) { unsigned int num = ((str.length() + 8) / 64) + 1; unsigned int *byte=new unsigned int[num * 16]; strlength=num*16; for (unsigned int i = 0; i < num*16; i++) byte[i]=0; for (unsigned int i = 0; i <str.length(); i++) { byte[i >> 2] |= (str[i]) << ((i % 4) * 8); } byte[str.length() >> 2] |= 0x80<<(((str.length() % 4)) * 8); byte[num * 16 - 2] = str.length() * 8; return byte;}//逆序处理每个字节string changeHex(int a) { int b; string str1; string str = ""; for(int i = 0; i < 4; i++) { str1=""; b=((a >> i * 8) % (1 << 8)) & 0xff; for (int j = 0; j < 2; j++) { str1.insert(0, 1, str16[b % 16]); b = b / 16; } str += str1; } return str;}//MD5调用流程string MD5(string source) { atemp=A; btemp=B; ctemp=C; dtemp=D; unsigned int *byte=add(source); for(unsigned int i=0;i<strlength/16;i++) { unsigned int num[16]; for(unsigned int j= 0; j < 16; j++) num[j] = byte[i * 16 + j]; iteration(num); } return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));}int main() { string ss; cin>>ss; string s = MD5(ss); cout<<s <<endl; return 0;}
实验测试样例
md5(a,32) = 0cc175b9c0f1b6a831c399e269772661
md5(yes,32) = a6105c0a611b41b08f1209506350279e
- MD5算法
- MD5 算法
- MD5算法
- MD5 算法
- MD5算法
- MD5算法
- MD5算法
- md5 算法
- MD5算法
- MD5算法
- MD5算法
- MD5算法
- md5算法
- MD5算法
- MD5算法
- md5算法
- MD5算法
- MD5算法
- leetcode---linked-list-cycle---链表中点
- mybatis dao参数个数,和后面的xml的取值问题
- cmd中可以运行java,但不能运行javac命令
- CentOS--网络配置详解
- 解析xml的4种方法详解
- MD5算法
- http 301与302的区别
- 贝尔实验室简介
- maven创建项目缺少 maven-resources-plugin-2.6.jar 包。
- < 笔记 > Git
- 二进制枚举子集与容斥
- 160. Intersection of Two Linked Lists
- Java RTTI(Run-Time Type Identification) 运行时类型识别
- 使用Maven构建javaWeb项目时,启动tomcat出错:严重: Error configuring application listener of class org.springframewo