是否有可能使用wincrypt进行HMAC

Is it possible to do a HMAC with wincrypt?

本文关键字:进行 HMAC wincrypt 有可能 是否      更新时间:2023-10-16

我一直在尝试使用wincrypt/cryptoapi/Cryptography API:下一代(CNG)执行直接的SHA256 HMAC,我真的很挣扎。我的目标是Windows 8。

我找不到正确的方法或在任何地方找到任何示例。我希望在 C/C++ 中执行以下操作,这在下面的 C# 中演示

        HMAC hashMaker = new HMACSHA256(Encoding.ASCII.GetBytes("SecretKey"));
        byte[] hash = hashMaker.ComputeHash(Encoding.ASCII.GetBytes("<SomeXmlData />"));
        string hashStr = BitConverter.ToString(hash);

它返回哈希:B2-42-48-67-5A-B8-03-87-5B-00-D7-8C-65-5A-AE-B7-92-E3-F9-27-40-C1-01-A5-37-74-E1-65-51-9F-F6-6A。

有没有人成功地使用cryptoapi执行直接的HMAC?

感谢您提供 Mgetz 的信息。我从来不知道BCrypt的方法集。对于HMAC来说,它比wincrypt/cryptoapi的CryptHashData容易得多。从使用 SHA256 使用哈希的示例中,我能够创建 HMAC 代码。您只需要将BCRYPT_ALG_HANDLE_HMAC_FLAG添加到 BCryptOpenAlgorithmProvider 的最后一个参数中,并在对 BCryptCreateHash 的调用中包含该键。

这是完成的代码:

#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>
#pragma comment(lib, "bcrypt.lib") 
#define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
void __cdecl wmain(
    int                      argc,
    __in_ecount(argc) LPWSTR *wargv)
{
    BCRYPT_ALG_HANDLE       hAlg = NULL;
    BCRYPT_HASH_HANDLE      hHash = NULL;
    NTSTATUS                status = STATUS_UNSUCCESSFUL;
    DWORD                   cbData = 0,
        cbHash = 0,
        cbHashObject = 0;
    PBYTE                   pbHashObject = NULL;
    PBYTE                   pbHash = NULL;
    CONST BYTE key[] = { "SecretKey" };
    CONST BYTE message[] = { "<SomeXmlData />" };
    //open an algorithm handle
    if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
        &hAlg,
        BCRYPT_SHA256_ALGORITHM,
        NULL,
        BCRYPT_ALG_HANDLE_HMAC_FLAG)))
    {
        wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvidern", status);
        goto Cleanup;
    }
    //calculate the size of the buffer to hold the hash object
    if (!NT_SUCCESS(status = BCryptGetProperty(
        hAlg,
        BCRYPT_OBJECT_LENGTH,
        (PBYTE)&cbHashObject,
        sizeof(DWORD),
        &cbData,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by BCryptGetPropertyn", status);
        goto Cleanup;
    }
    //allocate the hash object on the heap
    pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
    if (NULL == pbHashObject)
    {
        wprintf(L"**** memory allocation failedn");
        goto Cleanup;
    }
    //calculate the length of the hash
    if (!NT_SUCCESS(status = BCryptGetProperty(
        hAlg,
        BCRYPT_HASH_LENGTH,
        (PBYTE)&cbHash,
        sizeof(DWORD),
        &cbData,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by BCryptGetPropertyn", status);
        goto Cleanup;
    }
    //allocate the hash buffer on the heap
    pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
    if (NULL == pbHash)
    {
        wprintf(L"**** memory allocation failedn");
        goto Cleanup;
    }
    //create a hash
    if (!NT_SUCCESS(status = BCryptCreateHash(
        hAlg,
        &hHash,
        pbHashObject,
        cbHashObject,
        (PBYTE)key,
        sizeof(key)-1,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by BCryptCreateHashn", status);
        goto Cleanup;
    }
    //hash some data
    if (!NT_SUCCESS(status = BCryptHashData(
        hHash,
        (PBYTE)message,
        sizeof(message)-1,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by BCryptHashDatan", status);
        goto Cleanup;
    }
    //close the hash
    if (!NT_SUCCESS(status = BCryptFinishHash(
        hHash,
        pbHash,
        cbHash,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by BCryptFinishHashn", status);
        goto Cleanup;
    }
    printf("The hash is:  ");
    for (DWORD i = 0; i < cbHash; i++)
    {
        printf("%2.2X-", pbHash[i]);
    }

Cleanup:
    if (hAlg)
    {
        BCryptCloseAlgorithmProvider(hAlg, 0);
    }
    if (hHash)
    {
        BCryptDestroyHash(hHash);
    }
    if (pbHashObject)
    {
        HeapFree(GetProcessHeap(), 0, pbHashObject);
    }
    if (pbHash)
    {
        HeapFree(GetProcessHeap(), 0, pbHash);
    }
};