zl程序教程

您现在的位置是:首页 >  后端

当前栏目

c++实现MD5算法实现代码

C++算法代码 实现 MD5
2023-06-13 09:15:12 时间

测试结果和百度百科测试例子一致。

实现过程中需要注意事项:最后把四个变量ABCD链接成结果时,注意变量高低位的先后顺序,具体参考LinkResult()方法。

md5.h

#ifndef_MD5_H_
#define_MD5_H_

#include<iostream>
#include<string>
usingnamespacestd;

classMD5
{
public:
typedefunsignedcharuchar8;//makesureitis8bit
typedefcharchar8;//makesureitis8bit
MD5();

voidinit();

voidUpdateMd5(constuchar8input[],constintlength);
voidUpdateMd5(constchar8input[],constintlength);

voidFinalize();

voidComputMd5(constuchar8input[],constintlength);
voidComputMd5(constchar8input[],constintlength);

stringGetMd5();

voidprintMd5();


private:
typedefunsignedintuint32;//makesureitis32bit;
typedefunsignedlonglonguint64;//makesureitis64bit;
uint32A,B,C,D;
conststaticintblockLen_=64;//512/8
//theremainafterlastupdata(becausemd5maybecomputedsegmentbysegment)
uchar8remain_[blockLen_];
intremainNum_;//thenumberofremain_,<64
uint64totalInputBits_;
uchar8md5Result_[16];//bitstylemd5result,totally128bit
charmd5Result_hex_[33];//hexadecimalstyleresult;md5Result_hex_[32]="\0"
boolisDone_;//indicatethecomputisfinished;

inlineuint32RotateLeft(constuint32x,intn);
inlineuint32F(constuint32x,constuint32y,constuint32z);
inlineuint32G(constuint32x,constuint32y,constuint32z);
inlineuint32H(constuint32x,constuint32y,constuint32z);
inlineuint32I(constuint32x,constuint32y,constuint32z);
inlinevoidFF(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti);
inlinevoidGG(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti);
inlinevoidHH(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti);
inlinevoidII(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti);


voidUcharToUint(uint32output[],constuchar8input[],constunsignedinttransLength);

voidFourRound(constuchar8block[]);

voidLinkResult();

};

/*userguide
youcancomputthemd5byusingthefuntionComputMd5
eg:
MD5m;
MD5::char8str[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
m.ComputMd5(str,sizeof(str)-1);
m.printMd5();

ifyouwanttocomputsegmentbysegment,youcandoasfollow,andinit()issuggested
thebegging,andFinalize()mustcallintheend:

MD5M;
m.init();
MD5::uchar8str1[]="ABCDEFGHIJKLMN";
MD5::uchar8str2[]="OPQRSTUVWXYZabcdefghijk";
MD5::uchar8str3[]="lmnopqrstuvwxyz";
m.UpdateMd5(str1,sizeof(str1)-1);
m.UpdateMd5(str2,sizeof(str2)-1);
m.UpdateMd5(str3,sizeof(str3)-1);
m.Finalize();
m.printMd5();

ifyouwanttocomputthemd5ofafile,youcanusetheinterfaceofthisprogram.
*/

#endif

md5.cpp

#include"md5.h"

#include<iostream>
usingnamespacestd;

constintS[4][4]={7,12,17,22,
5,9,14,20,
4,11,16,23,
6,10,15,21};
voidMD5::init()
{
A=0x67452301;
B=0xefcdab89;
C=0x98badcfe;
D=0x10325476;
remainNum_=0;
remain_[0]="\0";
md5Result_hex_[0]="\0";
md5Result_[0]="\0";
totalInputBits_=0;
isDone_=false;
}

MD5::MD5()
{
init();
}

inlineMD5::uint32MD5::RotateLeft(constuint32x,intn)
{
return(x<<n)|(x>>(32-n));
//ifxissigned,use:(x<<n)|((x&0xFFFFFFFF)>>(32-n))
}
inlineMD5::uint32MD5::F(constuint32x,constuint32y,constuint32z)
{
return(x&y)|((~x)&z);
}
inlineMD5::uint32MD5::G(constuint32x,constuint32y,constuint32z)
{
return(x&z)|(y&(~z));
}
inlineMD5::uint32MD5::H(constuint32x,constuint32y,constuint32z)
{
returnx^y^z;
}
inlineMD5::uint32MD5::I(constuint32x,constuint32y,constuint32z)
{
returny^(x|(~z));
}

