最近公司的一个项目要在windows下实现MD5的函数功能,所以查阅了一些资料,现在我将完整实现发布,希望对有需要的人有帮助
实现就是这样子,大家如有需要直接用就可以,没怎么有必要去研究那几个Windows API,具体就不再细说了,有问题欢迎提问。
#include "windows.h" #include <tchar.h> #include <stdio.h> /*调用Windows API 获得 MD5 码 */ void GetMd5(LPCWSTR FileDirectory,char *pMD5 ) { HANDLE hFile=CreateFile(FileDirectory,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL); if (hFile==INVALID_HANDLE_VALUE) //如果CreateFile调用失败 { printf("CreateFile go wrong \n "); //提示CreateFile调用失败,并输出错误号。visual studio中可在“工具”>“错误查找”中利用错误号得到错误信息。 CloseHandle(hFile); } HCRYPTPROV hProv=NULL; if(CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)==FALSE) //获得CSP中一个密钥容器的句柄 { printf("CryptAcquireContext go wrong \n "); } HCRYPTPROV hHash=NULL; if(CryptCreateHash(hProv,CALG_MD5,0,0,&hHash)==FALSE) //初始化对数据流的hash,创建并返回一个与CSP的hash对象相关的句柄。这个句柄接下来将被CryptHashData调用。 { printf("CryptCreateHash go wrong \n "); } DWORD dwFileSize=GetFileSize(hFile,0); //获取文件的大小 if (dwFileSize==0xFFFFFFFF) //如果获取文件大小失败 { printf("GetFileSize go wrong \n "); } byte* lpReadFileBuffer=new byte[dwFileSize]; DWORD lpReadNumberOfBytes; if (ReadFile(hFile,lpReadFileBuffer,dwFileSize,&lpReadNumberOfBytes,NULL)==0) //读取文件 { printf("ReadFile go wrong \n "); } if(CryptHashData(hHash,lpReadFileBuffer,lpReadNumberOfBytes,0)==FALSE) //hash文件 { printf("CryptHashData go wrong \n "); } delete[] lpReadFileBuffer; CloseHandle(hFile); //关闭文件句柄 BYTE *pbHash; DWORD dwHashLen=sizeof(DWORD); if (CryptGetHashParam(hHash,HP_HASHVAL,NULL,&dwHashLen,0)) //我也不知道为什么要先这样调用CryptGetHashParam,这块是参照的msdn { } else { printf("get length wrong\n"); } if(pbHash=(byte*)malloc(dwHashLen)) {} else { printf("allocation failed\n"); } if(CryptGetHashParam(hHash,HP_HASHVAL,pbHash,&dwHashLen,0)) //获得md5值 { DWORD i; for( i=0;i<dwHashLen;i++) //输出md5值 { //printf("%02x",pbHash[i]); sprintf(pMD5+i*2,"%02x",pbHash[i]); } // printf("\n"); } //善后工作 if(CryptDestroyHash(hHash)==FALSE) //销毁hash对象 { printf("CryptReleaseContext go wrong: [%d] \n"); } if(CryptReleaseContext(hProv,0)==FALSE) { printf("CryptReleaseContext go wrong: [%d] \n"); } } /*将char 转换成 WCHAR并调用GetMd5 */ void C2W_GetMD5(char *FilePath,char *pMD5) //因为在Windows API中的WCHAR是宽字符(16位)的,而C语言中的是短字符(8位)的所以要进行转换,具体区别请查阅其他资料 { int textlen ; wchar_t * wDest; //MultiByteToWideChar() 函数是将短字符转成宽字符的关键,如要细究请百度。 textlen = MultiByteToWideChar(CP_ACP, 0, FilePath,-1,NULL,0 ); wDest = (wchar_t *)malloc((textlen+1)*sizeof(wchar_t)); if (wDest == NULL) { return ; } memset(wDest,0,(textlen+1)*sizeof(wchar_t)); MultiByteToWideChar(CP_ACP, 0,FilePath,-1,(LPWSTR)wDest,textlen); GetMd5(wDest,pMD5); free(wDest); } //main函数,实现例子 void main() { char *hello1 = "C:\\Users\\Chen\\Desktop\\world.txt"; //文件的绝对路径 char hello[33]; //转换后的MD5是32位的 C2W_GetMD5(hello1,hello); printf("%s\n",hello); //打印出该文件的MD5 }