Win32 MD5 哈希器的奇怪行为
Strange behavior of Win32 MD5 hasher
我用这个函数生成一个字符串的散列
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;
}
但是我有一个问题。编译后的二进制文件的某些用户无法生成 md5。但是,我在几行之间插入:
cout << "randomstring:gfdgfdgfdgfdg" << endl;
现在一切都对这些用户有效,但对其他一些用户无效。什么鬼?
CryptGetHashParam的第4个参数,pdwDataLen
,有两个作用。输入时,它指定可用缓冲区的长度。退出时,它包含真正使用的数据的长度。这是 Windows API.
中相当常见的概念
因为您没有用任何值初始化 dwHashLen
,所以当前在堆栈上的任何内容都会传递给函数。如果它小于散列值的大小,则它不起作用并且函数 returns 错误。如果它恰好更大,它就可以工作。做一些其他不相关的操作可以随机改变堆栈,因此有时可以让它工作。
因此,解决方案是像这样初始化大小:
DWORD dwHashLen = sizeof(BytesHash);
下次发生这种情况时,您可能需要检查 GetLastError()
,它会提示您哪里出了问题 (ERROR_MORE_DATA
)。
我用这个函数生成一个字符串的散列
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;
}
但是我有一个问题。编译后的二进制文件的某些用户无法生成 md5。但是,我在几行之间插入:
cout << "randomstring:gfdgfdgfdgfdg" << endl;
现在一切都对这些用户有效,但对其他一些用户无效。什么鬼?
CryptGetHashParam的第4个参数,pdwDataLen
,有两个作用。输入时,它指定可用缓冲区的长度。退出时,它包含真正使用的数据的长度。这是 Windows API.
因为您没有用任何值初始化 dwHashLen
,所以当前在堆栈上的任何内容都会传递给函数。如果它小于散列值的大小,则它不起作用并且函数 returns 错误。如果它恰好更大,它就可以工作。做一些其他不相关的操作可以随机改变堆栈,因此有时可以让它工作。
因此,解决方案是像这样初始化大小:
DWORD dwHashLen = sizeof(BytesHash);
下次发生这种情况时,您可能需要检查 GetLastError()
,它会提示您哪里出了问题 (ERROR_MORE_DATA
)。