【问题标题】:Strange behavior of Win32 MD5 hasherWin32 MD5 哈希的奇怪行为
【发布时间】:2017-02-07 13:24:34
【问题描述】:

我使用这个函数来生成一个字符串的哈希

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;

现在一切都对这些用户有效,但对其他一些用户无效。什么鬼?

【问题讨论】:

  • 如果添加打印语句“修复”了代码,这表明您的代码中有未定义的行为。
  • 忽略错误很少是一个好计划。

标签: c++ winapi md5


【解决方案1】:

CryptGetHashParam的第4个参数pdwDataLen有两个作用。在进入时,它指定可用缓冲区的长度。退出时,它包含实际使用数据的长度。这是 Windows API 中相当普遍的概念。

因为你没有用任何值初始化dwHashLen,所以当前在堆栈上的任何东西都会被传递给函数。如果它小于哈希值的大小,则它不起作用并且函数返回错误。如果它碰巧更大,它会起作用。做一些其他不相关的操作可能会以随机方式改变堆栈,因此有时会使其工作。

因此,解决方案是像这样初始化大小:

DWORD dwHashLen = sizeof(BytesHash);

下次发生这种情况时,您可能需要检查GetLastError(),它会告诉您出现问题的提示 (ERROR_MORE_DATA)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    相关资源
    最近更新 更多