MD5是一种摘要算法,通过压缩+加密+hash的算法是绝对不可逆的。网上有很多人都写了,我也参考了MD5的基本规则写的。这个算法从数学角度上来说,主要是需要证明唯一性,但凭我等的能力想要做这种证明是不太现实的。因为我实在没办法去证明通过一系列的运算,累加a,b,c,d还能够有唯一性,因为就逆向去看加法,那是有无数解的,MD5也只能说在概率上是不会重复的吧。所以说那个幻数,还有里面的那些数据,是不能轻易改的吧,稍微量变,加法可能就会发生质变,导致多种映射指向到同一结果。不过就hash来说,512位 64个字节,通过一系列运算使得有大于64^256种唯一映射还是有可能去证明的。我自己重新写了下MD5算法,写得逻辑更清晰,看着很舒服的。
两个工具方法:
uchar* longTouchar(long n) { uchar* b = new uchar[4]; for (int i = 3; i >= 0; --i) { b[i] = n >> i * 8; } return b; } std::string getHexStr(uchar* val, int length) { std::stringstream ss; char characterArray[] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; for (int i = 0; i<length; ++i) { ss << characterArray[val[i] / 16] << characterArray[val[i] % 16];; } return ss.str(); }
md5.h
#pragma once class md5 { const uint A = 0x67452301L; const uint B = 0xEFCDAB89L; const uint C = 0x98badcfe; const uint D = 0x10325476; uint F(uint x, uint y, uint z); uint G(uint x, uint y, uint z); uint H(uint x, uint y, uint z); uint I(uint x, uint y, uint z); void FF(uint& a, uint b, uint c, uint d, uint src, uint s, uint m); void GG(uint& a, uint b, uint c, uint d, uint src, uint s, uint m); void HH(uint& a, uint b, uint c, uint d, uint src, uint s, uint m); void II(uint& a, uint b, uint c, uint d, uint src, uint s, uint m); uint LeftMoveLoop(uint n, uint s); uchar* buf; uint virtualVals[4]; void Process(); uint* spTouintArray(); public: md5(uchar* str, int size); uchar* getResult(); };
#include"stdafx.h" #include "md5.h" uint md5::F(uint x, uint y, uint z) { return (x&y) | ((~x)&z); } uint md5::G(uint x, uint y, uint z) { return (x&z) | (y&(~z)); } uint md5::H(uint x, uint y, uint z) { return x^y^z; } uint md5::I(uint x, uint y, uint z) { return y ^ (x | (~z)); } void md5::FF(uint& a, uint b, uint c, uint d, uint src, uint s, uint m) { a = b + LeftMoveLoop(a + F(b, c, d) + src + m, s); } void md5::GG(uint& a, uint b, uint c, uint d, uint src, uint s, uint m) { a = b + LeftMoveLoop(a + G(b, c, d) + src + m, s); } void md5::HH(uint& a, uint b, uint c, uint d, uint src, uint s, uint m) { a = b + LeftMoveLoop(a + H(b, c, d) + src + m, s); } void md5::II(uint& a, uint b, uint c, uint d, uint src, uint s, uint m) { a = b + LeftMoveLoop(a + I(b, c, d) + src + m, s); } uint md5::LeftMoveLoop(uint n, uint s) { return (n << s) | (n >> (32 - s)); } unsigned* md5::spTouintArray() { uint* a = new uint[16]; for (int i = 0; i<16; ++i) { uint a1 = buf[i * 4]; uint a2 = buf[i * 4 + 1]; uint a3 = buf[i * 4 + 2]; uint a4 = buf[i * 4 + 3]; a[i] = a1 | a2 << 8 | a3 << 16 | a4 << 24; } return a; } void md5::Process() { uint a = virtualVals[0], b = virtualVals[1], c = virtualVals[2], d = virtualVals[3]; uint* M = spTouintArray(); FF(a, b, c, d, M[0], 7, 0xd76aa478); FF(d, a, b, c, M[1], 12, 0xe8c7b756); FF(c, d, a, b, M[2], 17, 0x242070db); FF(b, c, d, a, M[3], 22, 0xc1bdceee); FF(a, b, c, d, M[4], 7, 0xf57c0faf); FF(d, a, b, c, M[5], 12, 0x4787c62a); FF(c, d, a, b, M[6], 17, 0xa8304613); FF(b, c, d, a, M[7], 22, 0xfd469501); FF(a, b, c, d, M[8], 7, 0x698098d8); FF(d, a, b, c, M[9], 12, 0x8b44f7af); FF(c, d, a, b, M[10], 17, 0xffff5bb1); FF(b, c, d, a, M[11], 22, 0x895cd7be); FF(a, b, c, d, M[12], 7, 0x6b901122); FF(d, a, b, c, M[13], 12, 0xfd987193); FF(c, d, a, b, M[14], 17, 0xa679438e); FF(b, c, d, a, M[15], 22, 0x49b40821); GG(a, b, c, d, M[1], 5, 0xf61e2562); GG(d, a, b, c, M[6], 9, 0xc040b340); GG(c, d, a, b, M[11], 14, 0x265e5a51); GG(b, c, d, a, M[0], 20, 0xe9b6c7aa); GG(a, b, c, d, M[5], 5, 0xd62f105d); GG(d, a, b, c, M[10], 9, 0x2441453); GG(c, d, a, b, M[15], 14, 0xd8a1e681); GG(b, c, d, a, M[4], 20, 0xe7d3fbc8); GG(a, b, c, d, M[9], 5, 0x21e1cde6); GG(d, a, b, c, M[14], 9, 0xc33707d6); GG(c, d, a, b, M[3], 14, 0xf4d50d87); GG(b, c, d, a, M[8], 20, 0x455a14ed); GG(a, b, c, d, M[13], 5, 0xa9e3e905); GG(d, a, b, c, M[2], 9, 0xfcefa3f8); GG(c, d, a, b, M[7], 14, 0x676f02d9); GG(b, c, d, a, M[12], 20, 0x8d2a4c8a); HH(a, b, c, d, M[5], 4, 0xfffa3942); HH(d, a, b, c, M[8], 11, 0x8771f681); HH(c, d, a, b, M[11], 16, 0x6d9d6122); HH(b, c, d, a, M[14], 23, 0xfde5380c); HH(a, b, c, d, M[1], 4, 0xa4beea44); HH(d, a, b, c, M[4], 11, 0x4bdecfa9); HH(c, d, a, b, M[7], 16, 0xf6bb4b60); HH(b, c, d, a, M[10], 23, 0xbebfbc70); HH(a, b, c, d, M[13], 4, 0x289b7ec6); HH(d, a, b, c, M[0], 11, 0xeaa127fa); HH(c, d, a, b, M[3], 16, 0xd4ef3085); HH(b, c, d, a, M[6], 23, 0x4881d05); HH(a, b, c, d, M[9], 4, 0xd9d4d039); HH(d, a, b, c, M[12], 11, 0xe6db99e5); HH(c, d, a, b, M[15], 16, 0x1fa27cf8); HH(b, c, d, a, M[2], 23, 0xc4ac5665); II(a, b, c, d, M[0], 6, 0xf4292244); II(d, a, b, c, M[7], 10, 0x432aff97); II(c, d, a, b, M[14], 15, 0xab9423a7); II(b, c, d, a, M[5], 21, 0xfc93a039); II(a, b, c, d, M[12], 6, 0x655b59c3); II(d, a, b, c, M[3], 10, 0x8f0ccc92); II(c, d, a, b, M[10], 15, 0xffeff47d); II(b, c, d, a, M[1], 21, 0x85845dd1); II(a, b, c, d, M[8], 6, 0x6fa87e4f); II(d, a, b, c, M[15], 10, 0xfe2ce6e0); II(c, d, a, b, M[6], 15, 0xa3014314); II(b, c, d, a, M[13], 21, 0x4e0811a1); II(a, b, c, d, M[4], 6, 0xf7537e82); II(d, a, b, c, M[11], 10, 0xbd3af235); II(c, d, a, b, M[2], 15, 0x2ad7d2bb); II(b, c, d, a, M[9], 21, 0xeb86d391); virtualVals[0] += a; virtualVals[1] += b; virtualVals[2] += c; virtualVals[3] += d; delete buf; delete M; } md5::md5(uchar* str, int size) { virtualVals[0] = A; virtualVals[1] = B; virtualVals[2] = C; virtualVals[3] = D; int oriSize = size; int counter = 0; bool needAddEnd = true; while(true) { buf = new uchar[64];//在Process后自动释放 int cpyLen = size - counter; if(cpyLen>64) { cpyLen = 64; } if(size>=56)//只要大于等于56,就意味着无法同时写下8+64位,结束的情况一定是写下oriSize { memcpy(buf, str+counter, cpyLen);//先行拷贝 size -= cpyLen; counter += cpyLen; if(cpyLen==64) { Process(); continue; } buf[cpyLen] = 128;//0x10000000 memset(buf + cpyLen + 1, 0, 64 - cpyLen - 1);//剩余全部填充0 needAddEnd = false; Process(); } else { if (needAddEnd) { memcpy(buf, str + counter, size);//拷贝剩余字节 buf[size] = 128;//0x10000000 memset(buf + size + 1, 0, 64 - size - 1);//剩余全部填充0 } else { memset(buf, 0, 64);//在前一项已经填充过0,证明一定填充过0x10000000,所以这就只用填充0 } uchar* ucSize = longTouchar(oriSize*(long)8); //将int复制到buf上最后8个字节上去 memcpy(buf + 56, ucSize, 4); delete ucSize; Process(); break; } } } uchar* md5::getResult() { uchar* ret = new uchar[16]; for(int i=0;i<4;++i) { memcpy(ret+i*4, longTouchar(virtualVals[i]), 4); } return ret; }
调用
md5 m5((uchar*)pwd, strlen(pwd)); uchar* pmd5 = m5.getResult(); cout << getHexStr(pmd5, 16)<<endl;