#ifndef YMD5_H_#define YMD5_H_#include <string>using std::string;namespace yyy {typedef unsigned int uint32;class MD5 {public: static string Md5(const string& s); static char* Md5(char* r, const char* s);private://对数组做填充 static size_t AppendString(char* buf, size_t textlen);//四轮处理 static void FourRoundRun(uint32 res[], const char* buf);//数组中的每个gn[i][j]元素通过公式: 2 * sin(16* 1) 32 i + j + 计算后取整得到 static uint32 gn[4][16];//做循环移位的步数 static int move[4][16];};}#endif
#include "YMd5.h"#include <iostream>#include <stdio.h>#include <string.h>using namespace std;namespace yyy {//四个逻辑函数,用函数指针数组组织static inline uint32 F(uint32 x, uint32 y, uint32 z) { return (x&y)|((~x)&z);}static inline uint32 G(uint32 x, uint32 y, uint32 z) { return (x&z)|(y&(~z));}static inline uint32 H(uint32 x, uint32 y, uint32 z) { return x^y^z;}static inline uint32 I(uint32 x, uint32 y, uint32 z) { return y^(x|(~z));}typedef uint32 (*P_FUN)(uint32 x, uint32 y, uint32 z);P_FUN pfun[4] = {F, G, H, I};//将整数x循环左移n位static inline uint32 CirLeftMove(uint32 x, int n) { return (x<<n)|((x&0xffffffff)>>(32-n)); }//将buf从start开始的offset个字节内存赋值到a这个uint数组,要求a的长度是offset/4(向上取整)static inline void Char2Uint(uint32 a[], const char* buf, const int len) { memcpy(a, buf, len); }//将a从start开始的offset个整数内存赋值到buf这个字符串,要求buf的长度是4*offsetstatic inline char* Uint2Char(char* buf, const uint32 a[], const int offset) { memcpy(buf, a, offset*4); }//将a数组,按16进制输出成字符串数组,输入buf长度大于32+1,函数里面不作检查static const char int2hex[17] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};static inline char* Uint2HexString(char* buf, const uint32 a[], const int len) { int i = -1; for (int j = 0; j < len; ++j) { buf[++i] = int2hex[(a[j] >> 4) & 0xf]; buf[++i] = int2hex[(a[j] >> 0) & 0xf]; buf[++i] = int2hex[(a[j] >> 12) & 0xf]; buf[++i] = int2hex[(a[j] >> 8) & 0xf]; buf[++i] = int2hex[(a[j] >> 20) & 0xf]; buf[++i] = int2hex[(a[j] >> 16) & 0xf]; buf[++i] = int2hex[(a[j] >> 28) & 0xf]; buf[++i] = int2hex[(a[j] >> 24) & 0xf]; } buf[++i] = 0; return buf;}int MD5::move[4][16] = { { 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 }};uint32 MD5::gn[4][16] = { { 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 }};#define J_TO_I(i, j) {\ if (r == 0) i = j & 0xf; \ else if (r == 1) i = (1+5*j) & 0xf; \ else if (r == 2) i = (5+3*j) & 0xf; \ else if (r == 3) i = (7*j) & 0xf; \}inline void MD5::FourRoundRun(uint32 res[], const char * buf) { uint32 a[16]; Char2Uint(a, buf, 64); uint32 tmp_res[4]; memcpy(tmp_res, res, sizeof(res)*4); for(int r = 0; r < 4; ++r) { for (int j = 0; j < 16; ++j) { int i = 0; J_TO_I(i, j); tmp_res[0] = tmp_res[1] + CirLeftMove(tmp_res[0] + (*(pfun[r]))(tmp_res[1], tmp_res[2], tmp_res[3]) + a[i] + gn[r][j], move[r][j]); int tmp = tmp_res[3]; tmp_res[3] = tmp_res[2]; tmp_res[2] = tmp_res[1]; tmp_res[1] = tmp_res[0]; tmp_res[0] = tmp; } } res[0] += tmp_res[0]; res[1] += tmp_res[1]; res[2] += tmp_res[2]; res[3] += tmp_res[3];}char* MD5::Md5(char* r, const char* s) { uint32 temp[4], result[4] = { 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476 }; const size_t BUFLEN = 64; char buf[BUFLEN*2+1]; size_t offset = 0, len = 0; memcpy(temp, result, sizeof(result)); bool end = false; while (!end) { strncpy(buf, s+offset, BUFLEN); buf[BUFLEN] = 0; len = strlen(buf); offset += len; if (len < BUFLEN) { len = AppendString(buf, strlen(s)); end = true; } if (len == 64) { FourRoundRun(result, buf); } else if (len == 128) { FourRoundRun(result, buf); FourRoundRun(result, buf+BUFLEN); } } strcpy(r, Uint2HexString(buf, result, 4)); return r;}string MD5::Md5(const string& s) { char res[33]; Md5(res, s.c_str()); return string(res);}inline size_t MD5::AppendString(char* buf, size_t textlen) { //这里必须保证使用的buf有(64*2+1)byte的长度 size_t append_len, retlen, len = strlen(buf); size_t res = len&0x3f; if (res >= 56) { append_len = 64 - res + 56; retlen = 128; } else if (res < 56) { append_len = 56 - res; retlen = 64; } *(buf+len) = 0x80; memset(buf+len+1, 0, append_len-1); textlen *= 8;//转换成bit长度 memcpy(buf+len+append_len, &textlen, sizeof(size_t)); return retlen;}}