【问题标题】:MSDN HMAC-SHA1 example not workingMSDN HMAC-SHA1 示例不起作用
【发布时间】:2011-11-24 18:09:02
【问题描述】:

使用此处的 CryptoAPI 创建 HMAC 步骤:http://msdn.microsoft.com/en-us/library/Aa379863

  • 计算 HMAC

    1. 获取指向 Microsoft 加密服务提供程序的指针 (CSP) 通过调用 CryptAcquireContext。
    2. 通过调用创建 HMAChash 对象的句柄 加密创建哈希。在 Algid 参数中传递 CALG_HMAC。通过 hKey 参数中对称密钥的句柄。这个对称密钥 是用于计算 HMAC 的密钥。
    3. 通过调用指定要使用的散列类型 将 dwParam 参数设置为值的 CryptSetHashParam HP_HMAC_INFO。 pbData 参数必须指向一个已初始化的 HMAC_INFO 结构。
    4. 调用 CryptHashData 开始计算数据的 HMAC。这 第一次调用 CryptHashData 导致键值使用组合 带有内部字符串和数据的 XOR 运算符。的结果 XOR 操作被散列,然后是 HMAC 的目标数据 (由调用中传递的 pbData 参数指向 CryptHashData) 被散列。如有必要,后续调用 然后可以使 CryptHashData 完成目标的散列 数据。
    5. 调用 CryptGetHashParam 并将 dwParam 参数设置为 HP_HASHVAL。此调用导致内部哈希完成,并且 要使用 XOR 与键组合的外部字符串。结果 异或运算是hash,然后是inner hash的结果 (在上一步中完成)被散列。然后外部哈希是 完成并在 pbData 参数中返回,长度在 dwDataLen 参数。

我不能,因为我的生活让这个工作。我按顺序完成了所有步骤,但仍然无法运行我的程序。运行时出错:

Error in CryptImportKey 0x8009007
Error in CryptCreatHash 0x8009003
Error in CryptSetHashParam 0x00000057
Error in CryptHashData 0x00000057
Error in CryptGetHashParam 0x00000057

谁能帮忙?

#include <iostream>
#include <windows.h>
#include <wincrypt.h>
using namespace std;

#define CALG_HMAC CALG_SHA1

int main()
{
//--------------------------------------------------------------------
// Declare variables.
HCRYPTPROV  hProv       = NULL;
HCRYPTHASH  hHash       = NULL;
HCRYPTKEY   hKey        = NULL;
BYTE DesKeyBlob[] = { 0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64 };
HCRYPTHASH  hHmacHash   = NULL;
PBYTE       pbHash      = NULL;
DWORD       dwDataLen   = 20;
BYTE        Data[]     = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
HMAC_INFO   HmacInfo;

//--------------------------------------------------------------------
// Zero the HMAC_INFO structure
ZeroMemory(&HmacInfo, sizeof(HmacInfo));
HmacInfo.HashAlgid = CALG_HMAC;
HmacInfo.pbInnerString = (BYTE*)0x36;
HmacInfo.cbInnerString = 0;
HmacInfo.pbOuterString = (BYTE*)0x5C;
HmacInfo.cbOuterString = 0;

// Step 1
if (!CryptAcquireContext(
    &hProv,                   // handle of the CSP
    NULL,                     // key container name
    NULL,                     // CSP name
    PROV_RSA_FULL,            // provider type
    CRYPT_VERIFYCONTEXT))     // no key access is requested
{
   printf(" Error in AcquireContext 0x%08x \n",
          GetLastError());
}

//--------------------------------------------------------------------
//Step 2
//in step two, we need the hash key used to be imported?
//imports the key used...  as hKey1
if(!CryptImportKey(
       hProv,
       DesKeyBlob,
       sizeof(DesKeyBlob),
       0,
       CRYPT_EXPORTABLE,
       &hKey ))
{
       printf("Error in !CryptImportKey 0x%08x \n",
          GetLastError());
}

if (!CryptCreateHash(
    hProv,      // handle of the CSP
    CALG_HMAC,  // hash algorithm to use
    hKey,       // hash key this shoudl point to a key used to compute the HMAC?
    0,          // reserved
    &hHmacHash  // address of hash object handle
)){
   printf("Error in CryptCreateHash 0x%08x \n",
          GetLastError());
}
// Step 3

if (!CryptSetHashParam(
    hHmacHash,//hProv,//hHash,//hHmacHash,                // handle of the HMAC hash object
    HP_HMAC_INFO,             // setting an HMAC_INFO object
    (BYTE*)&HmacInfo,         // the HMAC_INFO object
    0))                       // reserved
{
   printf("Error in CryptSetHashParam 0x%08x \n", 
          GetLastError());
}

//Step 4

if (!CryptHashData(
    hHmacHash,                // handle of the HMAC hash object
    Data,                    // message to hash
    sizeof(Data),            // number of bytes of data to add
    0))                       // flags
{
   printf("Error in CryptHashData 0x%08x \n", 
          GetLastError());
}
//Step 5

if (!CryptGetHashParam(
    hHmacHash,                 // handle of the HMAC hash object
    HP_HASHVAL,                // query on the hash value
    pbHash,                    // pointer to the HMAC hash value
    &dwDataLen,                // length, in bytes, of the hash
    0))
{
   printf("Error in CryptGetHashParam 0x%08x \n", GetLastError());
}

// Print the hash to the console.

printf("The hash is:  ");
for(DWORD i = 0 ; i < dwDataLen ; i++) 
{
   printf("%2.2x ",pbHash[i]);
}
printf("\n");

int a;

std::cin >> a;

    return 0;
}

