3.MD5算法具有以下特點:3.1可壓縮性:對於任意長度的數據,計算出的MD5值的長度是固定的。
3.2計算簡單:從原始數據中很容易計算出MD5值。
3.3防修改:如果對原始數據做任何修改,哪怕只修改1字節,得到的MD5值都相差很大。
3.4抗碰撞性強:知道原始數據及其MD5值,很難找到壹個MD5值相同的數據(即偽造數據)。
生成的MD5結果本身是壹個十六進制數,可以轉換成相應的10十進制數。下面的代碼是C++生成的MD5:
# include & ltiostream & gt
# include & lt字符串& gt
使用?命名空間?std
#定義?shift(x,?n)?(((x)?& lt& lt?(n))?|?((x)?& gt& gt?(32-(n))//向右移動時,高位必須用零填充,而不是符號位。
#定義?F(x,?y,?z)?(((x)?& amp?(y))?|?((~x)?& amp?(z)))
#定義?G(x,?y,?z)?(((x)?& amp?(z))?|?((y)?& amp?(~z)))
#定義?H(x,?y,?z)?((x)??(y)??(z))
#定義?我(x,?y,?z)?((y)??((x)?|?(~z)))
#定義?答?0x67452301
#定義?b?0xefcdab89
#定義?c?0x98badcfe
#定義?d?0x10325476
//strBaye的長度
未簽名?int?strlength
//a、b、c和d的臨時變量
未簽名?int?atemp
未簽名?int?btemp
未簽名?int?ctemp
未簽名?int?dtemp
//常數ti?未簽名?int(ABS(sin(I+1))*(2pow 32))
const?未簽名?int?k[]={
0xd 76 a478,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,
0x befbc 70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
0xd9d4d039,0xe6db99e5,0x1fa27cf8,0 C4 AC 5665,0xf4292244,
0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0 xeb 86d 391 };
//向左移位的次數
const?未簽名?int?s[]= { 71217,22,71217,22,71217,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?夏爾?str 16[]= " 0123456789 abcdef ";
作廢?主循環(無符號?int?M[])
{
未簽名?int?f,g;
未簽名?int?a = atemp
未簽名?int?b = btemp
未簽名?int?c = ctemp
未簽名?int?d = dtemp
為了什麽?(未簽名?int?我?=?0;?我?& lt?64;?i++)
{
如果(我& lt16){
f=F(b,c,d);
g = I;
}別的?如果?(我& lt32)
{
f=G(b,c,d);
g =(5 * I+1)% 16;
}別的?如果(我& lt48){
f=H(b,c,d);
g =(3 * I+5)% 16;
}否則{
f=I(b,c,d);
g =(7 * I)% 16;
}
未簽名?int?tmp = d;
d = c;
c = b;
b=b+shift((a+f+k[i]+M[g]),shift
a = tmp
}
atemp = a+atemp;
b temp = b+ b temp;
ctemp = c+ctemp;
dt EMP = d+dt EMP;
}
/*
*填充功能
*處理後應滿足bits≡448(mod512),bytes≡56(mode64)為字節。
*填充方法是先加壹個1,其他位用零填充。
*最後加上原來的64位長度。
*/
未簽名?int*?添加(字符串?str)
{
未簽名?int?num =((str . length()+8)/64)+1;//以512位64字節為壹組。
未簽名?int?*strByte=new?未簽名?int[num * 16];//64/4=16,所以有16個整數。
strlength = num * 16;
為了什麽?(未簽名?int?我?=?0;?我?& lt?num * 16;?i++)
strByte[I]= 0;
為了什麽?(未簽名?int?I = 0;?我?& ltstr . length();?i++)
{
strByte[I & gt;& gt2]| =(str[I])& lt;& lt((I % 4)* 8);//壹個整數存儲四個字節,I >;& gt2代表i/4?未簽名的?Int對應4個字節,存儲4個字符的信息。
}
strByte[str . length()& gt;& gt2]| = 0x 80 & lt;& lt((((str . length()% 4))* 8);//最後加1?未簽名的?Int存儲四個字符的信息,所以用128左移。
/*
*加上原來的長度,長度指的是位的長度,所以妳要乘以8,然後是小端,所以妳放在倒數第二個,這裏長度只有32位。
*/
strByte[num * 16-2]= str . length()* 8;
回歸?strByte
}
字符串?changeHex(int?答
{
int?b;
字符串?str 1;
字符串?str =
for(int?I = 0;我& lt4;i++)
{
str 1 = " ";
b =((a & gt;& gtI * 8)%(1 & lt;& lt8))& amp;0xff//以相反的順序處理每個字節
為了什麽?(int?j?=?0;?j?& lt?2;?j++)
{
str1.insert(0,1,str 16[b % 16]);
b = b/16;
}
str+= str 1;
}
回歸?str
}
字符串?getMD5(字符串?來源)
{
atemp = A;//初始化
Bt EMP = B;
ctemp = C;
dt EMP = D;
未簽名?int?* strByte = add(source);
對於(未簽名?int?I = 0;我& ltstrlength/16;i++)
{
未簽名?int?編號[16];
對於(未簽名?int?j = 0;j & lt16;j++)
num[j]= strByte[I * 16+j];
主循環(num);
}
回歸?changeHex(atemp)。append(changeHex(btemp))。append(changeHex(ctemp))。append(change hex(dt EMP));
}
int?主()
{
字符串?ss,t;
CIN & gt;& gtss;?//輸入字符串
t = ss+“ABC”;//將輸入字符串與“abc”合並
cou & lt& ltt & lt& ltendl//輸出合並的字符串
字符串?s = get MD5(t);//獲取合並字符串md5
cout & lt& lts & lt& ltendl//輸出結果
回歸?0;
}