您的位置:首页 > 编程语言

MD5生成器源代码,写了几天呀....

2008-07-17 20:26 183 查看
//VC2005向导生成一个WIN32控制台工程,设置不使用Unicode字符集

//复制所有文本到你的工程就可以了。记得把所有 ' 替换成 单引号

//写了好几天,本意用来批量验证文件完整性的,这里是关键的算法部分。

#include "stdafx.h"
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#include <conio.h>
#include <stdio.h>
//================================================================================================================
/*
这个MD5生成类的使用有两种方法:
(1)、一次性把数据全部输入生成MD5码,通常对于较少的数据这样做,如生成一个字符串或者一个小文件的MD5。 操作步骤:
SetData 输入所有数据,传递的是数据缓冲区指针,并指定数据的长度.
Action 计算MD5值
(2)、逐步把数据分段输入生成MD5码,通常对于比较大量数据,如一个很大的文件,这时采用第一种方法很可能造成内存不足。操作步骤:
Step 循环调用,按循序每次向其传递一个64字节大小的缓冲区的指针。
End 末了当数据长度没有64字节时调用,并且指定数据长度
如果要多次使用本类要调用Reset以复位各个参数
*/

typedef unsigned int BUFF[16];
class ShuJu
{
public:
ShuJu(void);
public:
~ShuJu(void);
public:
void *data;
public:
void SetData(void * input, unsigned __int32 inlen);
public:
void Out(void);
public:
unsigned __int64 data_len; //原始数据长度,单位是"字节"
unsigned __int64 data_lenbit; //原始数据长度,单位是"位"
public:
unsigned __int64 all_len; //总共要处理的数据的长度,单位"字节",=数据原始长度+补位长度+8
unsigned __int64 all_lenbit; //总共要处理的数据的长度,单位"位"
public:
unsigned int A,B,C,D;
public:
inline UINT F(UINT x,UINT y,UINT z){return (x&y)|((~x)&z);}
inline UINT G(UINT x,UINT y,UINT z){return (x&z)|(y&(~z));}
inline UINT H(UINT x,UINT y,UINT z){return x^y^z;}
inline UINT I(UINT x,UINT y,UINT z){return y^(x|(~z));}
public:
inline UINT FF(UINT a,UINT b,UINT c,UINT d,UINT x,UINT s,UINT i){UINT e=a+F(b,c,d)+x+i;e=(e<<s)|(e>>(32-s));return b+e;}
inline UINT GG(UINT a,UINT b,UINT c,UINT d,UINT x,UINT s,UINT i){UINT e=a+G(b,c,d)+x+i;e=(e<<s)|(e>>(32-s));return b+e;}
inline UINT HH(UINT a,UINT b,UINT c,UINT d,UINT x,UINT s,UINT i){UINT e=a+H(b,c,d)+x+i;e=(e<<s)|(e>>(32-s));return b+e;}
inline UINT II(UINT a,UINT b,UINT c,UINT d,UINT x,UINT s,UINT i){UINT e=a+I(b,c,d)+x+i;e=(e<<s)|(e>>(32-s));return b+e;}
public:
void Action(void);
public:
unsigned char outstr[33]; //以字符串存储的MD5码
unsigned char outbit[16]; //以数字存储的MD5码
private:
void Change(void * p);
public:
unsigned char tail[64*2]; //尾巴,尾巴指的是原始数据对末尾剩余的若干字节数据(长度为原始数据长度字节数除已64的余数个字节),补位数据,8个"存储了以位计算的原始数据长度的"字节。
UINT tail_len; //尾巴的长度,单位是"字节"。尾巴长度是64字节(512位)或者128字节(1024位)。
public:
UINT buwei_len; //补位的长度,单位是字节
public:
void Reset(void);
public:
void End(void * p,UINT plen);
public:
void Step(void* p);
private:
void WeiShu(void * p, unsigned int plen);
public:
unsigned __int64 stepcount; //累计执行的步数,可以用来指示进度。
};

