MD5 c++ 實現
最近實現MD5算法,發現最頭疼的地方是對調試難以下手。衆所周知,MD5算法,只要輸入信息有一絲差別,結果就千差萬別,而且MD5算法原理並不難,實現的過程最頭疼的是細節,所以在此提供已實現完整功能的代碼及標註調試位置,方便大家調試。
ps 本文不對MD5算法進行描述,因爲一般都要開發說明,或者可以搜索 “RFC 1321”,這個是MD5的標準說明,本文使用的檢驗例子也來源於此,不過其內容有點多且亂,可另尋他處。
結果運行
首先爲大家驗證結果,證明本程序的可靠性:
測試例子,來源:RFC 1321
運行結果:
讀者也可先獲取代碼,修改一下main函數,計算任意字符串的MD5,與網上的MD5加密工具結果進行對比
完整源碼:MD5 代碼(筆者GitHub)
以下爲兩個關鍵函數,思路和debug部分已註釋好,讀者可自行使用。算法涉及的小端模式,可參考大端模式和小端模式詳解
信息流讀取函數
/*
此程序的信息讀取函數使用一種比較耗內存,但很容易寫的方法來實現:
1)定義一個非常大的數組
2)將所有元素按順序輸入數組
3)讀取,填充和加入信息長度這些步驟全部完成後,將數組賦值給M[16],每16個就push到MessageFlow中(16*32 = 512)
爲何要使用大數組?使用大數組,你就不需要考慮當前的信息是否要push,可以節省代碼,也可以減少if語句,降低程序的
複雜性。
*/
void MD5::read(string str)
{
unsigned int big_temp[1000] = {0};
unsigned int sub_index = 0;
unsigned int temp;
big_temp[sub_index] = 0;
int i;
long long int count = str.length() * 8;
for (i = 0; i < str.length(); i++)//transfer message
{
temp = str[i];
big_temp[sub_index] += temp << ((i % 4) * 8);
if (i % 4 == 3)
sub_index++;
}
temp = 0x80;//padding
big_temp[sub_index] += temp << ((i % 4) * 8);
if (i % 4 == 3)
sub_index++;
i++;
temp = 0x00;
while ((i * 8) % 512 != 448)
{
big_temp[sub_index] += temp << ((i % 4) * 8);
if (i % 4 == 3)
sub_index++;
i++;
}
big_temp[sub_index++] = (count << 32) >> 32;
big_temp[sub_index] = count >> 32;
unsigned int * M;
for (int i = 0; i <= sub_index; i++)//add message block to MessageFlow
{
if (i % 16 == 0)
{
M = new unsigned int[16];
}
else if (i % 16 == 15)
{
MessageFlow.push_back(M);
}
M[i % 16] = big_temp[i];
}
/*
此處用於將輸入的信息print出來,主要驗證“小端存儲”操作是否出現錯誤。
for (int i = 0; i < MessageFlow.size(); i++)
{
for (int j = 0; j < 16; j++)
{
printf("%x ", MessageFlow[i][j]);
}
cout << endl;
}
*/
}
循環壓縮函數:
void MD5::HMD5(int q)
{
unsigned int a, b, c, d;
a = A;
b = B;
c = C;
d = D;
unsigned int temp;
unsigned int X, sub_index;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 16; j++)
{
sub_index = i * 16 + j;
X = MessageFlow[q][index[sub_index]];
temp = a + g2(i, b, c, d) + X + T[sub_index];
/*
此處輸出的是官方給的數據的輸出,驗證數據是否出錯,注:T雖然可以臨時計算,但我看很多例子
和官方代碼都是使用現成的T值,且我嘗試過直接算,一開始結果還是對的,到後面錯了很多,因此建議
將T存入數組,直接使用就好。
cout << index[sub_index] << " " << T[sub_index] << " " << s[sub_index] << endl;
*/
temp = (temp << s[sub_index]) | (temp >> (32 - s[sub_index]));
a = b + temp;
/*
此處用於輸出a,若a輸出正確,說明以上步驟都是正確的。
printf("%x\n",a);
*/
temp = d;
d = c;
c = b;
b = a;
a = temp;
}
}
A = A + a;
B = B + b;
C = C + c;
D = D + d;
}