Created
June 4, 2020 15:14
-
-
Save joechenrh/7b867135d99e9da7e15a0788dd96576e to your computer and use it in GitHub Desktop.
C++ implementation of the MD5 Hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by dhche on 2020/6/3. | |
// | |
#ifndef UNTITLED_MD5_H | |
#define UNTITLED_MD5_H | |
#include <string.h> | |
#include <string> | |
#include <fstream> | |
#include <iostream> | |
#include <sstream> | |
#include <algorithm> | |
//TODO: 确定系统的unsigned int是32位 | |
// 确定系统的大小端 | |
using WordType = unsigned int; | |
WordType A = 0x67452301; | |
WordType B = 0xEFCDAB89; | |
WordType C = 0x98BADCFE; | |
WordType D = 0x10325476; | |
int s[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 | |
}; | |
WordType 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 | |
}; | |
int g[64] = { | |
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, | |
1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, | |
5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, | |
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 | |
}; | |
std::string Word2Hex(WordType num) { | |
std::stringstream ss; | |
std::string hexString; | |
ss << std::hex << num; | |
ss >> hexString; | |
if(8 > hexString.size()) { | |
std::string s0(8 - hexString.size(), '0'); | |
hexString = s0 + hexString; | |
} | |
std::swap(hexString[0], hexString[1]); | |
std::swap(hexString[2], hexString[3]); | |
std::swap(hexString[4], hexString[5]); | |
std::swap(hexString[6], hexString[7]); | |
std::reverse(hexString.begin(), hexString.end()); | |
return hexString; | |
} | |
WordType F(WordType &X, WordType &Y, WordType &Z) { | |
return (X & Y) | ((~X) & Z); | |
} | |
WordType G(WordType &X, WordType &Y, WordType &Z) { | |
return (Z & X) | ((~Z) & Y); | |
} | |
WordType H(WordType &X, WordType &Y, WordType &Z) { | |
return X ^ Y ^ Z; | |
} | |
WordType I(WordType &X, WordType &Y, WordType &Z) { | |
return Y ^ ((~Z) | X); | |
} | |
void FF(WordType &a, WordType &b, WordType &c, WordType &d, WordType xk, int s, WordType ti) { | |
WordType tmp1 = a + F(b, c, d) + xk + ti; | |
WordType tmp2 = (tmp1 << s) | (tmp1 >> (32 - s)); | |
a = b + tmp2; | |
// a = b + (tmp1 << s) | (tmp1 >> (32 - s)); | |
} | |
void GG(WordType &a, WordType &b, WordType &c, WordType &d, WordType xk, int s, WordType ti) { | |
WordType tmp1 = G(b, c, d) + a + xk + ti; | |
WordType tmp2 = (tmp1 << s) | (tmp1 >> (32 - s)); | |
a = b + tmp2; | |
// a = b + (tmp1 << s) | (tmp1 >> (32 - s)); | |
} | |
void HH(WordType &a, WordType &b, WordType &c, WordType &d, WordType xk, int s, WordType ti) { | |
WordType tmp1 = H(b, c, d) + a + xk + ti; | |
WordType tmp2 = (tmp1 << s) | (tmp1 >> (32 - s)); | |
a = b + tmp2; | |
// a = b + (tmp1 << s) | (tmp1 >> (32 - s)); | |
} | |
void II(WordType &a, WordType &b, WordType &c, WordType &d, WordType xk, int s, WordType ti) { | |
WordType tmp1 = I(b, c, d) + a + xk + ti; | |
WordType tmp2 = (tmp1 << s) | (tmp1 >> (32 - s)); | |
a = b + tmp2; | |
// a = b + (tmp1 << s) | (tmp1 >> (32 - s)); | |
} | |
void Md5Sum(const std::string &fileName) { | |
std::ifstream in(fileName, std::ifstream::ate | std::ifstream::binary); | |
int size = in.tellg(); | |
char *data = new char[size + 1]; | |
in.clear(); | |
in.seekg(0, std::ios::beg); | |
in.read(data, size); | |
in.close(); | |
int blockCount = size < 57 ? 1 : (size - 57) / 64 + 2; | |
WordType **blocks = new WordType*[blockCount]; | |
int remainder = size % 64; | |
if (remainder <= 56) { | |
blockCount = size / 64 + 1; | |
blocks = new WordType*[blockCount]; | |
for (int i = 0; i < blockCount - 1; ++i) { | |
blocks[i] = (WordType *)(data + i * 64); | |
} | |
char remainBlock[64] = { 0 }; | |
strncpy(remainBlock, data + size - remainder, remainder); | |
if (remainder < 56) { | |
remainBlock[remainder] = 0x80; | |
} | |
blocks[blockCount - 1] = (WordType*)&remainBlock; | |
} | |
else { | |
blockCount = size / 64 + 1; | |
blocks = new WordType*[blockCount]; | |
for (int i = 0; i < blockCount - 2; ++i) { | |
blocks[i] = (WordType *)(data + i * 64); | |
} | |
char remainBlock1[64] = { 0 }, remainBlock2[64] = { 0 }; | |
strncpy(remainBlock1, data + size - remainder, remainder); | |
remainBlock1[remainder] = 0x80; | |
blocks[blockCount - 2] = (WordType*)&remainBlock1; | |
blocks[blockCount - 1] = (WordType*)&remainBlock2; | |
} | |
((long long*)blocks[blockCount - 1])[7] = size * 8; | |
WordType a, b, c, d; | |
for (int i = 0; i < blockCount; ++i) { | |
WordType *M = blocks[i]; | |
a = A; | |
b = B; | |
c = C; | |
d = D; | |
for (int j = 0; j < 16; j += 4) { //每次增加4 | |
FF(a, b, c, d, M[g[j]], s[j], T[j]); | |
FF(d, a, b, c, M[g[j + 1]], s[j + 1], T[j + 1]); | |
FF(c, d, a, b, M[g[j + 2]], s[j + 2], T[j + 2]); | |
FF(b, c, d, a, M[g[j + 3]], s[j + 3], T[j + 3]); | |
} | |
for (int j = 16; j < 32; j += 4) { | |
GG(a, b, c, d, M[g[j]], s[j], T[j]); | |
GG(d, a, b, c, M[g[j + 1]], s[j + 1], T[j + 1]); | |
GG(c, d, a, b, M[g[j + 2]], s[j + 2], T[j + 2]); | |
GG(b, c, d, a, M[g[j + 3]], s[j + 3], T[j + 3]); | |
} | |
for (int j = 32; j < 48; j += 4) { | |
HH(a, b, c, d, M[g[j]], s[j], T[j]); | |
HH(d, a, b, c, M[g[j + 1]], s[j + 1], T[j + 1]); | |
HH(c, d, a, b, M[g[j + 2]], s[j + 2], T[j + 2]); | |
HH(b, c, d, a, M[g[j + 3]], s[j + 3], T[j + 3]); | |
} | |
for (int j = 48; j < 64; j += 4) { | |
II(a, b, c, d, M[g[j]], s[j], T[j]); | |
II(d, a, b, c, M[g[j + 1]], s[j + 1], T[j + 1]); | |
II(c, d, a, b, M[g[j + 2]], s[j + 2], T[j + 2]); | |
II(b, c, d, a, M[g[j + 3]], s[j + 3], T[j + 3]); | |
} | |
A += a; | |
B += b; | |
C += c; | |
D += d; | |
} | |
std::cout << Word2Hex(A) << Word2Hex(B) << Word2Hex(C) << Word2Hex(D) << std::endl; | |
} | |
#endif //UNTITLED_MD5_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment