Reputation: 23
I use this function to generate a hash of a string
std::string MD5(string input)
{
BYTE BytesHash[33];//!
DWORD dwHashLen;
string final;
HCRYPTPROV CryptProv;
HCRYPTHASH CryptHash;
if (CryptAcquireContext(&CryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) {
if (CryptCreateHash(CryptProv, CALG_MD5, 0, 0, &CryptHash)) {
if (CryptHashData(CryptHash, (BYTE*)input.c_str(), input.length(), 0)) {
if (CryptGetHashParam(CryptHash, HP_HASHVAL, BytesHash, &dwHashLen, 0)) {
final.clear();
string hexcharset = "0123456789ABCDEF";
for (int j = 0; j < 16; j++) {
final += hexcharset.substr(((BytesHash[j] >> 4) & 0xF), 1);
final += hexcharset.substr(((BytesHash[j]) & 0x0F), 1);
}
}
}
}
} CryptDestroyHash(CryptHash);
CryptReleaseContext(CryptProv, 0);
return final;
}
But I have a problem. Some users of the compiled binary can not generate md5. However, I insert between some lines:
cout << "randomstring:gfdgfdgfdgfdg" << endl;
And now everything is working for those users, but does not work for some others. What the hell?
Upvotes: 0
Views: 433
Reputation: 13868
The 4th parameter of CryptGetHashParam, pdwDataLen
, has two functions. Upon entry, it specifies the length of the available buffer. Upon exit, it contains the length of the really used data. This is fairly common concept in Windows API.
Because you do not initialize dwHashLen
with any value, whatever is currently on the stack is passed to the function. If it's less than the size of the hash value, it does not work and the function returns error. If it happens to be bigger, it works. Doing some other unrelated operation can change the stack in random ways, therefore make it work sometimes.
The solution is therefore to initialize the size like this:
DWORD dwHashLen = sizeof(BytesHash);
You might want to check GetLastError()
next time something like this happens, it would tell you a hint about what went wrong (ERROR_MORE_DATA
).
Upvotes: 5