const unsigned int T[64]=
{
0xD76AA478,0xE8C7B756,0x242070DB,0xC1BDCEEE,0xF57C0FAF,0x4787C62A,0xA8304613,0xFD469501,0x698098D8,0x8B44F7AF,0xFFFF5BB1,0x895CD7BE,0x6B901122,0xFD987193,0xA679438E,0x49B40821,
0xF61E2562,0xC040B340,0x265E5A51,0xE9B6C7AA,0xD62F105D,0x2441453,0xD8A1E681,0xE7D3FBC8,0x21E1CDE6,0xC33707D6,0xF4D50D87,0x455A14ED,0xA9E3E905,0xFCEFA3F8,0x676F02D9,0x8D2A4C8A,
0xFFFA3942,0x8771F681,0x6D9D6122,0xFDE5380C,0xA4BEEA44,0x4BDECFA9,0xF6BB4B60,0xBEBFBC70,0x289B7EC6,0xEAA127FA,0xD4EF3085,0x4881D05,0xD9D4D039,0xE6DB99E5,0x1FA27CF8,0xC4AC5665,
0xF4292244,0x432AFF97,0xAB9423A7,0xFC93A039,0x655B59C3,0x8F0CCC92,0xFFEFF47D,0x85845DD1,0x6FA87E4F,0xFE2CE6E0,0xA3014314,0x4E0811A1,0xF7537E82,0xBD3AF235,0x2AD7D2BB,0xEB86D391
};
const unsigned int S[4][4]=
{
{7,12,17,22},
{5,9,14,20},
{4,11,16,23},
{6,10,15,21}
};

ShuJu::ShuJu(void)
:data(0)
{
Reset();
}

ShuJu::~ShuJu(void)
{
if(data)delete data;
}
void ShuJu::Reset(void)
{
if(data)delete data;
data=0;
data_len=0;
data_lenbit=0;
all_lenbit=0;
all_len=0;
stepcount=0;

A=0x67452301;
B=0xefcdab89;
C=0x98badcfe;
D=0x10325476;

outstr[32]=0;
}
void ShuJu::SetData(void * input, unsigned __int32 inlen)
{
char err[]="错误:内存不足!";
UINT ys=inlen % 64;
data_len=inlen-ys;
if(data)delete data;
data=NULL;
data=new BYTE[(UINT)data_len];
if(!data)
{
::memcpy(outstr,err,32);
return;
}
::memcpy(data,input,(UINT)data_len);
WeiShu((((char *)input)+inlen-ys),ys);
}
inline void ShuJu::WeiShu(void * p, unsigned int plen)
{
data_len+=plen;
data_lenbit=data_len*8;
buwei_len=plen<56?56-plen:120-plen;
tail_len=plen+buwei_len+8;
all_len=data_len+buwei_len+8;
all_lenbit=all_len*8;
::memcpy(tail,p,plen);
::ZeroMemory(tail+plen,buwei_len);
tail[plen]=0x80;
*((unsigned __int64*)(&(tail[plen+buwei_len])))=data_lenbit;
}

void ShuJu::Action(void)
{
unsigned __int64 m;
unsigned __int64 n;
n=data_len/64;
BUFF *p;
p=(BUFF*)data;
for(m=0;m<n;m++)
{
Change(p);
p++;
}
p=(BUFF *)tail;
Change(p);
if(tail_len==128)
{
p=(BUFF*)(tail+64);
Change(p);
}
Out();
}

void ShuJu::Step(void* p)
{
data_len+=64;
Change(p);
}
void ShuJu::End(void * p,UINT plen)
{
WeiShu(p,plen);
BUFF * pp=(BUFF *)tail;
Change(pp);
if(tail_len==128)
{
pp=(BUFF *)(tail+64);
Change(pp);
}
Out();
}

