hashResult变量未存储正确的值

时间:2016-12-04 20:08:17

标签: c windows hash

我有一个从文件生成哈希键的程序。 例如,程序的结果是"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;
}

1 个答案:

答案 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;
}