标签:md5 实现 算法
// 直接贴代码了,具体原理有很多地方都有描述,这里给出实现方便对比自己的算法到底什么地方错,算法是绝对没有问题的,计算大型文件MD5的效率还可以优化的。 struct IIStream { virtual size_t GetLength() = 0; virtual size_t Read(size_t size_,unsigned char * buff_out_) = 0; virtual bool Eof() = 0; virtual bool Valid() = 0; virtual void Release() = 0; }; struct IOStream { virtual void Init(const char * param) = 0; virtual void OnRecvData(unsigned char * data_,size_t size_) = 0; virtual bool Valid() = 0; virtual void Release() = 0; }; IIStream * CreateStdFileStream(const char * szPath ); IIStream * CreateMemoryStream(unsigned char * pData,size_t size); struct SimpleProgressMotintor:public IProgress { void OnProcess(size_t bytes_total,size_t bytes_processed,size_t bytes_got); }; struct StdFileStream:public IIStream { FILE * m_file; unsigned long m_iLen; StdFileStream(const char * szPath); bool Valid(); size_t GetLength(); size_t Read(size_t size_,unsigned char * buff_out_); bool Eof(); void Release(); }; struct FileWriter:public IOStream { FILE * m_file; FileWriter(); void Init(const char * param); virtual void OnRecvData(unsigned char * data_,size_t size_); bool Valid(); void Release(); }; #include "ZUtils.h" void * AllocateMem(size_t size_) { return malloc(size_); } void RecycleMem(void * p) { free(p); } struct MemoryStream:public IIStream { unsigned char * m_pData; unsigned char * m_pEnd; unsigned char * m_pCurr; MemoryStream( unsigned char * pData, size_t size) { m_pData = pData; m_pEnd = pData + size; m_pCurr = m_pData; } bool Valid() { return m_pData; } size_t GetLength() { return m_pEnd - m_pData; } size_t Read(size_t size_,unsigned char * buff_out_) { unsigned long left = m_pEnd - m_pCurr; if(left > size_) { memcpy(buff_out_,m_pCurr,size_); m_pCurr += size_; return size_; } else { memcpy(buff_out_,m_pCurr,left); m_pCurr += left; return left; } } bool Eof() { return (m_pCurr >= m_pEnd)?true:false; } void Release() { delete this; } }; IIStream * CreateMemoryStream(unsigned char * pData,size_t size) { MemoryStream * pObj = new MemoryStream(pData,size); return pObj; } IIStream * CreateStdFileStream(const char * szPath ) { return new StdFileStream(szPath); } void SimpleProgressMotintor::OnProcess(size_t bytes_total,size_t bytes_processed,size_t bytes_got) { printf("bytes total : %d bytes processed : %d bytes got : %d",bytes_total,bytes_processed,bytes_got); } StdFileStream::StdFileStream(const char * szPath) { m_file = fopen(szPath,"rb+"); if(m_file) { m_iLen = ftell(m_file); fseek(m_file,0,SEEK_END); m_iLen = ftell(m_file) - m_iLen; fseek(m_file,0,SEEK_SET); } else { m_iLen = 0; } } bool StdFileStream::Valid() { return m_iLen > 0; } size_t StdFileStream::GetLength() { return m_iLen; } size_t StdFileStream::Read(size_t size_,unsigned char * buff_out_) { return fread(buff_out_,1,size_,m_file); } bool StdFileStream::Eof() { return feof(m_file); } void StdFileStream::Release() { if(m_file) fclose(m_file); delete this; } FileWriter::FileWriter() { } void FileWriter::Init(const char * param) { m_file = fopen(param,"wb+"); } void FileWriter::OnRecvData(unsigned char * data_,size_t size_) { fwrite(data_,1,size_,m_file); } bool FileWriter::Valid() { return !!m_file; } void FileWriter::Release() { fclose(m_file); delete this; } #ifndef MD5_H_INCLUDED #define MD5_H_INCLUDED #include <cassert> #ifndef uint typedef unsigned int uint; #endif const extern size_t align_size; const extern size_t align_mod_size; const extern size_t align_end_size; // 8 ×ú 64 struct MD5Calc { char m_helpBuff[128]; uint A,B,C,D; uint a,b,c,d; 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& x,uint y,uint& z); void GG(uint& a,uint& b,uint& c,uint& d,uint& x,uint y,uint& z); void HH(uint& a,uint& b,uint& c,uint& d,uint& x,uint y,uint& z); void II(uint& a,uint& b,uint& c,uint& d,uint& x,uint y,uint& z); MD5Calc(); void MD5(const char * szFile); void Turn( uint * chunk); void PrintMD5(); }; size_t calc_md5_fill_n( size_t nData ); #endif // MD5_H_INCLUDED #include "md5.h" #include "ZUtils.h" #include <cmath> #include <cstdio> struct MD5IStream:public IIStream { IIStream * m_FileStream; IIStream * m_MemStream; unsigned char m_helpBuff[128]; MD5IStream(const char * szFilepath) { m_FileStream = CreateStdFileStream(szFilepath); long long datalen = m_FileStream->GetLength(); long long md5_fill_n = calc_md5_fill_n(m_FileStream->GetLength()); long long buffsize = md5_fill_n + align_end_size; m_helpBuff[0] = 128; memset(m_helpBuff + 1,0,md5_fill_n -1); long long datalenbytes = datalen * 8; memcpy(m_helpBuff + md5_fill_n,&datalenbytes,sizeof(datalenbytes)); m_MemStream = CreateMemoryStream(m_helpBuff,buffsize); } size_t GetLength() { return m_FileStream->GetLength() + m_MemStream->GetLength(); } virtual size_t Read(size_t size_,unsigned char * buff_out_) { size_t read = 0; if(!m_FileStream->Eof()) { read += m_FileStream->Read(size_,buff_out_); if(read < size_) { read += m_MemStream->Read(size_ - read,buff_out_ + read); } return read; } else { return m_MemStream->Read(size_,buff_out_); } } virtual bool Eof() { return m_FileStream->Eof() && m_MemStream->Eof(); } virtual bool Valid() { return m_FileStream && m_MemStream; } virtual void Release() { m_FileStream->Release(); m_MemStream->Release(); } }; char chain_values[] = { 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98, 0x76,0x54,0x32,0x10 }; uint T[] = { 0x00000000, 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 }; /* unsigned int T(float i) { double s = sin(i); if (s > 0) { return 4294967296.f * s; } else { return 4294967296.f * -s; } } */ const size_t align_size = 64; const size_t align_mod_size = 56; const size_t align_end_size = sizeof(long long int); // unsigned int CLS_32( unsigned int i , unsigned int offset) { assert(offset < 32 && offset > 0); return i<<offset|i>>(32-offset); } MD5Calc::MD5Calc() { } uint MD5Calc::F(uint& x,uint& y,uint& z) { return (x&y)|((~x)&z); } uint MD5Calc::G(uint& x,uint& y,uint& z) { return (x&z)|(y&(~z)); } uint MD5Calc::H(uint& x,uint& y,uint& z) { return x^y^z; } uint MD5Calc::I(uint& x,uint& y,uint& z) { return y^(x|(~z)); } void MD5Calc::FF(uint& a,uint& b,uint& c,uint& d,uint& x,uint y,uint& z) { a = b+CLS_32(a+F(b,c,d)+x+z,y); } void MD5Calc::GG(uint& a,uint& b,uint& c,uint& d,uint& x,uint y,uint& z) { a = b+CLS_32(a+G(b,c,d)+x+z,y); } void MD5Calc::HH(uint& a,uint& b,uint& c,uint& d,uint& x,uint y,uint& z) { a = b+CLS_32(a+H(b,c,d)+x+z,y); } void MD5Calc::II(uint& a,uint& b,uint& c,uint& d,uint& x,uint y,uint& z) { a = b+CLS_32(a+I(b,c,d)+x+z,y); } void MD5Calc::MD5(const char * szFile) { A = *(uint*)chain_values; B = *((uint*)chain_values + 1); C = *((uint*)chain_values + 2); D = *((uint*)chain_values + 3); MD5IStream md5IStream(szFile); unsigned char buff[64]; while(!md5IStream.Eof()) { md5IStream.Read(64,buff); this->Turn((uint *)&buff[0]); } md5IStream.Release(); } void MD5Calc::Turn(uint * chunk) { // a = A; b = B; c = C; d = D; FF(a,b,c,d,chunk[0],7,T[1]);FF(d,a,b,c,chunk[1],12,T[2]);FF(c,d,a,b,chunk[2],17,T[3]);FF(b,c,d,a,chunk[3],22,T[4]); FF(a,b,c,d,chunk[4],7,T[5]);FF(d,a,b,c,chunk[5],12,T[6]);FF(c,d,a,b,chunk[6],17,T[7]);FF(b,c,d,a,chunk[7],22,T[8]); FF(a,b,c,d,chunk[8],7,T[9]);FF(d,a,b,c,chunk[9],12,T[10]);FF(c,d,a,b,chunk[10],17,T[11]);FF(b,c,d,a,chunk[11],22,T[12]); FF(a,b,c,d,chunk[12],7,T[13]);FF(d,a,b,c,chunk[13],12,T[14]);FF(c,d,a,b,chunk[14],17,T[15]);FF(b,c,d,a,chunk[15],22,T[16]); // GG(a,b,c,d,chunk[1],5,T[17]);GG(d,a,b,c,chunk[6],9,T[18]);GG(c,d,a,b,chunk[11],14,T[19]);GG(b,c,d,a,chunk[0],20,T[20]); GG(a,b,c,d,chunk[5],5,T[21]);GG(d,a,b,c,chunk[10],9,T[22]);GG(c,d,a,b,chunk[15],14,T[23]);GG(b,c,d,a,chunk[4],20,T[24]); GG(a,b,c,d,chunk[9],5,T[25]);GG(d,a,b,c,chunk[14],9,T[26]);GG(c,d,a,b,chunk[3],14,T[27]);GG(b,c,d,a,chunk[8],20,T[28]); GG(a,b,c,d,chunk[13],5,T[29]);GG(d,a,b,c,chunk[2],9,T[30]);GG(c,d,a,b,chunk[7],14,T[31]);GG(b,c,d,a,chunk[12],20,T[32]); // HH(a,b,c,d,chunk[5],4,T[33]);HH(d,a,b,c,chunk[8],11,T[34]);HH(c,d,a,b,chunk[11],16,T[35]);HH(b,c,d,a,chunk[14],23,T[36]); HH(a,b,c,d,chunk[1],4,T[37]);HH(d,a,b,c,chunk[4],11,T[38]);HH(c,d,a,b,chunk[7],16,T[39]);HH(b,c,d,a,chunk[10],23,T[40]); HH(a,b,c,d,chunk[13],4,T[41]);HH(d,a,b,c,chunk[0],11,T[42]);HH(c,d,a,b,chunk[3],16,T[43]);HH(b,c,d,a,chunk[6],23,T[44]); HH(a,b,c,d,chunk[9],4,T[45]);HH(d,a,b,c,chunk[12],11,T[46]);HH(c,d,a,b,chunk[15],16,T[47]);HH(b,c,d,a,chunk[2],23,T[48]); // II(a,b,c,d,chunk[0],6,T[49]); II(d,a,b,c,chunk[7],10,T[50]); II(c,d,a,b,chunk[14],15,T[51]);II(b,c,d,a,chunk[5],21,T[52]); II(a,b,c,d,chunk[12],6,T[53]);II(d,a,b,c,chunk[3],10,T[54]); II(c,d,a,b,chunk[10],15,T[55]);II(b,c,d,a,chunk[1],21,T[56]); II(a,b,c,d,chunk[8],6,T[57]); II(d,a,b,c,chunk[15],10,T[58]);II(c,d,a,b,chunk[6], 15,T[59]); II(b,c,d,a,chunk[13],21,T[60]); II(a,b,c,d,chunk[4],6,T[61]); II(d,a,b,c,chunk[11],10,T[62]);II(c,d,a,b,chunk[2], 15,T[63]); II(b,c,d,a,chunk[9],21,T[64]); A += a; B += b; C += c; D += d; } void MD5Calc::PrintMD5() { uint array[] = {A,B,C,D}; for(int i = 0;i<sizeof(array);i++) { unsigned char cc = *(((unsigned char *)array)+i); printf("%02x",cc); } } size_t calc_md5_fill_n( size_t nData ) { if(nData & (align_size-1)) { unsigned int t = (nData + align_size - 1) & ~(align_size-1); if (t - align_end_size > nData) { return t - align_end_size - nData; } else { return t + align_mod_size; } } else // 64a¥–°μ’ ± { return align_mod_size; } } #include <iostream> #include <cstring> #include <cstdio> #include "md5.h" using namespace std; int main() { MD5Calc calc; calc.MD5("DG8Setup_1311Beta.exe"); calc.PrintMD5(); return 0; }
本文出自 “冰狐浪子的博客” 博客,请务必保留此出处http://bhlzlx.blog.51cto.com/3389283/1592361
标签:md5 实现 算法
原文地址:http://bhlzlx.blog.51cto.com/3389283/1592361