#include<iostream> #include<string> using namespace std; //主循环使用的函数 #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 leftrotate(x,n) (((x)<<(n))|((x)>>(32-n))) //初始哈希值 const unsigned int h0 = 0x67452301; const unsigned int h1 = 0xEFCDAB89; const unsigned int h2 = 0x98BADCFE; const unsigned int h3 = 0x10325476; //常数表 const int k[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 }; //左移表 const unsigned int r[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 }; //512bits大小的块的数目 unsigned int chunk_num; //填充函数 unsigned int* add(string input){ /*一个char型大小是1Byte,也就是8bits, 因此用(长度*8+64/512)就是加了长度信息后未填充的时候的块数目, 填充后就是(长度*8+64/512)+1 填充的信息量是(chunk_num*512-长度*8)bits */ chunk_num = ((input.length()*8 + 64) / 512) + 1; //一个无符号整型存放32bits(4Bytes)的信息,512/32 = 16,所以需要chunk_num*16个 unsigned int *inputByte = new unsigned int[chunk_num * 16]; //初始化全填0,可以省去填充时在尾部加一个1后填充0的步骤 for (int i = 0; i < chunk_num * 16; i++){ inputByte[i] = 0; } //把输入信息转化为无符号整型存放在数组中 for (unsigned int i = 0; i < input.length(); i++){ /*一个字符8bits,因此4个字符才能填满一个无符号整型 存放使用小端规则(低低,高高)存放, 例如(字符串低位)(1000 0001)(1000 0011)(1000 0111)(1000 1111)(字符串的高位) 存放进去是(整数的高位)(1000 1111)(1000 0111)(1000 0011)(1000 0001)(整数的低位) */ inputByte[i / 4] += (input[i]) << ((i % 4) * 8); } //填充一个1,1000 0000 -> 0x80 inputByte[input.length() / 4] += 0x80 << ((input.length() % 4) * 8); /* *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位 */ inputByte[chunk_num * 16 - 2] = input.length() * 8; return inputByte; } //把大端规则存放的哈希值转换回小端规则 string hex_to_string(unsigned int h){ unsigned int temp; string str; string str_temp; for (int i = 0; i < 4; i++){ str_temp = ""; //每次找出8bits temp = ((h >> (i * 8)) % (1 << 8)) & 0xff; for (int j = 0; j < 2; j++){ char c; //把这8bits从整型转换成字符 if (temp % 16 > 9){ c = (char)(65 + ((temp % 16) - 10)); } else{ c = (char)(48 + (temp % 16)); } //例如AB先转换出的顺序是B,A,因此要插在前头 str_temp.insert(0, 1, c); temp /= 16; } str += str_temp; } return str; } //获得MD5的核心函数 string getMD5(string input){ //填充后获得块 unsigned int* chunk = add(input); unsigned int temph0 = h0; unsigned int temph1 = h1; unsigned int temph2 = h2; unsigned int temph3 = h3; for (int i = 0; i < chunk_num; i++){ /*总共有chunk[chunk_num*16] 每次处理16个chunk,16个chunk是一个512块 */ unsigned int a = temph0; unsigned int b = temph1; unsigned int c = temph2; unsigned int d = temph3; unsigned int f; unsigned int g; for (int j = 0; j < 64; j++){ if (j < 16){ f = F(b, c, d); g = j; } else if (j < 32){ f = G(b,c,d); g = (5 * j + 1) % 16; } else if (j < 48){ f = H(b, c, d); g = (3 * j + 5) % 16; } else{ f = I(b, c, d); g = (7 * j) % 16; } unsigned int temp = d; d = c; c = b; //每次处理16个块,所以是i*16+g b = leftrotate((a + f + k[j] + chunk[i*16+g]), r[j]) + b; a = temp; } temph0 += a; temph1 += b; temph2 += c; temph3 += d; } //获得MD5码 string ans = hex_to_string(temph0) + hex_to_string(temph1) + hex_to_string(temph2) + hex_to_string(temph3); return ans; } int main(){ string ss[7] = { "", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "8a683566bcc7801226b3d8b0cf35fd97" }; /* 测试数据应该得到的md5码 MD5 ("") = d41d8cd98f00b204e9800998ecf8427e MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") = f29939a25efabaef3b87e2cbfe641315 MD5 ("8a683566bcc7801226b3d8b0cf35fd97") =cf2cb5c89c5e5eeebef4a76becddfcfd */ for (int i = 0; i < 7; i++){ cout << "加密的字符串:" << ss[i] << endl; cout << "MD5码:" << getMD5(ss[i]) << endl; } return 0; } 1 Fin 10.30/23:45 ← Previous Post Next Post →