Hello,
I wrote a program in C with the Win32 API that could, or was supposed to, be able to generate correct hashes for an input message. The algorithms to be used were all one-way, such as MD2, MD4, MD5, and SHA-1. These are the ones I tested, because apparently those are the ones Win32 support.
Then I wrote a PHP script to do much the same as I wanted to test the validity of the hashes based on the message I wanted hashed. When my script returned different hashes I decided to download a C program from MSDN (which I will also provide you with) to fix any possible mistakes I may have made.
The PHP script can be a single line:
Or you could use the hash() function like I did in my script: hash('message', 'md5')
I decided to combine it with an HTML form to make life easier, and I'm happy to share it with you if it helps. Both the PHP/HTML and C/Win32 are in "What I have tried", or you can download the latter here:
Example C Program: Creating an HMAC - Win32 apps | Microsoft Docs[
^]
I hope you can help me alter the C code to give the same results as the PHP functions, or at least help me understand why they don't. Thank you very much!
What I have tried:
<?php
error_reporting(0);
extract($_POST);
if (isset($data)) {
if ($algo == 'other') $algo = $other;
$hash = @hash($algo, $data);
if (is_bool($hash)) {
$hash = 'Fejl: "' . $other . '" er ikke en understøttet algoritme.';
}
}
?>
<form action="" method="post">
<b>Algorithm</b><br>
<input required type="radio" name="algo" value="md5" <?=$algo == 'md5' ? 'checked' : '';?>><span>MD5</span>
<input required type="radio" name="algo" value="sha1"<?=$algo == 'sha1' ? 'checked' : '';?>><span>SHA-1</span>
<input required type="radio" name="algo" value="sha256"<?=$algo == 'sha256' ? 'checked' : '';?>><span>SHA-2</span>
<input onclick="_focus('txt_oth');" required type="radio" name="algo" value="other" id="rad_oth" <?=$algo == $other ? 'checked' : '';?>><span>Other: </span>
<input onfocus="_check('rad_oth');" type="text" name="other" size="5" id="txt_oth" value="<?=$other;?>">
<br><br>
<textarea style="width: 100%; height: 100px;" name="data"><?=$data;?></textarea>
<br><br>
<input type="submit" value="Show hash">
<?php
if (isset($hash)) {
echo "<span> {$hash}</span>";
}
?>
</form>
<script>
function _focus(id) { document.getElementById(id).focus(); }
function _check(id) { document.getElementById(id).checked = true; }
</script>
And the C program I promised:
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
int main()
{
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHmacHash = NULL;
PBYTE pbHash = NULL;
DWORD dwDataLen = 0;
BYTE Data1[] = {0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64};
BYTE Data2[] = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
HMAC_INFO HmacInfo;
ZeroMemory(&HmacInfo, sizeof(HmacInfo));
HmacInfo.HashAlgid = CALG_SHA1;
if (!CryptAcquireContext(
&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
printf(" Error in AcquireContext 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptCreateHash(
hProv, CALG_SHA1, 0, 0, &hHash)) {
printf("Error in CryptCreateHash 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptHashData(
hHash, Data1, sizeof(Data1), 0)) {
printf("Error in CryptHashData 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptDeriveKey(
hProv, CALG_RC4, hHash, 0, &hKey)) {
printf("Error in CryptDeriveKey 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptCreateHash(
hProv, CALG_HMAC, hKey, 0, &hHmacHash)) {
printf("Error in CryptCreateHash 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptSetHashParam(
hHmacHash, HP_HMAC_INFO, (BYTE*)&HmacInfo, 0)) {
printf("Error in CryptSetHashParam 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptHashData(
hHmacHash, Data2, sizeof(Data2), 0)) {
printf("Error in CryptHashData 0x%08x \n",
GetLastError());
goto ErrorExit;
}
if (!CryptGetHashParam(
hHmacHash, HP_HASHVAL, NULL, &dwDataLen, 0))
{
printf("Error in CryptGetHashParam 0x%08x \n",
GetLastError());
goto ErrorExit;
}
pbHash = (BYTE*)malloc(dwDataLen);
if(NULL == pbHash)
{
printf("unable to allocate memory\n");
goto ErrorExit;
}
if (!CryptGetHashParam(
hHmacHash, HP_HASHVAL, pbHash, &dwDataLen, 0))
{
printf("Error in CryptGetHashParam 0x%08x \n", GetLastError());
goto ErrorExit;
}
printf("The hash is: ");
for(DWORD i = 0 ; i < dwDataLen ; i++)
{
printf("%2.2x ",pbHash[i]);
}
printf("\n");
ErrorExit:
if(hHmacHash)
CryptDestroyHash(hHmacHash);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hProv)
CryptReleaseContext(hProv, 0);
if(pbHash)
free(pbHash);
return 0;
}