inline void ShuJu::Change(void * p)
{
BUFF & x=*((BUFF *)p);

UINT a=A;
UINT b=B;
UINT c=C;
UINT d=D;

a=FF(a,b,c,d,x[ 0],S[0][0],T[ 0]);
d=FF(d,a,b,c,x[ 1],S[0][1],T[ 1]);
c=FF(c,d,a,b,x[ 2],S[0][2],T[ 2]);
b=FF(b,c,d,a,x[ 3],S[0][3],T[ 3]);
a=FF(a,b,c,d,x[ 4],S[0][0],T[ 4]);
d=FF(d,a,b,c,x[ 5],S[0][1],T[ 5]);
c=FF(c,d,a,b,x[ 6],S[0][2],T[ 6]);
b=FF(b,c,d,a,x[ 7],S[0][3],T[ 7]);
a=FF(a,b,c,d,x[ 8],S[0][0],T[ 8]);
d=FF(d,a,b,c,x[ 9],S[0][1],T[ 9]);
c=FF(c,d,a,b,x[10],S[0][2],T[10]);
b=FF(b,c,d,a,x[11],S[0][3],T[11]);
a=FF(a,b,c,d,x[12],S[0][0],T[12]);
d=FF(d,a,b,c,x[13],S[0][1],T[13]);
c=FF(c,d,a,b,x[14],S[0][2],T[14]);
b=FF(b,c,d,a,x[15],S[0][3],T[15]);

a=GG(a,b,c,d,x[ 1],S[1][0],T[16]);
d=GG(d,a,b,c,x[ 6],S[1][1],T[17]);
c=GG(c,d,a,b,x[11],S[1][2],T[18]);
b=GG(b,c,d,a,x[ 0],S[1][3],T[19]);
a=GG(a,b,c,d,x[ 5],S[1][0],T[20]);
d=GG(d,a,b,c,x[10],S[1][1],T[21]);
c=GG(c,d,a,b,x[15],S[1][2],T[22]);
b=GG(b,c,d,a,x[ 4],S[1][3],T[23]);
a=GG(a,b,c,d,x[ 9],S[1][0],T[24]);
d=GG(d,a,b,c,x[14],S[1][1],T[25]);
c=GG(c,d,a,b,x[ 3],S[1][2],T[26]);
b=GG(b,c,d,a,x[ 8],S[1][3],T[27]);
a=GG(a,b,c,d,x[13],S[1][0],T[28]);
d=GG(d,a,b,c,x[ 2],S[1][1],T[29]);
c=GG(c,d,a,b,x[ 7],S[1][2],T[30]);
b=GG(b,c,d,a,x[12],S[1][3],T[31]);

a=HH(a,b,c,d,x[ 5],S[2][0],T[32]);
d=HH(d,a,b,c,x[ 8],S[2][1],T[33]);
c=HH(c,d,a,b,x[11],S[2][2],T[34]);
b=HH(b,c,d,a,x[14],S[2][3],T[35]);
a=HH(a,b,c,d,x[ 1],S[2][0],T[36]);
d=HH(d,a,b,c,x[ 4],S[2][1],T[37]);
c=HH(c,d,a,b,x[ 7],S[2][2],T[38]);
b=HH(b,c,d,a,x[10],S[2][3],T[39]);
a=HH(a,b,c,d,x[13],S[2][0],T[40]);
d=HH(d,a,b,c,x[ 0],S[2][1],T[41]);
c=HH(c,d,a,b,x[ 3],S[2][2],T[42]);
b=HH(b,c,d,a,x[ 6],S[2][3],T[43]);
a=HH(a,b,c,d,x[ 9],S[2][0],T[44]);
d=HH(d,a,b,c,x[12],S[2][1],T[45]);
c=HH(c,d,a,b,x[15],S[2][2],T[46]);
b=HH(b,c,d,a,x[ 2],S[2][3],T[47]);

a=II(a,b,c,d,x[ 0],S[3][0],T[48]);
d=II(d,a,b,c,x[ 7],S[3][1],T[49]);
c=II(c,d,a,b,x[14],S[3][2],T[50]);
b=II(b,c,d,a,x[ 5],S[3][3],T[51]);
a=II(a,b,c,d,x[12],S[3][0],T[52]);
d=II(d,a,b,c,x[ 3],S[3][1],T[53]);
c=II(c,d,a,b,x[10],S[3][2],T[54]);
b=II(b,c,d,a,x[ 1],S[3][3],T[55]);
a=II(a,b,c,d,x[ 8],S[3][0],T[56]);
d=II(d,a,b,c,x[15],S[3][1],T[57]);
c=II(c,d,a,b,x[ 6],S[3][2],T[58]);
b=II(b,c,d,a,x[13],S[3][3],T[59]);
a=II(a,b,c,d,x[ 4],S[3][0],T[60]);
d=II(d,a,b,c,x[11],S[3][1],T[61]);
c=II(c,d,a,b,x[ 2],S[3][2],T[62]);
b=II(b,c,d,a,x[ 9],S[3][3],T[63]);

A=A+a;
B=B+b;
C=C+c;
D=D+d;
stepcount++;
}

typedef unsigned int ABCD[4];
void ShuJu::Out(void)
{
ABCD abcd;
abcd[0]=A;
abcd[1]=B;
abcd[2]=C;
abcd[3]=D;
unsigned char * p;
for(int m=0;m<4;m++)
{
p=(unsigned char *)(&abcd[m]);
for(int n=0;n<4;n++)
{
outbit[m*4+n]=p
;
}
}
unsigned char c;
for(int m=0;m<16;m++)
{
c=outbit[m]>>4;
outstr[2*m]=c<10?c+48:c+55;
c=outbit[m]&0x0F;
outstr[2*m+1]=c<10?c+48:c+55;
}
outstr[32]=0;
}
//==================================================================================================================