inlinevoidMD5::FF(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti)
{
a=b+RotateLeft(a+F(b,c,d)+Mj+ti,s);
}
inlinevoidMD5::GG(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti)
{
a=b+RotateLeft(a+G(b,c,d)+Mj+ti,s);
}
inlinevoidMD5::HH(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti)
{
a=b+RotateLeft(a+H(b,c,d)+Mj+ti,s);
}
inlinevoidMD5::II(uint32&a,constuint32b,constuint32c,constuint32d,
constuint32Mj,constints,constuint32ti)
{
a=b+RotateLeft(a+I(b,c,d)+Mj+ti,s);
}

//linkABCDtoresult(bitstyleresultandhexadecimalstyleresult)
voidMD5::LinkResult()
{
//bitstyleresult
for(inti=0;i<4;i++)//linkA:lowtohigh
{
md5Result_[i]=(A>>8*i)&0xff;
}
for(inti=4;i<8;i++)//linkB:lowtohigh
{
md5Result_[i]=(B>>8*(i-4))&0xff;
}
for(inti=8;i<12;i++)//linkC:lowtohigh
{
md5Result_[i]=(C>>8*(i-8))&0xff;
}
for(inti=12;i<16;i++)//linkD:lowtohigh
{
md5Result_[i]=(D>>8*(i-12))&0xff;
}

//changetohexadecimalstyleresult
//note:itisnotthesameassimplylinkhex(A)hex(B)hex(C)hex(D)
for(inti=0;i<16;i++)
sprintf(&md5Result_hex_[i*2],"%02x",md5Result_[i]);
md5Result_hex_[32]="\0";

}

//printthemd5byhex
voidMD5::printMd5()
{
if(!isDone_)
{
cout<<"Error:computationisnotfinished"<<endl;

}
else
cout<<"MD5Value:"<<md5Result_hex_<<endl;
}

//getthemd5valueofhexstyle
stringMD5::GetMd5()
{
if(!isDone_)
{
cout<<"Error:computationisnotfinished"<<endl;
exit(0);
}
stringa((constchar*)md5Result_hex_);
returna;
}

voidMD5::UcharToUint(uint32output[],constuchar8input[],constunsignedinttransLength)
{
for(inti=0,j=0;j<transLength;i++,j+=4)
{
output[i]=((uint32)input[j])|(((uint32)input[j+1])<<8)|
(((uint32)input[j+2])<<16)|(((uint32)input[j+3])<<24);
}
}

