MD5(MD5 消息摘要算法)
MD5(MD5 消息摘要算法)
MD5 简介
MD5 消息摘要算法(MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个 128 位(16 字节)的散列值(hash value),用于确保信息传输完整一致。MD5 由美国密码学家罗纳德 · 李维斯特(Ronald Linn Rivest)设计,于 1992 年公开,用以取代 MD4 算法。这套算法的程序在 RFC 1321 中被加以规范。
散列算法基础原理:将数据(如一段文字)运算变为另一固定长度值。
1996 年后被证实存在弱点,可以被加以**,对于需要高度安全性的数据,专家一般建议改用其他算法,如 SHA-2。2004 年,证实 MD5 算法无法防止碰撞(collision),因此不适用于安全性认证,如 SSL 公开**认证或是数字签名等用途。
由于 MD5 算法普遍、稳定、快速的特点。仍广泛应用于普通数据的错误检查领域。(如软件将通过计算 MD5 检验下载到的文件片段的完整性)
MD5 算法
MD5 算法对输入数据的长度没有限制,允许输入任意长度的数据。输出固定长度 128-bits (16 Byte)。
MD5 算法经由程序流程,生成 4 组 32 bits (4 Byte)数据,最后联合起来成为一个 128-bits 的散列。
基本方式为:求余、取余、调整长度、与链接变量进行循环运算。
C++ 版本代码如下:
#include<iostream>
#include<string>
#define LEFT_ROTATE_SHIFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) // (X AND Y) OR ((NOT X) AND Z)
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) // (X AND 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
#define HEX_NUM_CHAR_MAX 16
#define HEX_NUM_UPPER_CHAR_SET "0123456789ABCDEF"
#define HEX_NUM_LOWER_CHAR_SET "0123456789abcdef"
#define HEX_NUM_CHAR_SET HEX_NUM_LOWER_CHAR_SET
const static char msc_hexChars[] = HEX_NUM_CHAR_SET;
// 常量ti unsigned int(abs(sin(i+1))*(2pow32)), 优先记录结果加快运算速度
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 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,
};
void mainLoop(unsigned int M[], unsigned int temp[]) {
unsigned int f, g, tmp;
unsigned int a = temp[0];
unsigned int b = temp[1];
unsigned int c = temp[2];
unsigned int d = temp[3];
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;
}
tmp = d;
d = c;
c = b;
b = b + LEFT_ROTATE_SHIFT((a + f + k[i] + M[g]), s[i]);
a = tmp;
}
temp[0] += a;
temp[1] += b;
temp[2] += c;
temp[3] += d;
}
/*
* 填充函数
* 处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
* 填充方式为先加一个1,其它位补零
* 最后加上64位的原来长度
*/
unsigned int* add(std::string& str, unsigned int * out_len) {
unsigned int len = str.length();
unsigned int num = ((len + 8) / 64) + 1;
const int strlength = num * 16;
unsigned int *strByte = new unsigned int[strlength];
for (unsigned int i = 0; i < strlength; ++i) {
strByte[i] = 0;
}
for (unsigned int i = 0; i < len; ++i) {
strByte[i >> 2] |= (str[i]) << ((i & 0x03) << 3);
}
strByte[len >> 2] |= 0x80 << ((len & 0x03) << 3);
strByte[strlength - 2]=len * 8;
*out_len = strlength;
return strByte;
}
void DecToHex(unsigned int num, char * out) {
out[8] = 0;
for(int i = 0; i < 4; ++i) {
unsigned int byte_val = (num >> (i << 3)) & 0xff;
for (int j = 0; j < 2; ++j) {
out[i << 1 | (1 - j)] = msc_hexChars[byte_val & 0x0f];
byte_val >>= 4;
}
}
}
std::string getMD5(std::string& source) {
unsigned int temp[] = { A, B, C, D };
unsigned int strlength = 0;
unsigned int *strByte = add(source, &strlength);
for (unsigned int i = 0, len = strlength / 16; i < len; ++i){
unsigned int num[16];
for (unsigned int j = 0; j < 16; ++j){
num[j] = strByte[(i << 4) + j];
}
mainLoop(num, temp);
}
delete[] strByte;
char hex[32 + 1] = { 0 };
for (int i = 0; i < 4; ++ i) {
DecToHex(temp[i], hex + (i << 3));
}
return std::string(hex);
}
测试代码:
(需要与 Linux 的 md5sum
命令对比结果,由于用到的 echo
命令自带换行,所以测试代码加了个换行)
// 测试代码
int main(int argc, char *argv[]) {
if (argc == 1) {
return -1;
}
std::string val = argv[1];
val += "\n";
std::string md5 = getMD5(val);
std::cout << md5 << " : " << val << std::endl;
return 0;
}
测试结果如下:
[email protected]:/data/code# g++ md5.cpp && ./a.out zone && echo zone > a.txt && md5sum a.txt
8ac8489932db6327334c9b6d58544cfe : zone
8ac8489932db6327334c9b6d58544cfe a.txt
[email protected]:/data/code# g++ md5.cpp && ./a.out zone_test000 && echo zone_test000 > a.txt && md5sum a.txt
8a2f1e93bdccbc0e4168973a2cd8b9f5 : zone_test000
8a2f1e93bdccbc0e4168973a2cd8b9f5 a.txt
转载于:https://www.jianshu.com/p/6a7e9f329c3a
上一篇: python生成数字签名及验证签名
下一篇: web安全之攻击