2

I need to compare hash values of two strings. I use string "template" for testing. But I got different hash values for this string so it is always not the same. I use CryptoApi and MD4

int _tmain(int argc, _TCHAR* argv[])
{
    std::hash_map<int,int> table;
    HCRYPTPROV hProv1,hProv2;
    BYTE *pbBuffer1=(BYTE*)"template";//data to hash
    DWORD dwBufferLen1=strlen((char*)pbBuffer1)+1;
    HCRYPTHASH hHash1,hHash2;
    //first hash
    CryptAcquireContext(&hProv1,NULL,NULL,PROV_RSA_AES,0);
    CryptCreateHash(hProv1,CALG_MD4,0,0,&hHash1);
    CryptHashData(hHash1,pbBuffer1,dwBufferLen1,0);
    /*---------*/
    BYTE *pbBuffer2=(BYTE*)"template";//data to hash
    DWORD dwBufferLen2=strlen((char*)pbBuffer2)+1;
    //second hash
    CryptAcquireContext(&hProv2,NULL,NULL,PROV_RSA_AES,0);  
    CryptCreateHash(hProv2,CALG_MD4,0,0,&hHash2);
    CryptHashData(hHash2,pbBuffer2,dwBufferLen2,0);
    if (hHash1==hHash2)
        printf("The Same\n");
    else printf("Not same\n");
    /*---------*/
    std::cout<<hHash1<<std::endl;
    std::cout<<hHash2<<std::endl;
    if (hProv1)
        CryptReleaseContext(hProv1,0);
    if (hProv2)
        CryptReleaseContext(hProv2,0);
    system("pause");
    return 0;
} 

For example hash value in hHash1

691136

Hash value in hHash2

691216
2
  • 1
    C tag replaced with c++. There is no :: in C. Commented Jan 6, 2012 at 13:28
  • Did you step through it with a debugger? Two strings always produce the same hash, so something must be different about them. Commented Jan 6, 2012 at 13:34

3 Answers 3

5

HCRPTHASH is a ULONG_PTR typedef, as per here. That means it's a pointer:

The HCRYPTHASH data type is used to represent handles to hash objects. These handles indicate to the CSP module which hash is being used in a particular operation. The CSP module does not enable direct manipulation of the hash values. Instead, the user manipulates the hash values through the hash handle.

typedef ULONG_PTR HCRYPTHASH;

Comparing pointers with == is about as productive as nailing jelly (or jello to US citizens) to a tree, or trying to train a cat :-)

The values you're seeing as your "hashes" are actually the pointers, 80 bytes apart (since they are pointers to two different memory blocks).

In order to get the actual hash from the handle, you need something like the following, which prints the hex digits:

CHAR hexDigits[] = "0123456789abcdef";
BYTE md4Hash[MD4LEN];
DWORD cbHash = MD4LEN;
if (CryptGetHashParam (hHash1, HP_HASHVAL, md4Hash, &cbHash, 0)) {
    printf("MD4 hash is: ");
    for (DWORD i = 0; i < cbHash; i++) {
        printf ("%c%c", hexDigits[md4Hash[i] >> 4], hexDigits[md4Hash[i] & 0xf]);
    }
    printf("\n");
} else {
    DWORD dwStatus = GetLastError();
    printf ("CryptGetHashParam failed with code %d\n", dwStatus); 
}

For comparing the two hash values, you can do:

BYTE md4Hash1[MD4LEN], md4Hash2[MD4LEN];
DWORD cbHash1 = MD4LEN, cbHash2 = MD4LEN;

CryptGetHashParam (hHash1, HP_HASHVAL, md4Hash1, &cbHash1, 0);
CryptGetHashParam (hHash2, HP_HASHVAL, md4Hash2, &cbHash2, 0);

if ((cbHash1 == cbHash2) &&
    (memcmp (md4Hash1, md4Hash2, cbHash1) == 0))
{
    // they are equal.
}
Sign up to request clarification or add additional context in comments.

2 Comments

I've done like this. I call CryptGetHashParam and put bytes into array for hHash1 and hHash2 and then compare it with memcmp and it seems working correctly.
@Артём, that's basically where I ended up after a search - see the updated answer.
2

As the other answers have noted, hHash1 and hHash2 are opaque handles — comparing them is pointless, as that's akin to comparing the addresses of two different objects that have the same value.

Use CryptGetHashParam to get the hash values and compare those instead:

The CryptGetHashParam function retrieves data that governs the operations of a hash object. The actual hash value can be retrieved by using this function.

Comments

2

hHash1 and hHash2 are not the hash codes, but handles.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa379908(v=vs.85).aspx

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.