Можно ли сделать HMAC с wincrypt?

Я пытался выполнить прямолинейный SHA256 HMAC с использованием wincrypt / cryptoapi / Cryptography API: Next Generation (CNG), и я действительно изо всех сил. Моя цель — 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.

Кому-нибудь удалось выполнить прямой HMAC с использованием cryptoapi?

2

Решение

Спасибо за информацию Mgetz. Я никогда не знал о наборе методов BCrypt. Для HMAC это намного проще, чем CryptHashData из wincrypt / cryptoapi. Из примера использования хеширование с использованием 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 BCryptOpenAlgorithmProvider\n", 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 BCryptGetProperty\n", status);
goto Cleanup;
}

//allocate the hash object on the heap
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
if (NULL == pbHashObject)
{
wprintf(L"**** memory allocation failed\n");
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 BCryptGetProperty\n", status);
goto Cleanup;
}

//allocate the hash buffer on the heap
pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
if (NULL == pbHash)
{
wprintf(L"**** memory allocation failed\n");
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 BCryptCreateHash\n", 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 BCryptHashData\n", status);
goto Cleanup;
}

//close the hash
if (!NT_SUCCESS(status = BCryptFinishHash(
hHash,
pbHash,
cbHash,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", 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);
}
};
5

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector