Skip to content

Instantly share code, notes, and snippets.

@joechenrh
Created June 4, 2020 15:14
Show Gist options
  • Save joechenrh/7b867135d99e9da7e15a0788dd96576e to your computer and use it in GitHub Desktop.
Save joechenrh/7b867135d99e9da7e15a0788dd96576e to your computer and use it in GitHub Desktop.
C++ implementation of the MD5 Hash
//
// 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