通过c ++ WinAPI计算MD5哈希值

RRR*_*RRR 6 c++ windows hash winapi md5

我的C++应用程序需要计算MD5哈希值.目前,它由OpenSSL完成,我想使用WinAPI - 以避免依赖外部库.

我写了这段代码:

HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTHASH hHexHash = NULL;
HASH HA1;
HASHHEX HA1HEX;
DWORD data = HASHLEN;

// Get a handle to a cryptography provider context.
if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0))
{
    goto err;
}

// Acquire a hash object handle.
if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
{
    goto err;
}

CryptHashData(hHash, (const BYTE *)str, strlen(str), 0);
Run Code Online (Sandbox Code Playgroud)

现在,奇怪的是有时它运行良好,但在其他时候CryptAcquireContext返回NTE_BAD_KEYSET错误,根据MSDN:

密钥容器无法打开.此错误的常见原因是密钥容器不存在.要创建密钥容器,请使用CRYPT_NEWKEYSET标志调用CryptAcquireContext.此错误代码还可以指示拒绝访问现有密钥容器.密钥集创建者可以使用CryptSetProvParam授予对容器的访问权限.

大段引用

现在我的问题是:

  1. 如果我调用CryptSetProvParam,它到底是做什么的?简单的应用程序更改操作系统设置是否正常?
  2. 在C++窗口中计算MD5有什么不那么困难的方法吗?

如果有人给我很好的建议,我会很感激.
谢谢.

Pat*_*k M 8

所以,我在http://msdn.microsoft.com/en-us/library/aa382380%28VS.85%29.aspx找到了一个可以满足您需求的示例.

看看他们的代码,我看到的区别是这一行:

他们的:CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)

你的:CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,0)

所以,阅读那面旗帜,我发现这个信息:

CRYPT_VERIFYCONTEXT:此选项适用于使用临时密钥的应用程序或不需要访问持久私钥的应用程序,例如仅执行散列,加密和数字签名验证的应用程序.只有创建签名或解密消息的应用程序才需要访问私钥.在大多数情况下,应该设置此标志.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa379886%28v=vs.85%29.aspx

因此,您似乎正在尝试访问不需要的信息,并且请求被拒绝.因此,最好的选择是通过包含该标志告诉Windows您不需要该信息.


Nas*_*zta 6

我喜欢使用PROV_RSA_AESand CRYPT_VERIFYCONTEXT,因为大多数哈希值都受支持。

这是一个工作示例:

#include <Wincrypt.h>

enum HashType
{
  HashSha1, HashMd5, HashSha256
};

std::string GetHashText( const void * data, const size_t data_size, HashType hashType )
{
  HCRYPTPROV hProv = NULL;

  if ( ! CryptAcquireContext( &hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT ) ) {
    return "";
  }

  BOOL hash_ok = FALSE;
  HCRYPTPROV hHash = NULL;
  switch ( hashType ) {
  case HashSha1 : hash_ok = CryptCreateHash( hProv, CALG_SHA1, 0, 0, &hHash ); break;
  case HashMd5 : hash_ok = CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash ); break;
  case HashSha256 : hash_ok = CryptCreateHash( hProv, CALG_SHA_256, 0, 0, &hHash ); break;
  }

  if ( ! hash_ok ) {
    CryptReleaseContext(hProv, 0);
    return "";
  }

  if ( ! CryptHashData( hHash, static_cast<const BYTE *>(data), data_size, 0 ) ) {
    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);
    return "";
  }

  DWORD cbHashSize = 0, dwCount = sizeof(DWORD);
  if( ! CryptGetHashParam( hHash, HP_HASHSIZE, (BYTE *)&cbHashSize, &dwCount, 0 ) ) {
    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);
    return "";
  }

  std::vector<BYTE> buffer( cbHashSize );
  if ( ! CryptGetHashParam( hHash, HP_HASHVAL, reinterpret_cast<BYTE*>( &buffer[0] ), &cbHashSize, 0) ) {
    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);
    return "";
  }

  std::ostringstream oss;

  for ( std::vector<BYTE>::const_iterator iter = buffer.begin(); iter != buffer.end(); ++iter ) {
    oss.fill('0');
    oss.width(2);
    oss << std::hex << static_cast<const int>(*iter);
  }

  CryptDestroyHash(hHash);
  CryptReleaseContext(hProv, 0);
  return oss.str();
}
Run Code Online (Sandbox Code Playgroud)