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

  • 计算HMAC
  • 获取指向Microsoft加密服务提供者的指针
    (CSP),方法是调用CryptAcquireContext。
  • 通过调用创建HMAChash对象的句柄
    CryptCreateHash。在Algid参数中传递CALG_HMAC。通过
    hKey参数中对称 key 的句柄。这个对称 key
    是用于计算HMAC的 key 。
  • 指定通过调用使用的哈希类型
    将dwParam参数设置为值的CryptSetHashParam
    HP_HMAC_INFO。 pbData参数必须指向已初始化
    HMAC_INFO结构。
  • 调用CryptHashData开始计算数据的HMAC。这
    首次调用CryptHashData会导致键值使用
    带有内部字符串和数据的XOR运算符。的结果
    对XOR操作进行哈希处理,然后将HMAC的目标数据
    (由传递给的调用中的pbData参数指向
    CryptHashData)进行哈希处理。如有必要,随后致电
    然后可以使CryptHashData完成目标的散列
    数据。
  • 将dwParam参数设置为来调用CryptGetHashParam
    HP_HASHVAL。此调用导致内部哈希完成,并且
    要使用XOR与键组合的外部字符串。结果
    对XOR操作进行哈希处理,然后进行内部哈希处理的结果
    (在上一步中完成)进行哈希处理。然后是外部哈希
    完成并在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;
    }
    

    最佳答案

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

    #define CALG_HMAC CALG_SHA1 // or CALG_MD5 etc
    

    编辑
  • 为什么要初始化dwDataLen = 20(而不是0)?
  • 为什么从SHA1更改哈希算法
  • 为什么您不再退出ErrorExit(仅此一项可以防止崩溃,而不是正确的错误消息)
  • 您可以使用CryptImportKey而不是CryptDeriveKey-MSDN上的示例中甚至不存在此类内容。 CryptImportKey是因0x80090005(NTE_BAD_DATA)而失败的调用,这绝非偶然。您的CSP不支持该 key !
  • 为此,您需要 key 访问权,因此至少需要将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 。这可能仅仅是因为我没有该键集,或者是因为我在Linux上的Wine下运行。

    希望这可以帮助。

    1在Linux上使用以下命令进行编译:
    i586-mingw32msvc-g++ -m32 -O2 -g test.cpp -o test.exe
    

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

    10-07 20:37