现在的位置: 首页 > 综合 > 正文

利用Windows的API实现C语言的MD5函数功能

2012年04月07日 ⁄ 综合 ⁄ 共 2565字 ⁄ 字号 评论关闭

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

}

抱歉!评论已关闭.