md5 для exe не дает ожидаемого дайджеста

Я новичок здесь, я надеюсь, что я делаю это правильно.

Я сделал приложение на C++, которое вычисляет дайджест хеша MD5 для файлов после реализации Microsoft по этой ссылке http://msdn.microsoft.com/en-us/library/windows/desktop/aa382380%28v=vs.85%29.aspx Случай - это то, что дайджест хеша md5 является правильным для любого файла типа при сравнении его с любым готовым инструментом, который вычисляет дайджест md5. кроме случаев, когда файл в руках является исполняемым файлом, например cmd.exe. Дайджест хеша отличается и зависит от расположения 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"

1 ответ

Решение

Ваш код правильный! Вы столкнулись с особенностью 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-разрядную, и заметив, что они дают разные ответы.

Другие вопросы по тегам