一、MD5算法簡介
MD5算法是一種廣泛使用的密碼散列函數,可以將任意長度的文本轉換成128位(16字節)的哈希值。由於哈希值的長度固定,因此可以用來驗證信息的完整性和一致性。MD5算法的產生是為了取代MD4算法(由於密碼分析學的進步及用戶的需求,MD4的安全性已經無法保證)。
MD5算法的核心思想是將輸入的信息進行分組,並按照規定的方式進行處理,最後得到一個定長的輸出。它的算法是基於位運算、模2的餘數運算和邏輯運算等算法的組合
二、MD5算法實現過程
1. 填充
MD5算法處理的是二進制數據,但是輸入的數據往往是以字節為單位的,所以需要將輸入數據按照512位(64字節)為一組進行劃分,並且需要將輸入的數據進行填充。 填充規則如下: (1)如果輸入的數據的字節數是64的倍數,不需要填充; (2)如果輸入的數據的字節數不足64字節,需要在末尾填充一個1,其餘補0,直到滿足64字節; (3)如果輸入的數據的字節數超過64字節,需要在末尾填充一個1,其餘補0,直到末尾64字節,然後將所有的64字節分組按照算法進行處理。
2. MD5算法處理
(1)初始化 定義4個32位的參數:A、B、C、D,用於存儲中間狀態。 每次處理512位時,先將A、B、C、D分別賦成如下值: A = 0x67452301; B = 0xefcdab89; C = 0x98badcfe; D = 0x10325476; (2)處理512位 將512位數據劃分成16組,每組32位。設當前處理的一組數據為X[i],則下一組數據為X[i+1]。 (3)四輪運算 分別進行4輪運算,每輪運算都將當前結果進行迭代,迭代方式如下: 1)輪 1:F(X,Y,Z) = (X & Y) | (~X & Z); 2)輪 2:G(X,Y,Z) = (X & Z) | (Y & ~Z); 3)輪 3:H(X,Y,Z) = X ^ Y ^ Z; 4)輪 4:I(X,Y,Z) = Y ^ (X | ~Z); (4)更新中間狀態 每輪運算後,都需要更新中間狀態A、B、C、D。 A = A + F(B,C,D) + X[i] + T[i]; B = D; C = B; D = A; (5)最終結果 處理完所有的數據塊後,將A、B、C、D拼接為一個128位的hash值,即為MD5算法處理結果。
三、使用方法
1. 環境要求
在VS2015中實現,需要用到以下頭文件:
#include #include #include
由於MD5算法使用了位運算和邏輯運算,因此為了便於處理,可以使用uint32_t類型進行定義。
2. MD5算法代碼實現
#include #include #include #include #include using namespace std; typedef unsigned int uint32_t; const uint32_t A = 0x67452301; const uint32_t B = 0xefcdab89; const uint32_t C = 0x98badcfe; const uint32_t D = 0x10325476; const uint32_t T[64] = { 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 }; inline uint32_t leftrotate(uint32_t x, uint32_t n) { return x <> (32 - n); } uint32_t F(uint32_t X, uint32_t Y, uint32_t Z) { return (X & Y) | (~X & Z); } uint32_t G(uint32_t X, uint32_t Y, uint32_t Z) { return (X & Z) | (Y & ~Z); } uint32_t H(uint32_t X, uint32_t Y, uint32_t Z) { return X ^ Y ^ Z; } uint32_t I(uint32_t X, uint32_t Y, uint32_t Z) { return Y ^ (X | ~Z); } void md5(uint32_t* data, uint32_t len, uint32_t* digest) { uint32_t* X = new uint32_t[16]; uint32_t a = A; uint32_t b = B; uint32_t c = C; uint32_t d = D; for (uint32_t i = 0; i < len; i += 16) { memcpy(X, data + i, 16 * sizeof(uint32_t)); uint32_t aa = a; uint32_t bb = b; uint32_t cc = c; uint32_t dd = d; for (uint32_t i = 0; i < 64; ++i) { uint32_t f, g; 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; } uint32_t tmp = d; d = c; c = b; b = b + leftrotate(a + f + X[g] + T[i], 7); a = tmp; } a += aa; b += bb; c += cc; d += dd; } delete[] X; digest[0] = a; digest[1] = b; digest[2] = c; digest[3] = d; } int main() { string input = "hello world"; uint32_t* data = new uint32_t[input.size() + 64]; memcpy(data, input.c_str(), input.size()); uint32_t len = ceil(8 * input.size() / 512) * 16; memset(data + input.size(), 0, (len - input.size()) * sizeof(uint32_t)); data[input.size() / 4] |= 0x00000001 << (8 * input.size() % 32); uint32_t digest[4]; md5(data, len, digest); delete[] data; printf("MD5 hash:\n"); printf("%08x%08x%08x%08x\n", digest[0], digest[1], digest[2], digest[3]); return 0; }
3. 示例
對字符串”hello world”進行MD5加密:
input: "hello world" output: 5eb63bbbe01eeed093cb22bb8f5acdc3
完整代碼如下:
#include
#include
#include
#include
#includeusing namespace std;
typedef unsigned int uint32_t;
const uint32_t A = 0x67452301;
const uint32_t B = 0xefcdab89;
const uint32_t C = 0x98badcfe;
const uint32_t D = 0x10325476;const uint32_t T[64] = { 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 };inline uint32_t leftrotate(uint32_t x, uint32_t n) {
return x <> (32 - n);
}uint32_t
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/249194.html