MSDN HMAC-SHA1 示例不起作用

发布于 2024-12-06 13:23:37 字数 4446 浏览 3 评论 0原文

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

  • 计算 HMAC

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

Creating an HMAC steps by using CryptoAPI found here: http://msdn.microsoft.com/en-us/library/Aa379863

  • To compute an HMAC

    1. Get a pointer to the Microsoft Cryptographic Service Provider
      (CSP) by calling CryptAcquireContext.
    2. Create a handle to an HMAChash object by calling
      CryptCreateHash. Pass CALG_HMAC in the Algid parameter. Pass the
      handle of a symmetric key in the hKey parameter. This symmetric key
      is the key used to compute the HMAC.
    3. Specify the type of hash to be used by calling
      CryptSetHashParam with the dwParam parameter set to the value
      HP_HMAC_INFO. The pbData parameter must point to an initialized
      HMAC_INFO structure.
    4. Call CryptHashData to begin computing the HMAC of the data. The
      first call to CryptHashData causes the key value to be combined using
      the XOR operator with the inner string and the data. The result of
      the XOR operation is hashed, and then the target data for the HMAC
      (pointed to by the pbData parameter passed in the call to
      CryptHashData) is hashed. If necessary, subsequent calls to
      CryptHashData may then be made to finish the hashing of the target
      data.
    5. Call CryptGetHashParam with the dwParam parameter set to
      HP_HASHVAL. This call causes the inner hash to be finished and the
      outer string to be combined using XOR with the key. The result of the
      XOR operation is hashed, and then the result of the inner hash
      (completed in the previous step) is hashed. The outer hash is then
      finished and returned in the pbData parameter and the length in the
      dwDataLen parameter.

I can not, for the life of me get this working. I have all the steps in order, and still can not even run my program. Errors while running:

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

Can anyone help?

#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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

西瑶 2024-12-13 13:23:37

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

#define CALG_HMAC CALG_SHA1 // or CALG_MD5 etc

编辑

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

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

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

  • 你使用 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

运行时(不带参数)它确实崩溃了,但这可能是 wine 不兼容(或者我还没有阅读 来源看看它做了什么:))

You might (?1) need to specify what hash algorithm you want to use.

#define CALG_HMAC CALG_SHA1 // or CALG_MD5 etc

Edit

  • Why do you initialize dwDataLen = 20 (instead of 0)?

  • Why did you change the hash algorithm from SHA1

  • Why do you not exit on ErrorExit anymore (that alone will prevent the crash instead of proper error message)

  • You use CryptImportKey instead of CryptDeriveKey -- no such thing even exists in the sample on MSDN. It can't be a coincidence that CryptImportKey is the call failing with 0x80090005 (NTE_BAD_DATA). The key is not supported by your CSP!

  • For that to work, you need key access so you'd at least need to change CRYPT_VERIFY_CONTEXT into something else (don't know what); I tried using

.

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

Now my program results in 0x80090016: Keyset does not exist. This might simply be because I don't have that keyset, or because I'm running on Linux under Wine.

Hope this helps.


1 Compiled on Linux using:

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

It did crash when run (without parameters) but that might be wine incompatibility (or the fact that I haven't read the source to see what it does :))

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文