#ifndefXCRYTO__H_H#defineXCRYTO__H_H#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#defineF1(x, y, z)(z ^(x &(y ^ z)))#defineF2(x, y, z)F1(z, x, y)#defineF3(x, y, z)(x ^ y ^ z)#defineF4(x, y, z)(y ^(x |~z))#defineMD5STEP(f, w, x, y, z, data, s)( w +=f(x, y, z)+ data, w =w<<s | w>>(32-s), w += x)classxcrypto{public:typedefstructmd5_context{unsignedint buf[4];unsignedint bits[2];unsignedchar in[64];} MD5_CTX;public:xcrypto();~xcrypto();public:static std::string get_md5(std::string input);static std::string get_file_md5(std::string file_path,int* ret_file_len);protected:staticvoidbyte_reverse(unsignedchar* buf,unsigned longs);staticvoidmd5_init(structmd5_context* ctx);staticvoidmd5_update(structmd5_context* ctx,unsignedchar* buf,unsigned len);staticvoidmd5_final(unsignedchar digest[16],structmd5_context* ctx);//The core of the MD5 algorithmstaticvoidmd5_transform(unsignedint buf[4],unsignedint in[16]);};#endif
xcrypto.cpp
#include"xcrypto.h"//十六进制转字符串staticinthex_to_str(unsignedchar* b_data,char* s_data,int data_len){constchar arrchar[256][4]={"00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F","10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F","20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F","30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F","40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F","50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F","60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F","70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F","80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F","90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F","A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF","B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF","C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF","D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF","E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","DE","EF","F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"};for(int i =0; i <data_len; i++){memcpy(s_data+(i<<1),arrchar[b_data[i]],2);}return(data_len <<1);}
std::string xcrypto::get_md5(std::string input){structmd5_context md5c;unsignedchar md5nature[16]={0};md5_init(&md5c);md5_update(&md5c,(unsignedchar*)input.data(),(unsignedint)input.length());md5_final(md5nature,&md5c);char cal_md5[36]={0};hex_to_str(md5nature,cal_md5,16);
cal_md5[32]='\0';for(unsignedint i =0; i <strlen(cal_md5); i++) cal_md5[i]=tolower(cal_md5[i]);return std::string(cal_md5);}
std::string xcrypto::get_file_md5(std::string file_path,int* ret_file_len){
FILE *fd_file =fopen(file_path.c_str(),"rb");if(!fd_file){if(ret_file_len){*ret_file_len =0;}return"";}structmd5_context md5c;unsignedchar md5nature[16]={0};md5_init(&md5c);//获取文件长度if(ret_file_len){//定位到文件末尾fseek(fd_file,0L,SEEK_END);//得到文件大小*ret_file_len =ftell(fd_file);//定位到文件开头fseek(fd_file,0L,SEEK_SET);}int read_len =0;char read_buff[1024]={0};do{
read_len =fread(read_buff,1,1024,fd_file);if(read_len >0){md5_update(&md5c,(unsignedchar*)read_buff,(unsignedint)read_len);}}while(read_len >=1024);fclose(fd_file);
fd_file =NULL;md5_final(md5nature,&md5c);char cal_md5[36]={0};hex_to_str(md5nature,cal_md5,16);
cal_md5[32]='\0';for(unsignedint i =0; i <strlen(cal_md5); i++) cal_md5[i]=tolower(cal_md5[i]);return std::string(cal_md5);}void xcrypto::byte_reverse(unsignedchar* buf,unsigned longs){unsignedint t;do{
t =(unsignedint)((unsigned) buf[3]<<8| buf[2])<<16|((unsigned) buf[1]<<8| buf[0]);*(unsignedint*) buf = t;
buf +=4;}while(--longs);}void xcrypto::md5_init(structmd5_context* ctx){
ctx->buf[0]=0x67452301;
ctx->buf[1]=0xefcdab89;
ctx->buf[2]=0x98badcfe;
ctx->buf[3]=0x10325476;
ctx->bits[0]=0;
ctx->bits[1]=0;}//Update context to reflect the concatentaion of another buffer full of bytesvoid xcrypto::md5_update(structmd5_context* ctx,unsignedchar* buf,unsigned len){unsignedint t = ctx->bits[0];if((ctx->bits[0]= t +((unsignedint) len <<3))< t){
ctx->bits[1]++;//Carry from to high}
ctx->bits[1]+= len >>29;
t =(t >>3)&0x03f;//Bytes already int sshInfo->dataif(t){unsignedchar*p =(unsignedchar*) ctx->in + t;
t =64- t;if(len < t){memcpy(p, buf, len);return;}memcpy(p,buf,t);byte_reverse(ctx->in,16);md5_transform(ctx->buf,(unsignedint*)ctx->in);
buf += t;
len -= t;}//Process data in 64 bytes chunkswhile( len >=64){memcpy(ctx->in,buf,64);byte_reverse(ctx->in,16);md5_transform(ctx->buf,(unsignedint*)ctx->in);
buf +=64;
len -=64;}//Handle any remaining bytes of datamemcpy(ctx->in,buf,len);}//Final wrapup - pad to 64-byte boundary with the bit pattern 1 0*(64-bit count of bits processed, MSB-first)void xcrypto::md5_final(unsignedchar digest[16],structmd5_context* ctx){unsigned count =(ctx->bits[0]>>3)&0x03f;//Compute number of bytes mod 64unsignedchar*p = ctx->in + count;*p++=0x80;//Set the first char of padding to 0x80. This is safe since there is always at least one byte free
count =64-1-count;//Bytes of padding needed to make 64 bytesif(count <8)//Pad out to 56 mod 64{memset(p,0,count);byte_reverse(ctx->in,16);md5_transform(ctx->buf,(unsignedint*)ctx->in);//Two lots of padding: Pad the first block to 64 bytesmemset(ctx->in,0,56);//Now fill the next block with 56 bytes}else{memset(p,0,count -8);}byte_reverse(ctx->in,14);((unsignedint*) ctx->in)[14]= ctx->bits[0];//Append length in bits and transform((unsignedint*) ctx->in)[15]= ctx->bits[1];md5_transform(ctx->buf,(unsignedint*) ctx->in);byte_reverse((unsignedchar*) ctx->buf,4);memcpy(digest,ctx->buf,16);memset(ctx,0,(size_t)sizeof(md5_context));//In case It's sensitive}void xcrypto::md5_transform(unsignedint buf[4],unsignedint in[16]){registerunsignedint a,b,c,d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];MD5STEP(F1, a, b, c, d, in[0]+0xd76aa478,7);MD5STEP(F1, d, a, b, c, in[1]+0xe8c7b756,12);MD5STEP(F1, c, d, a, b, in[2]+0x242070db,17);MD5STEP(F1, b, c, d, a, in[3]+0xc1bdceee,22);MD5STEP(F1, a, b, c, d, in[4]+0xf57c0faf,7);MD5STEP(F1, d, a, b, c, in[5]+0x4787c62a,12);MD5STEP(F1, c, d, a, b, in[6]+0xa8304613,17);MD5STEP(F1, b, c, d, a, in[7]+0xfd469501,22);MD5STEP(F1, a, b, c, d, in[8]+0x698098d8,7);MD5STEP(F1, d, a, b, c, in[9]+0x8b44f7af,12);MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1,17);MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be,22);MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,7);MD5STEP(F1, d, a, b, c, in[13]+0xfd987193,12);MD5STEP(F1, c, d, a, b, in[14]+0xa679438e,17);MD5STEP(F1, b, c, d, a, in[15]+0x49b40821,22);MD5STEP(F2, a, b, c, d, in[1]+0xf61e2562,5);MD5STEP(F2, d, a, b, c, in[6]+0xc040b340,9);MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51,14);MD5STEP(F2, b, c, d, a, in[0]+0xe9b6c7aa,20);MD5STEP(F2, a, b, c, d, in[5]+0xd62f105d,5);MD5STEP(F2, d, a, b, c, in[10]+0x02441453,9);MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681,14);MD5STEP(F2, b, c, d, a, in[4]+0xe7d3fbc8,20);MD5STEP(F2, a, b, c, d, in[9]+0x21e1cde6,5);MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,9);MD5STEP(F2, c, d, a, b, in[3]+0xf4d50d87,14);MD5STEP(F2, b, c, d, a, in[8]+0x455a14ed,20);MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,5);MD5STEP(F2, d, a, b, c, in[2]+0xfcefa3f8,9);MD5STEP(F2, c, d, a, b, in[7]+0x676f02d9,14);MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a,20);MD5STEP(F3, a, b, c, d, in[5]+0xfffa3942,4);MD5STEP(F3, d, a, b, c, in[8]+0x8771f681,11);MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122,16);MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c,23);MD5STEP(F3, a, b, c, d, in[1]+0xa4beea44,4);MD5STEP(F3, d, a, b, c, in[4]+0x4bdecfa9,11);MD5STEP(F3, c, d, a, b, in[7]+0xf6bb4b60,16);MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70,23);MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,4);MD5STEP(F3, d, a, b, c, in[0]+0xeaa127fa,11);MD5STEP(F3, c, d, a, b, in[3]+0xd4ef3085,16);MD5STEP(F3, b, c, d, a, in[6]+0x04881d05,23);MD5STEP(F3, a, b, c, d, in[9]+0xd9d4d039,4);MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5,11);MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8,16);MD5STEP(F3, b, c, d, a, in[2]+0xc4ac5665,23);MD5STEP(F4, a, b, c, d, in[0]+0xf4292244,6);MD5STEP(F4, d, a, b, c, in[7]+0x432aff97,10);MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7,15);MD5STEP(F4, b, c, d, a, in[5]+0xfc93a039,21);MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,6);MD5STEP(F4, d, a, b, c, in[3]+0x8f0ccc92,10);MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d,15);MD5STEP(F4, b, c, d, a, in[1]+0x85845dd1,21);MD5STEP(F4, a, b, c, d, in[8]+0x6fa87e4f,6);MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0,10);MD5STEP(F4, c, d, a, b, in[6]+0xa3014314,15);MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1,21);MD5STEP(F4, a, b, c, d, in[4]+0xf7537e82,6);MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235,10);MD5STEP(F4, c, d, a, b, in[2]+0x2ad7d2bb,15);MD5STEP(F4, b, c, d, a, in[9]+0xeb86d391,21);
buf[0]+= a;
buf[1]+= b;
buf[2]+= c;
buf[3]+= d;}
test_xcrypto.cpp
#include"xcrypto.h"#include<stdio.h>intmain(int argc,char** argv){if(argc ==2){int file_size =0;
std::string file_path(argv[1]);
std::string md5_str = xcrypto::get_file_md5(file_path,&file_size);printf("file=%s md5=%s\n",file_path.c_str(),md5_str.c_str());}else{printf("argc number is error\n");}return0;}