Is it possible to do a HMAC with wincrypt?

后端 未结 1 1384
挽巷
挽巷 2021-01-20 04:05

I\'ve been trying to perform a straight forward SHA256 HMAC using wincrypt/cryptoapi/Cryptography API: Next Generation (CNG) and i\'m really struggling. My target is Windows

相关标签:
1条回答
  • 2021-01-20 04:41

    Thank you for the information Mgetz. I never knew about the BCrypt set of methods. It is a lot easier for HMAC than CryptHashData of the wincrypt/cryptoapi. From the example of using hashing using SHA256 I was able to create the HMAC code. You only need to add BCRYPT_ALG_HANDLE_HMAC_FLAG to the last parameter of BCryptOpenAlgorithmProvider and include the key in the call to BCryptCreateHash.

    This is the completed code:

    #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);
        }
    };
    
    0 讨论(0)
提交回复
热议问题