标签: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