//fourroundonablockof512bits;
voidMD5::FourRound(constuchar8block[])
{
uint32a=A,b=B,c=C,d=D;
uint32M[16];
UcharToUint(M,block,blockLen_);//blockLen_isaconstint=64;

//round1
FF(a,b,c,d,M[0],S[0][0],0xd76aa478);
FF(d,a,b,c,M[1],S[0][1],0xe8c7b756);
FF(c,d,a,b,M[2],S[0][2],0x242070db);
FF(b,c,d,a,M[3],S[0][3],0xc1bdceee);
FF(a,b,c,d,M[4],S[0][0],0xf57c0faf);
FF(d,a,b,c,M[5],S[0][1],0x4787c62a);
FF(c,d,a,b,M[6],S[0][2],0xa8304613);
FF(b,c,d,a,M[7],S[0][3],0xfd469501);
FF(a,b,c,d,M[8],S[0][0],0x698098d8);
FF(d,a,b,c,M[9],S[0][1],0x8b44f7af);
FF(c,d,a,b,M[10],S[0][2],0xffff5bb1);
FF(b,c,d,a,M[11],S[0][3],0x895cd7be);
FF(a,b,c,d,M[12],S[0][0],0x6b901122);
FF(d,a,b,c,M[13],S[0][1],0xfd987193);
FF(c,d,a,b,M[14],S[0][2],0xa679438e);
FF(b,c,d,a,M[15],S[0][3],0x49b40821);

//round2
GG(a,b,c,d,M[1],S[1][0],0xf61e2562);
GG(d,a,b,c,M[6],S[1][1],0xc040b340);
GG(c,d,a,b,M[11],S[1][2],0x265e5a51);
GG(b,c,d,a,M[0],S[1][3],0xe9b6c7aa);
GG(a,b,c,d,M[5],S[1][0],0xd62f105d);
GG(d,a,b,c,M[10],S[1][1],0x2441453);
GG(c,d,a,b,M[15],S[1][2],0xd8a1e681);
GG(b,c,d,a,M[4],S[1][3],0xe7d3fbc8);
GG(a,b,c,d,M[9],S[1][0],0x21e1cde6);
GG(d,a,b,c,M[14],S[1][1],0xc33707d6);
GG(c,d,a,b,M[3],S[1][2],0xf4d50d87);
GG(b,c,d,a,M[8],S[1][3],0x455a14ed);
GG(a,b,c,d,M[13],S[1][0],0xa9e3e905);
GG(d,a,b,c,M[2],S[1][1],0xfcefa3f8);
GG(c,d,a,b,M[7],S[1][2],0x676f02d9);
GG(b,c,d,a,M[12],S[1][3],0x8d2a4c8a);

//round3
HH(a,b,c,d,M[5],S[2][0],0xfffa3942);
HH(d,a,b,c,M[8],S[2][1],0x8771f681);
HH(c,d,a,b,M[11],S[2][2],0x6d9d6122);
HH(b,c,d,a,M[14],S[2][3],0xfde5380c);
HH(a,b,c,d,M[1],S[2][0],0xa4beea44);
HH(d,a,b,c,M[4],S[2][1],0x4bdecfa9);
HH(c,d,a,b,M[7],S[2][2],0xf6bb4b60);
HH(b,c,d,a,M[10],S[2][3],0xbebfbc70);
HH(a,b,c,d,M[13],S[2][0],0x289b7ec6);
HH(d,a,b,c,M[0],S[2][1],0xeaa127fa);
HH(c,d,a,b,M[3],S[2][2],0xd4ef3085);
HH(b,c,d,a,M[6],S[2][3],0x4881d05);
HH(a,b,c,d,M[9],S[2][0],0xd9d4d039);
HH(d,a,b,c,M[12],S[2][1],0xe6db99e5);
HH(c,d,a,b,M[15],S[2][2],0x1fa27cf8);
HH(b,c,d,a,M[2],S[2][3],0xc4ac5665);

//round4
II(a,b,c,d,M[0],S[3][0],0xf4292244);
II(d,a,b,c,M[7],S[3][1],0x432aff97);
II(c,d,a,b,M[14],S[3][2],0xab9423a7);
II(b,c,d,a,M[5],S[3][3],0xfc93a039);
II(a,b,c,d,M[12],S[3][0],0x655b59c3);
II(d,a,b,c,M[3],S[3][1],0x8f0ccc92);
II(c,d,a,b,M[10],S[3][2],0xffeff47d);
II(b,c,d,a,M[1],S[3][3],0x85845dd1);
II(a,b,c,d,M[8],S[3][0],0x6fa87e4f);
II(d,a,b,c,M[15],S[3][1],0xfe2ce6e0);
II(c,d,a,b,M[6],S[3][2],0xa3014314);
II(b,c,d,a,M[13],S[3][3],0x4e0811a1);
II(a,b,c,d,M[4],S[3][0],0xf7537e82);
II(d,a,b,c,M[11],S[3][1],0xbd3af235);
II(c,d,a,b,M[2],S[3][2],0x2ad7d2bb);
II(b,c,d,a,M[9],S[3][3],0xeb86d391);

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

//updatemd5,mustconsidertheremain_.
voidMD5::UpdateMd5(constuchar8input[],constintlength)
{
isDone_=false;
totalInputBits_+=(length<<3);

intstart=blockLen_-remainNum_;//blockLen_=64
//copyapartofinputtoremain_soitcanformablock(size=64)

if(start<=length)
{
//canformablock,thendoFourRoundtothisblock
memcpy(&remain_[remainNum_],input,start);
FourRound(remain_);

inti;
for(i=start;i<=length-blockLen_;i+=blockLen_)
{
FourRound(&input[i]);
}
remainNum_=length-i;
memcpy(remain_,&input[i],remainNum_);
}
else
{
//cannotformablock,functionreturn;
memcpy(&remain_[remainNum_],input,length);
remainNum_+=length;
}

}

voidMD5::UpdateMd5(constchar8input[],constintlength)
{
UpdateMd5((constuchar8*)input,length);
}

//paddingwith100000...toremain_andaddthe64bitoriginalsizeofinput
voidMD5::Finalize()
{
if(isDone_==true)
return;

uchar8padding[64]={
0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

inttemp=56-remainNum_;//56=448/8
if(temp>0)
{
UpdateMd5(padding,temp);
totalInputBits_-=(temp<<3);
}
elseif(temp<0)
{
UpdateMd5(padding,64+temp);
totalInputBits_-=((64+temp)<<3);
}

//transtotalInputBits_touchar8(64bits)
uchar8Bits[8];
for(inti=0;i<8;i++)
{
Bits[i]=(totalInputBits_>>8*i)&0xff;
}

UpdateMd5(Bits,8);//addthenumberoforiginalinput(thelast64bits)

LinkResult();
isDone_=true;
}

//computthemd5basedoninput,(justthisoneinput)
voidMD5::ComputMd5(constuchar8input[],constintlength)
{
init();
UpdateMd5(input,length);
Finalize();
}

voidMD5::ComputMd5(constchar8input[],constintlength)
{
ComputMd5((constuchar8*)input,length);
}