md5加密算法c实现!七分注释!!收藏!经常到csdn来是查资料,每次都会有所收获。总是看别人的感觉很不好意思,于是决定自己也写一点东西贡献出来。于是就有了这篇md5七分注释。希望对用到的朋友有所帮助。记得当初自己刚开始学习md5的时候,从网上搜了很多关于算法的原理和文字性的描述的东西,但是看了很久一直没有搞懂,搜c的源代码又很少。直到后来学习rsa算法的时候,从网上下了1991年的欧洲的什么组织写的关于rsa、des、md5算法的c源代码(各部分代码混在一块的,比如rsa用到的随机大素数就是用机器的随机时间的md5哈希值获得的)。我才彻底把md5弄明白了。这里的代码就是我从那里面分离出来的,代码的效率和可重用性都是很高的。整理了一下希望对需要的朋友能够有帮助。md5的介绍的文章网上很多,关于md5的来历,用途什么的这里就不再介绍了。这里主要介绍代码。代码明白了就什么都明白了。/////////////////////////////////////////////////////////////////////*md5.h*/#ifndef_MD5_H_#define_MD5_H_#defineR_memset(x,y,z)memset(x,y,z)#defineR_memcpy(x,y,z)memcpy(x,y,z)#defineR_memcmp(x,y,z)memcmp(x,y,z)typedefunsignedlongUINT4;typedefunsignedchar*POINTER;/*MD5context.*/typedefstruct{/*state(ABCD)*//*四个32bits数,用于存放最终计算得到的消息摘要。当消息长度〉512bits时,也用于存放每个512bits的中间结果*/UINT4state[4];/*numberofbits,modulo2^64(lsbfirst)*//*存储原始信息的bits数长度,不包括填充的bits,最长为2^64bits,因为2^64是一个64位数的最大值*/UINT4count[2];/*inputbuffer*//*存放输入的信息的缓冲区,512bits*/unsignedcharbuffer[64];}MD5_CTX;voidMD5Init(MD5_CTX*);voidMD5Update(MD5_CTX*,unsignedchar*,unsignedint);voidMD5Final(unsignedchar[16],MD5_CTX*);#endif/*_MD5_H_*/////////////////////////////////////////////////////////////////////////////*md5.cpp*/#includestdafx.h/*ConstantsforMD5Transformroutine.*//*md5转换用到的常量,算法本身规定的*/#defineS117#defineS1212#defineS1317#defineS1422#defineS215#defineS229#defineS2314#defineS2420#defineS314#defineS3211#defineS3316#defineS3423#defineS416#defineS4210#defineS4315#defineS4421staticvoidMD5Transform(UINT4[4],unsignedchar[64]);staticvoidEncode(unsignedchar*,UINT4*,unsignedint);staticvoidDecode(UINT4*,unsignedchar*,unsignedint);/*用于bits填充的缓冲区,为什么要64个字节呢?因为当欲加密的信息的bits数被512除其余数为448时,需要填充的bits的最大值为512=64*8。*/staticunsignedcharPADDING[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};/*接下来的这几个宏定义是md5算法规定的,就是对信息进行md5加密都要做的运算。据说有经验的高手跟踪程序时根据这几个特殊的操作就可以断定是不是用的md5*//*F,G,HandIarebasicMD5functions.*/#defineF(x,y,z)(((x)&(y))|((~x)&(z)))#defineG(x,y,z)(((x)&(z))|((y)&(~z)))#defineH(x,y,z)((x)^(y)^(z))#defineI(x,y,z)((y)^((x)|(~z)))/*ROTATE_LEFTrotatesxleftnbits.*/#defineROTATE_LEFT(x,n)(((x)(n))|((x)(32-(n))))/*FF,GG,HH,andIItransformationsforrounds1,2,3,and4.Rotationisseparatefromadditiontopreventrecomputation.*/#defineFF(a,b,c,d,x,s,ac){\(a)+=F((b),(c),(d))+(x)+(UINT4)(ac);\(a)=ROTATE_LEFT((a),(s));\(a)+=(b);\}#defineGG(a,b,c,d,x,s,ac){\(a)+=G((b),(c),(d))+(x)+(UINT4)(ac);\(a)=ROTATE_LEFT((a),(s));\(a)+=(b);\}#defineHH(a,b,c,d,x,s,ac){\(a)+=H((b),(c),(d))+(x)+(UINT4)(ac);\(a)=ROTATE_LEFT((a),(s));\(a)+=(b);\}#defineII(a,b,c,d,x,s,ac){\(a)+=I((b),(c),(d))+(x)+(UINT4)(ac);\(a)=ROTATE_LEFT((a),(s));\(a)+=(b);\}/*MD5initialization.BeginsanMD5operation,writinganewcontext.*//*初始化md5的结构*/voidMD5Init(MD5_CTX*context){/*将当前的有效信息的长度设成0,这个很简单,还没有有效信息,长度当然是0了*/context-count[0]=context-count[1]=0;/*Loadmagicinitializationconstants.*//*初始化链接变量,算法要求这样,这个没法解释了*/context-state[0]=0x67452301;context-state[1]=0xefcdab89;context-state[2]=0x98badcfe;context-state[3]=0x10325476;}/*MD5blockupdateoperation.ContinuesanMD5message-digestoperation,processinganothermessageblock,andupdatingthecontext.*//*将与加密的信息传递给md5结构,可以多次调用context:初始化过了的md5结构input:欲加密的信息,可以任意长inputLen:指定input的长度*/voidMD5Update(MD5_CTX*context,unsignedchar*input,unsignedintinputLen){unsignedinti,index,partLen;/*Computenumberofbytesmod64*//*计算已有信息的bits长度的字节数的模64,64bytes=512bits。用于判断已有信息加上当前传过来的信息的总长度能不能达到512bits,如果能够达到则对凑够的512bits进行一次处理*/index=(unsignedint)((context-count[0]3)&0x3F);/*Updatenumberofbits*//*更新已有信息的bits长度*/if((context-count[0]+=((UINT4)inputLen3))((UINT4)inputLen3))context-count[1]++;context-count[1]+=((UINT4)inputLen29);/*计算已有的字节数长度还差多少字节可以凑成64的整倍数*/partLen=64-index;/*Transformasmanytimesaspossible.*//*如果当前输入的字节数大于已有字节数长度补足64字节整倍数所差的字节数*/if(inputLen=partLen){/*用当前输入的内容把context-buffer的内容补足512bits*/R_memcpy((POINTER)&context-buffer[index],(POINTER)input,partLen);/*用基本函数对填充满的512bits(已经保存到context-buffer中)做一次转换,转换结果保存到context-state中*/MD5Transform(context-state,context-buffer);/*对当前输入的剩余字节做转换(如果剩余的字节在输入的input缓冲区中大于512bits的话),转换结果保存到context-state中*/for(i=partLen;i+63inputLen;i+=64)/*把i+63inputlen改为i+64=inputlen更容易理解*/MD5Transform(context-state,&input[i]);index=0;}elsei=0;/*Bufferremaininginput*//*将输入缓冲区中的不足填充满512bits的剩余内容填充到context-buffer中,留待以后再作处理*/R_memcpy((POINTER)&context-buffer[index],(POINTER)&input[i],inputLen-i);}/*MD5finalization.EndsanMD5message-digestoperation,writingthethemessagedigestandzeroizingthecontext.*//*获取加密的最终结果digest:保存最终的加密串context:你前面初始化并填入了信息的md5结构*/voidMD5Final(unsignedchardigest[16],MD5_CTX*context){unsignedcharbits[8];unsignedintindex,padLen;/*Savenumberofbits*//*将要被转换的信息(所有的)的bits长度拷贝到bits中*/Encode(bits,context-count,8);/*Padoutto56mod64.*//*计算所有的bits长度的字节数的模64,64bytes=512bits*/index=(unsignedint)((context-count[0]3)&0x3f);/*计算需要填充的字节数,padLen的取值范围在1-64之间*/padLen=(index56)?(56-index):(120-index);/*这一次函数调用绝对不会再导致MD5Transform的被调用,因为这一次不会填满512bits*/MD5Update(context,PADDING,padLen);