最近公司的一个项目要在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
}