我有一个从文件生成哈希键的程序。
例如,程序的结果是"hash of file c:\Users\Jax\Desktop\files\file.txt is: 4db5a10d2ea73e3f76"
。
我有一个变量,它具有此file.txt的预期哈希值:
char hashExpected = "4db5a10d2ea73e3f76";
在代码的特定部分中,我验证程序的结果散列是否等于hashExpected
变量中存储的散列。我就像下面这样。我有hashResult
变量存储结果哈希所以我可以比较。但它无法正常工作,因为它始终显示Hash is different
,即使它相等。似乎hashResult
变量没有存储正确的值。
for (i = 0; i < cbHash; i++)
{
printf("%c%c",
rgbDigits[rgbHash[i] >> 4],
rgbDigits[rgbHash[i] & 0xf]);
hashResult[i] = rgbDigits[rgbHash[i] >> 4];
hashResult[i] += rgbDigits[rgbHash[i] & 0xf];
}
if (verify(hashResult, hashExpected))
{
printf("Hash is the same\n");
}
else
{
printf("Hash is different\n");
}
完整计划:
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#include <stdbool.h>
#define BUFSIZE 1024
#define MD5LEN 16
bool verify(char array1[], char array2[])
{
int i;
for (i = 0; array1[i] && array2[i]; ++i)
{
if (array1[i] != array2[i])
{
return false;
}
}
return true;
}
DWORD main()
{
DWORD dwStatus = 0;
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HANDLE hFile = NULL;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
CHAR rgbDigits[] = "0123456789abcdef";
PCSTR filename = "c:\\Users\\Jax\\Desktop\\files\\file.txt";
char hashActual[] = "4db5a10d2ea73e3f76";
char hashExpected[] = "4db5a10d2ea73e3f76";
char hashWrong[] = "0a0a0a0a0a0a0a";
char hashResult[] = "";
hFile = CreateFile(filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
dwStatus = GetLastError();
printf("Error opening file %s\nError: %d\n", filename,
dwStatus);
return dwStatus;
}
// Get handle to the crypto provider
if (!CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
return dwStatus;
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
return dwStatus;
}
while (bResult = ReadFile(hFile, rgbFile, BUFSIZE,
&cbRead, NULL))
{
if (0 == cbRead)
{
break;
}
if (!CryptHashData(hHash, rgbFile, cbRead, 0))
{
dwStatus = GetLastError();
printf("CryptHashData failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
}
if (!bResult)
{
dwStatus = GetLastError();
printf("ReadFile failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return dwStatus;
}
cbHash = MD5LEN;
if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
{
DWORD i;
printf("MD5 hash of file %s is: ", filename);
for (i = 0; i < cbHash; i++)
{
printf("%c%c",
rgbDigits[rgbHash[i] >> 4],
rgbDigits[rgbHash[i] & 0xf]);
hashResult[i] = rgbDigits[rgbHash[i] >> 4];
hashResult[i] += rgbDigits[rgbHash[i] & 0xf];
}
if (verify(hashResult, hashExpected))
{
printf("Hash is the same\n");
}
else
{
printf("Hash is different\n");
}
}
else
{
dwStatus = GetLastError();
printf("CryptGetHashParam failed: %d\n", dwStatus);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
return dwStatus;
}
答案 0 :(得分:0)
char hashExpected[] = "4db5a10d2ea73e3f76";
MD5值以上是错误的。 MD5值长度为16个字节。但那只是字节。我们不能在屏幕上打印字节,因此我们经常将字节转换为十六进制值。例如,如果我们有unsinged char bytes[3] = {0x01,0x01,0xFF}
,我们将字节转换为十六进制字符串,它变为"0102FF"
。
请注意,字符串表示形式是两倍加上一个nul-terminator。 MD5哈希的示例是:
"C4CA4238A0B923820DCC509A6F75849B"
字符串的缓冲区大小应为33
(16 x 2 + 1)
要找到正确的hashExpected
,请搜索&#34;在线MD5计算器&#34; 。您可以使用http://onlinemd5.com/之类的网站来计算文件的MD5。
或使用内容为1
的文件。 MD5("1")
为"C4CA4238A0B923820DCC509A6F75849B"
,将其用作预期的哈希值。
char hashResult[] = "";
上面的行是一个编程错误,正如@melpomene的评论中提到的
hashResult[i] = rgbDigits[rgbHash[i] >> 4];
hashResult[i] += rgbDigits[rgbHash[i] & 0xf];
上面的代码错了,你想要这个:
char hashResult[MD5LEN * 2 + 1] = "";
...
hashResult[i * 2] = rgbDigits[rgbHash[i] >> 4];
hashResult[i * 2 + 1] = rgbDigits[rgbHash[i] & 0xf];
函数verify
也存在问题,因为它将字节表示中的错误MD5与字符串表示中的错误MD5进行比较。
您可以使用strcmp
或_stricmp
来比较字符串表示中的MD5值。或者使用memcmp(data1, data2, 16)
直接比较字节。
完整示例:
#define BUFSIZE 1024
#define MD5LEN 16
int main()
{
DWORD dwStatus = 0;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HANDLE hFile = NULL;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
BYTE rgbHash[MD5LEN];
DWORD cbHash = 0;
CHAR rgbDigits[] = "0123456789abcdef";
PCSTR filename = "c:\\Users\\Jax\\Desktop\\files\\file.txt";
//assuming content of file.txt is '1'
char hashExpected[] = "C4CA4238A0B923820DCC509A6F75849B";
char hashResult[MD5LEN * 2 + 1] = "";
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
dwStatus = GetLastError();
printf("Error opening file %s\nError: %d\n", filename, dwStatus);
return (int)dwStatus;
}
// Get handle to the crypto provider
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
return (int)dwStatus;
}
if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
return (int)dwStatus;
}
while(ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
if(0 == cbRead)
break;
if(!CryptHashData(hHash, rgbFile, cbRead, 0))
{
dwStatus = GetLastError();
printf("CryptHashData failed: %d\n", dwStatus);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CloseHandle(hFile);
return (int)dwStatus;
}
}
cbHash = MD5LEN;
if(CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
{
DWORD i;
printf("MD5 expected, versus MD5 of file %s is:\n", filename);
printf("%s\n", hashExpected);
for(i = 0; i < cbHash; i++)
{
printf("%c%c",
rgbDigits[rgbHash[i] >> 4],
rgbDigits[rgbHash[i] & 0xf]);
hashResult[i * 2] = rgbDigits[rgbHash[i] >> 4];
hashResult[i * 2 + 1] = rgbDigits[rgbHash[i] & 0xf];
}
printf("\n");
if(_strcmpi(hashResult, hashExpected) == 0)
printf("Hash is the same\n");
else
printf("Hash is different\n");
}
else
{
dwStatus = GetLastError();
printf("CryptGetHashParam failed: %d\n", dwStatus);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
return (int)dwStatus;
}