char * help[]=
{
"------本软件为学习测试用,你可以随意复制,但不得做商业发行。------/n/
版本:1.0 作者:LH /n/n/
调用格式:md5 [参数1] [参数2] [参数3] [参数4]/n/
参数1: 用来指定要生成MD5码的数据,可以是文件名或者字符串。/n/
如果是字符串要在前加斜杠(/),内部处理时这个字符会被去除的。/n/
参数2: 用来指定以小写输出的MD5码中字母,或者显示完成百分比。/n/
本参数可以是字母(L)或(P)或(H)。/n/
参数3: 与[参数2]作用一样。/n/
参数4: 与[参数2]作用一样。/n/
参数n: 忽略。/n/
(P)显示完成百分比。(L)以小写输出。(H)隐藏控制台窗口,用于脚本时可能需要。/n/
参数间以空格来分隔,参数不区分大小写,自[参数2]起所有参数不分先后顺序。/n/
关于参数本身带空格和双引号的情况请参照WINDOWS命令行相关说明。/n/
示例: /n/
md5 c://boot.ini 计算文件boot.ini的md5值/n/
md5 c://boot.ini L 计算文件boot.ini的md5值并输出小写的十六进制字符/n/
md5 d://ghost//sys.gho P L /n/
计算文件sys.gho的md5值且在计算过程中显示完成百分比,输出小写的十六进制字符/n/
md5 /42C://Program Files//Internet Explorer//iexplore.exe/42 /n/
计算文件C://Program Files//Internet Explorer//iexplore.exe的MD5值。/n/
md5 /ABCDEFG 计算字符串 ABCDEFG 的MD5值/n/
-------------------------------------------------------------------------"
};
//==================================================================================================================
class Parament
{
public:
Parament(void);
public:
~Parament(void);
public:
bool trace;
public:
bool low;
public:
bool hide;
public:
char *instr;
public:
bool isstr;
public:
void Process(int argc, char * * argv);
public:
bool help;
};

Parament::Parament(void)
: trace(false)
, low(false)
, hide(false)
, instr(NULL)
, isstr(false)
, help(false)
{

}

Parament::~Parament(void)
{
}

void Parament::Process(int argc, char ** argv)
{
if(argc==1)
{
help=true;
return ;
}
instr=argv[1];
if(instr[0]=='/')
{
instr++;
isstr=true;
}
for(int m=2;m<argc;m++)
{
if(m>3)continue;
switch(argv[m][0])
{
case 'l':
case 'L':
low=true;
break;
case 'p':
case 'P':
trace=true;
break;
case 'h':
case 'H':
hide=true;
break;
}
}
if(hide)trace=false;
}
//===================================================================================================================
Parament para;
ShuJu data;
char outstr[33];
__int64 filelen;

void Action(int fr);
void Md5(char * instr);
void Help();

extern "C" WINBASEAPI HWND WINAPI GetConsoleWindow ();
int _tmain(int argc, _TCHAR* argv[])
{
para.Process(argc,argv);
if(para.help)
{
Help();
return 'H';
}
if(para.hide)FreeConsole();
Md5(para.instr);
if(para.low)strlwr(outstr);
printf("/15%s",outstr);
return 0;
}
#define BS 1024*10
#if !(BS%64==0)
#error BS必须是64的整数倍!
#endif

inline void Action(int fr)
{
size_t n;
size_t m;
unsigned char buff[BS];
unsigned char *p;
__int64 segment=filelen/1000;
__int64 seg=0;
int percent=0;
while((n=_read(fr,buff,BS))==BS)
{
p=buff;
for(m=0;m<n;m+=64)
{
data.Step(p);
p+=64;
}
if(para.trace)
{
seg+=BS;
if(seg>=segment*percent)
{
percent++;
printf("/15%d.%d%%",percent/10,percent-percent/10*10);
}
}
}
p=buff;
for(m=0;m<n/64;m++)
{
data.Step(p);
p+=64;
}
data.End(p,(UINT)n%64);
}

void Md5(char * instr)
{
if(para.isstr)
{
data.SetData(instr,(unsigned int)strlen(instr));
data.Action();
memcpy(outstr,data.outstr,32);
outstr[32]=0;
}
else
{
int fr=_open(instr,_O_BINARY|_O_RDONLY);
if(!(fr==-1))
{
filelen=_lseeki64(fr,0,SEEK_END);
_lseeki64(fr,0,SEEK_SET);
Action(fr);
_close(fr);
memcpy(outstr,data.outstr,32);
outstr[32]=0;
}
else
{
printf("%s%s%s/n%s%s","错误:文件 ",instr," 未能打开!","Error:Can't open file ",instr);
return;
}
}
}

void Help()
{
for(int m=0;m<sizeof(help)/4;m++)
{
printf("%s/n",help[m]);
printf("---------------ESC键退出,其它键继续显示MD5算法介绍-----------------/n");
char c=_getch();
if(c==27)break;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: