Я новичок здесь, я надеюсь, что я делаю это правильно.
Я сделал приложение на C ++, которое вычисляет хэш-дайджест MD5 для следующих файлов
реализация Microsoft в этой ссылке http://msdn.microsoft.com/en-us/library/windows/desktop/aa382380%28v=vs.85%29.aspx
дело в том, что дайджест хеша md5 является правильным для любого файла типа при сравнении его с любым готовым инструментом, который вычисляет дайджест md5. кроме случаев, когда файл в руках является исполняемым файлом, например cmd.exe. Дайджест хеша отличается и зависит от местоположения исполняемого файла. если вы переместите cmd.exe в другое место, дайджест снова станет другим. поэтому я продолжил реализацию той же функциональности, используя библиотеку openssl, чтобы столкнуться с той же проблемой. Я заметил, что хеш-дайджест от реализации Microsoft и openssl одинаков. поэтому я думаю, что чего-то не хватает в чтении файла перед его передачей для вычисления дайджеста. но я много искал, чтобы ничего не найти.
Я попытался прочитать файл, используя «createfile» из win API и «fopen», чтобы получить тот же результат … поэтому, пожалуйста, помогите мне с этим, что я пропускаю?
вот исходный код
#include "stdafx.h"#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define BUFSIZE 1024
#define MD5LEN 16
int _tmain(int argc, _TCHAR* argv[])
{
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";
LPCWSTR filename=L"C:\\Windows\\System32\\cmd.exe";
// Logic to check usage goes here.
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))
{
printf("MD5 hash of file %s is: ", filename);
for (DWORD i = 0; i < cbHash; i++)
{
printf("%c%c", rgbDigits[rgbHash[i] >> 4],
rgbDigits[rgbHash[i] & 0xf]);
}
printf("\n");
}
else
{
dwStatus = GetLastError();
printf("CryptGetHashParam failed: %d\n", dwStatus);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
return dwStatus;return 0;
}
этот код вычисляет хеш «59a1d4facd7b333f76c4142cd42d3aba», с другой стороны «инструмент хэширования цифрового вулкана», а «утилита md5 и контрольная сумма sha v2.1» вычисляет хеш «fc0b4a626881d7c5980d757214db2d25»
Ваш код правильный! Вы столкнулись с особенностью Windows.
Файл, который вы читаете, находится внутри C:\Windows\System32
каталог.
В 64-битной Windows, если 32-битное приложение пытается получить доступ к этому каталогу он перенаправляется в C:\Windows\SysWow64
,
Как есть cmd.exe
файлы в обоих C:\Windows\System32
а также C:\Windows\SysWow64
, но это разные сборки и разные хэши, программы проверяют хеш C:\Windows\System32\cmd.exe
даст разные результаты в зависимости от того, являются ли они 32-разрядными или 64-разрядными.
Вы можете убедиться в этом сами, создав свою примерную программу, как 32-разрядную, так и 64-разрядную, и заметив, что они дают разные ответы.