2014-03-03 3 views
2

Я пытаюсь выполнить прямой SHA256 HMAC с использованием wincrypt/cryptoapi/Cryptography API: Next Generation (CNG), и я действительно борется. Моя цель - Windows 8.Возможно ли сделать HMAC с wincrypt?

Я не могу найти правильные методы или найти какие-либо примеры в любом месте. Я ищу сделать следующее в 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 с использованием криптоапи?

+1

Существует [пример использования SHA256] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa376217 (V = vs.85) .aspx) все, что вам нужно будет сделать, это заменить алгоритм из vanilla SHA256 на использование ['BCRYPT_SP800108_CTR_HMAC_ALGORITHM'] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa375534 (v = vs.85) .aspx). Вы заметите, что в примере они создают алгоритм и хэш, вам нужно изменить алгоритм *. Также вам не нужен ASCII вашего XML, некоторые символы могут быть заменены. – Mgetz

+0

Да, я согласен с использованием ASCII для XML, это будет плохая идея. Некоторые символы будут неправильно закодированы. К счастью, это был всего лишь пример содержимого, поскольку я знал, что преобразование в c будет проще, чем UFT16. –

ответ

4

Благодарим за информацию Mgetz. Я никогда не знал о наборе методов BCrypt. Это намного проще для HMAC, чем CryptHashData для wincrypt/cryptoapi. Из примера использования hashing using 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); 
    } 
};