【问题讨论】:

  • 编译时错误是什么?
  • 对不起,我的意思是运行,而不是编译。我运行时遇到的错误是: CryptImportKey 0x8009007 中的错误 CryptCreatHash 0x8009003 中的错误 CryptSetHashParam 0x00000057 中的错误 CryptHashData 0x00000057 中的错误 CryptGetHashParam 0x00000057
  • 这绝不是来自 MSDN 的示例应用程序。它已多次更改:请参阅msdn.microsoft.com/en-us/library/aa382379(v=VS.85).aspx
  • 这不会返回真实值作为证据:buchananweb.co.uk/security01.aspx :-(

标签: c++ cryptography sha1 hmac hmacsha1


【解决方案1】:

您可能 (?1) 需要指定要使用的哈希算法。

#define CALG_HMAC CALG_SHA1 // or CALG_MD5 etc

编辑

  • 为什么要初始化dwDataLen = 20(而不是0)?

  • 为什么要从 SHA1 更改哈希算法

  • 为什么不再退出 ErrorExit(仅此一项就可以防止崩溃,而不是正确的错误消息)

  • 您使用CryptImportKey 而不是CryptDeriveKey——MSDN 上的示例中甚至不存在这样的东西。 CryptImportKey 调用失败并出现 0x80090005 (NTE_BAD_DATA) 并非巧合。您的 CSP 不支持该密钥!

  • 为此,您需要密钥访问权限,因此您至少需要将 CRYPT_VERIFY_CONTEXT 更改为其他内容(不知道是什么);我尝试使用

.

if (!CryptAcquireContext(
            &hProv,                   
            NULL,                     
            MS_STRONG_PROV,           // allow 2048 bit keys, in case you need it
            PROV_RSA_FULL,            
            CRYPT_MACHINE_KEYSET))    // just a guess

现在我的程序生成 0x80090016: Keyset does not exist。这可能只是因为我没有那个键集,或者因为我在 Wine 下的 Linux 上运行。

希望这会有所帮助。


1 在 Linux 上编译使用:

i586-mingw32msvc-g++ -m32 -O2 -g test.cpp -o test.exe

它在运行时确实崩溃了(没有参数),但这可能是葡萄酒不兼容(或者我没有阅读源代码以查看它的作用:))

【讨论】:

  • 已添加:#define CALG_HMAC CALG_SHA1 现在我得到错误:CryptImportKey 0x80090007 和 CryptSetHashParam 0x8009000A。你用过我贴的代码吗?
  • @user954753: 还有什么 :) 但是,您稍后发布了运行时错误 - 我收到了 Error in !CryptImportKey 0x80090005 Error in CryptSetHashParam 0x80090020 - 看起来很相似。恐怕会发生其他事情(但我回答了这个问题,因为你提到它不会编译,而且对我来说,没有这个定义就无法编译)
  • 我深入挖掘并提出了一些可能对您有所帮助的线索。尤其是您尝试使用 CryptImportKey 的事实可能比您想象的要多(就获取提供者上下文而言)
  • 为什么初始化dwDataLen = 20(而不是0)? -> 我希望输出长度为 20 个字节。为什么要从 SHA1 更改哈希算法-> 我只是尝试遵循 5 个步骤。我做了所有步骤告诉我要做的事情。
  • @user954753:答案是:问题是 与执行 HMAC 的步骤有关。相反,它是使用 CryptImportKey 的步骤。阅读不同的教程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 2010-10-19
  • 1970-01-01
相关资源
最近更新 更多