Code:
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "advapi32.lib")
/*
* Creates a hexadecimal hash string from input data.
* ALG_ID can be one of CALG_MD2, CALG_MD4, CALG_MD5 or CALG_SHA1.
* SHA1 algorithm is strongest, while MD2 and MD4 should be avoided.
* MD algorithms require a 33 character output buffer. SHA1 requires 41 characters.
* Returns TRUE on success, FALSE on failure.
*/
BOOL HashData(LPTSTR szOut, DWORD cchOut, LPCBYTE lpIn, DWORD cbIn, ALG_ID hash_algorithm)
{
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE raw[64];
DWORD raw_len = sizeof(raw);
BOOL bResult = FALSE;
UINT i;
if(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT) &&
CryptCreateHash(hProv, hash_algorithm, 0, 0, &hHash) &&
CryptHashData(hHash, lpIn, cbIn, 0) &&
CryptGetHashParam(hHash, HP_HASHVAL, raw, &raw_len, 0) &&
(raw_len * 2) + 1 <= cchOut)
{
for (i = 0;i < raw_len;i++)
{
wsprintf(&szOut[i * 2], TEXT("%02.2x"), raw[i]);
}
bResult = TRUE;
}
if (hHash) CryptDestroyHash(hHash);
if (hProv) CryptReleaseContext(hProv, 0);
return bResult;
}
#if 1
#include <stdio.h>
int main(void)
{
TCHAR szHash[64];
char * test = "Hello, this is a test";
printf("Input: %s\n", test);
if (HashData(szHash, 33, test, strlen(test), CALG_MD5))
printf("MD5: %s\n", szHash);
if (HashData(szHash, 33, test, strlen(test), CALG_MD2))
printf("MD2: %s\n", szHash);
if (HashData(szHash, 33, test, strlen(test), CALG_MD4))
printf("MD4: %s\n", szHash);
if (HashData(szHash, 41, test, strlen(test), CALG_SHA1))
printf("SHA1: %s\n", szHash);
getchar();
return 0;
}
#endif
/// ===================================================================
/// Hashing in chunks.
HCRYPTHASH HashInit(HCRYPTPROV hCryptProvider, ALG_ID hash_algorithm)
{
HCRYPTHASH hHash = 0;
CryptCreateHash(hCryptProvider, hash_algorithm, 0, 0, &hHash);
return hHash;
}
BOOL HashUpdate(HCRYPTHASH hHash, LPCBYTE lpData, DWORD cbData)
{
return CryptHashData(hHash, lpData, cbData, 0);
}
BOOL HashFinal(HCRYPTHASH hHash, LPTSTR szOut, DWORD cchOut)
{
BYTE raw[64];
DWORD raw_len = sizeof(raw);
BOOL bResult = FALSE;
UINT i;
if (CryptGetHashParam(hHash, HP_HASHVAL, raw, &raw_len, 0) &&
(raw_len * 2) + 1 <= cchOut)
{
for (i = 0;i < raw_len;i++)
{
wsprintf(&szOut[i * 2], TEXT("%02.2x"), raw[i]);
}
bResult = TRUE;
}
if (hHash) CryptDestroyHash(hHash);
return bResult;
}
#if 0
#include <stdio.h>
int main(void)
{
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
TCHAR szHash[64];
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
hHash = HashInit(hProv, CALG_MD5);
HashUpdate(hHash, "abcd", strlen("abcd"));
HashUpdate(hHash, "efgh", strlen("efgh"));
HashFinal(hHash, szHash, 33);
printf("MD5: %s\n", szHash);
hHash = HashInit(hProv, CALG_SHA1);
HashUpdate(hHash, "abcd", strlen("abcd"));
HashUpdate(hHash, "efgh", strlen("efgh"));
HashFinal(hHash, szHash, 41);
printf("SHA1: %s\n", szHash);
CryptReleaseContext(hProv, 0);
getchar();
return 0;
}
#endif
I have to comment on this, from the Microsoft sample code: