采用系统提供的加密图形服务计算 MD5 哈希
计算内存块的哈希值一般采用 MD5,SHA 两种加密算法,现在最常用的仍然是 MD5,因为 MD5 有着速度快,冲突少的优势,下面就来说一些如何使用系统加密图形服务进行 MD5 计算,先参考封装的类:
#pragma once
#include <wincrypt.h>
namespace CryptGraphics
{
struct CryptContext
{
CryptContext(LPCTSTR szContainer = NULL, LPCTSTR szProvider = NULL, DWORD dwProvType = PROV_RSA_FULL)
{
hProvider = NULL; Acquire(szContainer, szProvider, dwProvType);
}
~CryptContext() { Release(); }
BOOL Acquire(LPCTSTR szContainer = NULL, LPCTSTR szProvider = NULL, DWORD dwProvType = PROV_RSA_FULL)
{
// 如果 szContainer 指定的容器存在,那么直接返回,否则新建一个。
CHK_EXP_RET(CryptAcquireContext(&hProvider, szContainer, szProvider, dwProvType, 0) , TRUE );
return CryptAcquireContext(&hProvider, szContainer, szProvider, dwProvType, CRYPT_NEWKEYSET);
}
BOOL Release()
{
BOOL bReturn = CryptReleaseContext(hProvider, NULL);
hProvider = NULL; return bReturn;
}
HCRYPTPROV hProvider;
};
class CHashMD5 : public CryptContext
{
public:
CHashMD5( ) : hChiper( NULL ) { Initialize(); }
~CHashMD5( ) { Terminate( ); }
public:
BOOL Chiper( LPBYTE lpData , DWORD dwSize ) { return CryptHashData(hChiper, lpData, dwSize, 0); }
BOOL Result( DWORD& dwSize, LPBYTE lpData = NULL )
{
DWORD dwParam = lpData == NULL ? HP_HASHSIZE : HP_HASHVAL ;
return CryptGetHashParam(hChiper, dwParam, lpData, &dwSize, 0);
}
public:
BOOL Create( ) { return CryptCreateHash(hProvider, CALG_MD5, NULL, 0, &hChiper); }
BOOL Destroy( ) { return CryptDestroyHash(hChiper); }
protected:
BOOL Initialize() { return Create(); }
BOOL Terminate() { return Destroy(); }
protected:
HCRYPTHASH hChiper;
};
}
#include <wincrypt.h>
namespace CryptGraphics
{
struct CryptContext
{
CryptContext(LPCTSTR szContainer = NULL, LPCTSTR szProvider = NULL, DWORD dwProvType = PROV_RSA_FULL)
{
hProvider = NULL; Acquire(szContainer, szProvider, dwProvType);
}
~CryptContext() { Release(); }
BOOL Acquire(LPCTSTR szContainer = NULL, LPCTSTR szProvider = NULL, DWORD dwProvType = PROV_RSA_FULL)
{
// 如果 szContainer 指定的容器存在,那么直接返回,否则新建一个。
CHK_EXP_RET(CryptAcquireContext(&hProvider, szContainer, szProvider, dwProvType, 0) , TRUE );
return CryptAcquireContext(&hProvider, szContainer, szProvider, dwProvType, CRYPT_NEWKEYSET);
}
BOOL Release()
{
BOOL bReturn = CryptReleaseContext(hProvider, NULL);
hProvider = NULL; return bReturn;
}
HCRYPTPROV hProvider;
};
class CHashMD5 : public CryptContext
{
public:
CHashMD5( ) : hChiper( NULL ) { Initialize(); }
~CHashMD5( ) { Terminate( ); }
public:
BOOL Chiper( LPBYTE lpData , DWORD dwSize ) { return CryptHashData(hChiper, lpData, dwSize, 0); }
BOOL Result( DWORD& dwSize, LPBYTE lpData = NULL )
{
DWORD dwParam = lpData == NULL ? HP_HASHSIZE : HP_HASHVAL ;
return CryptGetHashParam(hChiper, dwParam, lpData, &dwSize, 0);
}
public:
BOOL Create( ) { return CryptCreateHash(hProvider, CALG_MD5, NULL, 0, &hChiper); }
BOOL Destroy( ) { return CryptDestroyHash(hChiper); }
protected:
BOOL Initialize() { return Create(); }
BOOL Terminate() { return Destroy(); }
protected:
HCRYPTHASH hChiper;
};
}
有了上面的封装类,计算 MD5 就简单多了,参考如下代码:
CryptGraphics::CHashMD5 xChiper;
xChiper.Chiper((LPBYTE)lpData, dwData);
DWORD dwResult[4] = { 0 };
DWORD dwSize = sizeof(dwResult);
xChiper.Result(dwSize, (LPBYTE)dwResult);
xChiper.Chiper((LPBYTE)lpData, dwData);
DWORD dwResult[4] = { 0 };
DWORD dwSize = sizeof(dwResult);
xChiper.Result(dwSize, (LPBYTE)dwResult);
另外如果是需要对文件计算 MD5 HASH ,其实可以不必自己实现加载文件到内存进行 MD5 运算的复制代码,使用 MSI 中提供的函数就可以简单实现,如下所示:
MSIFILEHASHINFO xHashInfo = { sizeof( MSIFILEHASHINFO ) };
UINT nCaller = MsiGetFileHash( szPath , 0 , & xHashInfo );
UINT nCaller = MsiGetFileHash( szPath , 0 , & xHashInfo );
判断返回值即可知道 MD5 计算是否成功,如果成功,计算的结果就放在 xHashInfo 的 dwData 数组中,
虽然 MD5 现在已经可以算是被破解了(山东大学王晓云女博士提供了可以在很短时间内伪造MD5签名的算法),但是仅限于使用 MD5 的结果来对机密信息进行加密不再安全了,如果是一般性应用还是没有任何问题的,当然如果对 MD5 不放心的话可以使用 SHA , 当然要 SHA-256 及其以上的才行;