MD5
概念
是计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。
作用
用于确保信息传输完整一致,属于杂凑算法(又称为摘要算法,哈希算法)。
让大容量信息在用数字签名软件签署私人密钥前被”压缩”成一种保密的格式(把一个任意长度的字节串变换成一定长的十六进制字符串)。
基础原理
将数据运算为另一固定长度值,是杂凑算法的基础原理。
特点
(1)压缩性:任意长度数据算出的MD5值长度固定
(2)容易计算:从原数据计算出MD5值很容易
(3)抗修改性:对原数据进行任何改动,所得到的MD5值都有很大区别
(4)强抗碰撞:已知原数据和MD5值,想找一个相同的MD5值得数据是分厂困难的
C++代码示例,来自百度百科,MD5已经被别人实现了,那我们知道它的原理作用拿来用就好了,我就不写了,剖析懂代码就好,我只加了一小部分用于将16进制数转换为10进制0~1023大小的数字的
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
//填充操作,使得信息位长恰好是512的倍数
#define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位
//MD5有四轮运算,将原先数据分为4个32位分组组成,选其中三个进行运算
#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//初始化变量,用于第一轮
//strBaye的长度
unsigned int strlength;
//A,B,C,D的临时变量
unsigned int atemp;
unsigned int btemp;
unsigned int ctemp;
unsigned int dtemp;
//常量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 };
const char str16[] = "0123456789abcdef";
void mainLoop(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;
}
/*
*填充函数
*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
*填充方式为先加一个1,其它位补零
*最后加上64位的原来长度
*/
unsigned int* add(string str)
{
unsigned int num = ((str.length() + 8) / 64) + 1;//以512位,64个字节为一组
unsigned int *strByte = new unsigned int[num * 16]; //64/4=16,所以有16个整数
strlength = num * 16;
for (unsigned int i = 0; i < num * 16; i++)
strByte[i] = 0;
for (unsigned int i = 0; i < str.length(); i++)
{
strByte[i >> 2] |= (str[i]) << ((i % 4) * 8);//一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息
}
strByte[str.length() >> 2] |= 0x80 << (((str.length() % 4)) * 8);//尾部添加1 一个unsigned int保存4个字符信息,所以用128左移
/*
*添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
*/
strByte[num * 16 - 2] = str.length() * 8;
return strByte;
}
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;
}
string getMD5(string source)
{
atemp = A; //初始化
btemp = B;
ctemp = C;
dtemp = D;
unsigned int *strByte = 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] = strByte[i * 16 + j];
mainLoop(num);
}
return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));
}
unsigned int main()
{
string ss;
// cin>>ss;
string s = getMD5("abc");
string s2 = getMD5("");
cout << s << endl;
cout << s2 << endl;
long hash = 0;//求哈希值的方法
for (int i = 0; i < 4; i++)
{
hash += ((long)(digest[i * 4 + 3] & 0xFF) << 24)
| ((long)(digest[i * 4 + 2] & 0xFF) << 16)
| ((long)(digest[i * 4 + 1] & 0xFF) << 8)
| ((long)(digest[i * 4 + 0] & 0xFF));
}
cout << "值" << abs(hash%1024) << endl;
return 0;
}