CryptCreateHashを利用するとハッシュを計算できる。このAPIは利用できるOSに制限があるものもあるがMD5以外にもSHA-1やMD4、SHA-256、SHA-512など様々なハッシュ計算に対応している。
ここで作成した関数は簡単にするためメモリ上のデータを一括してハッシュ計算処理に回している。小さなデータであればこの関数で十分だ。しかしファイルハッシュを計算したいときなどにはこの関数は利用しない方がいい。ファイルハッシュ計算時はファイルを少しずつ読み出しCryptHashDataを何度も呼び出して計算するのがいい。
依存環境:ATL#include "atlstr.h"
#include "wincrypt.h"
//
// MD5ハッシュ計算(128ビット)
//
//対応:Windows 95 OSR2以降
//
bool GetMD5Hash(const void* pData,DWORD dwLen,BYTE pcbHashData[16])
{
bool ret;
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
BYTE pbHash[0x7f];
DWORD dwHashLen;
::ZeroMemory(pcbHashData,16);
if(pData == NULL || dwLen == 0)
return false;
dwHashLen = 16;
hHash = NULL;
hCryptProv = NULL;
ret = false;
if(::CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET))
{
if(::CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash))
{
if(::CryptHashData(hHash,(BYTE*)pData,dwLen,0))
{
if(::CryptGetHashParam(hHash,HP_HASHVAL,pbHash,&dwHashLen,0))
{
::memcpy_s(pcbHashData,dwHashLen,pbHash,dwHashLen);
ret = true;
}
}
}
}
if(hHash)
::CryptDestroyHash(hHash);
if(hCryptProv)
::CryptReleaseContext(hCryptProv,0);
if(ret == false)
::ZeroMemory(pcbHashData,dwHashLen);
return ret;
}
void Test(void)
{
bool ret;
int i;
BYTE pcbData[16];
CAtlString strTmp;
CAtlString strMessage;
//"abc"という文字のMD5ハッシュを計算
ret = GetMD5Hash("abc",3,pcbData);
if(ret == false)
{
::MessageBox(NULL,_T("取得に失敗しました"),_T(""),MB_OK);
return;
}
for(i = 0; i < 16; i++)
{
strTmp.Format(_T("%x"),pcbData[i]);
strMessage += strTmp;
}
::MessageBox(NULL,strMessage,_T(""),MB_OK);
}
