MD5:又称消息摘要算法,对于输入的任意长度的消息进行产生固定长度为128位的消息摘要,由于MD5的算法是对数据进行有损压缩,也就是会无法直接通过分析算法来反向通过MD5值获取原始压缩数据,一般是用来数据校验和避免密码这类的隐私数据的明码保存。
算法步骤:
1.数据填充:填充消息使其长度对512取余等于448,填充方法:先在消息后面添加一个1(按bit),然后用0来填充,对于内存结构来看,就是在消息其后添加一个0x80;添加的长度最少为1,最多为512.
2.添加长度:在填充后的结果后附上64位的消息长度,如果消息长度超过2^64,则只使用低64位数据。第一步加上第二步第二数据填充刚好是512的倍数
3.初始化变量:标准参数:A=0X67452301h,B=0XEFCDAB89h,C=0X98BADCFEh,D=0X10325476h,在内存中显示就是0123456789ABCDEFFEDCBA9876543210
4.数据处理:以512位分组为单位处理消息,每个分组又会被分解成16个32位的数组,首先定义4个辅助函数:
int F(int x, int y, int z)
{
return (x & y) | ((~x) & z);
}
int G(int x, int y, int z)
{
return (x & z) | ((~z) & y);
}
int H(int x, int y, int z)
{
return x ^ y ^ z;
}
int I(int x, int y, int z)
{
return y ^ (x | (~z));
}
然后将16 个数据和ABCD的副本值参与到F、G、H、I的四轮变换中,运算完后在一次加上变换前的初始值作为下一个消息分组的计算初始值,直到所有的消息分组均运算完成。
F、G、H、I对应的运算函数如下:
结构一致:a、b、c、d:输入的参数(A、B、C、D) k:消息分组被分割后的16个32位数组值 s:循环左移位数 i:加法常数的id
void FF(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + F(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
void GG(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + G(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
void HH(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + H(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
void II(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + I(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
完整算法如下(仅适合短字符串,):
#include
#define ROL(data,n) ((data >> (32 - n)) | (data << n))
#define BIG_ENDIAN_SWITCH_LITTLE_ENDIAN(X) X << 24 | X >> 24 | ((X << 8) & 0xFF0000) | ((X >> 8) & 0xFF00)
int F(int x, int y, int z)
{
return (x & y) | ((~x) & z);
}
int G(int x, int y, int z)
{
return (x & z) | ((~z) & y);
}
int H(int x, int y, int z)
{
return x ^ y ^ z;
}
int I(int x, int y, int z)
{
return y ^ (x | (~z));
}
void FF(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + F(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
void GG(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + G(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
void HH(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + H(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
void II(unsigned int* a, unsigned int b, unsigned int c, unsigned int d, unsigned int k, unsigned int s, unsigned int i)
{
*a = b + ROL((*a + I(b, c, d) + k + (unsigned int)(4294967296 * abs(sin(i)))), s);
}
int main()
{
//数据填充
unsigned char cValue[64] = {0};
unsigned int iValue[16] = { 0 };
char code[] = "zfy1996";
unsigned int len = strlen(code);
unsigned int len1 = strlen(code)*8;
memcpy(cValue, code, strlen(code));
cValue[strlen(code)] = 0x80;
memcpy(iValue, cValue, 64);
iValue[14] = strlen(code) * 8;
//参数初始化
unsigned int A = 0x67452301, B = 0xefcdab89, C = 0x98badcfe, D = 0x10325476;
unsigned int a = A, b = B, c = C, d = D;
unsigned int s[64] = {
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
};
unsigned int k[64] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
};
typedef void(*func)(unsigned int*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
func fun[] = { FF,GG,HH,II };
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 16; j += 4)
{
fun[i](&a, b, c, d, iValue[k[16 * i + j]], s[16 * i + j], 16 * i + j + 1);
fun[i](&d, a, b, c, iValue[k[16 * i + j+1]], s[16 * i + j+1], 16 * i + j+2);
fun[i](&c, d, a, b, iValue[k[16 * i + j+2]], s[16 * i + j+2], 16 * i + j+3);
fun[i](&b, c, d, a, iValue[k[16 * i + j+3]], s[16 * i + j+3], 16 * i + j+4);
}
}
A += a;
B += b;
C += c;
D += d;
//小端转大端
printf("%X%X%X%X\n",
BIG_ENDIAN_SWITCH_LITTLE_ENDIAN(A),
BIG_ENDIAN_SWITCH_LITTLE_ENDIAN(B),
BIG_ENDIAN_SWITCH_LITTLE_ENDIAN(C),
BIG_ENDIAN_SWITCH_LITTLE_ENDIAN(D));
}