Charles
Charles

Reputation: 93

C++ HMAC-SHA256 implementation with openssl

I am trying to use HMAC-SHA256 using openssl in C++.

I am double-checking my output using a python code which seems to prove that something is wrong... Surprisingly I am able to hash using HMAC-SHA384 and HMAC-SHA512 (still double checking with my python code)

Can someone kindly point me to what I am doing wrong ?

My code :

static std::vector<unsigned char> hmac_sha256(const std::vector<unsigned char>& data, const std::vector<unsigned char>& key)
{
    unsigned int len = EVP_MAX_MD_SIZE;
    std::vector<unsigned char> digest(len);

    HMAC_CTX ctx;
    HMAC_CTX_init(&ctx);

    HMAC_Init_ex(&ctx, key.data(), key.size(), EVP_sha256(), NULL);
    HMAC_Update(&ctx, data.data(), data.size());
    HMAC_Final(&ctx, digest.data(), &len);

    HMAC_CTX_cleanup(&ctx);

    return digest;
}

My implementation of HMAC-SHA384 and HMAC-SHA512 only differs from the above by respectively changing EVP_sha256() by EVP_sha384() and EVP_sha512()...

Example : message = "azertyAZERTY", key = "vzxgPuegSjRksLnCAu/LElxWRonjVkCoArWzZqliiSEtmlbaCfZaGkrSweWJKQkgQsyrBUpSusAcPcGDfFhWOx==" (that one should be b64 decoded before being used in my function).

The following python implementation

import json, hmac, hashlib, time, requests, base64 from requests.auth import AuthBase

message = "azertyAZERTY"
hmac_key = base64.b64decode("vzxgPuegSjRksLnCAu/LElxWRonjVkCoArWzZqliiSEtmlbaCfZaGkrSweWJKQkgQsyrBUpSusAcPcGDfFhWOx==")

signature256 = hmac.new(hmac_key, message, hashlib.sha256)
print('signature 256 : ' + 
signature256.digest().encode('base64').rstrip('\n'))
signature384 = hmac.new(hmac_key, message, hashlib.sha384)
print('signature 384 : ' + 
signature384.digest().encode('base64').rstrip('\n'))
signature512 = hmac.new(hmac_key, message, hashlib.sha512)
print('signature 512 : ' + 
signature512.digest().encode('base64').rstrip('\n'))

returns

signature 256 : tfnYBB630T/8TemIeNMSSTuY12eJMmel55ZWaRAEq/w=
signature 384 : irWXsFWoNREZddkTRDzPFgyhyiLoIt8uoi0Kpxw4GgYSfSnILXLdQu0HuM5qN4Zb
signature 512 : DU+sAkJnJBqY1QPwJRmwCK/vdACwKfysz+PetdsmvlmgRlK8Ad1tbHsjvRs/By2PR7uWEngXGjocTgqjDGMTFw==

while my c++ implementation

std::string secret = "vzxgPuegSjRksLnCAu/LElxWRonjVkCoArWzZqliiSEtmlbaCfZaGkrSweWJKQkgQsyrBUpSusAcPcGDfFhWOx==";

std::vector<unsigned char> v = b64_decode(secret);
std::string message = "azertyAZERTY";
std::vector<unsigned char> data(message.begin(), message.end());
std::vector<unsigned char> v = b64_decode(secret);

std::cout << "signature 256 : " << b64_encode(hmac_sha256(data, v)) << std::endl;
std::cout << "signature 384 : " << b64_encode(hmac_sha384(data, v)) << std::endl;
std::cout << "signature 512 : " << b64_encode(hmac_sha512(data, v)) << std::endl;

returns

signature 256 : AUTcxQUgWHDOX3KzXJwl6ACDtfNJlMXq55pTBGp3RxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
signature 384 : irWXsFWoNREZddkTRDzPFgyhyiLoIt8uoi0Kpxw4GgYSfSnILXLdQu0HuM5qN4ZbAAAAAAAAAAAAAAAAAAAAAA==
signature 512 : DU+sAkJnJBqY1QPwJRmwCK/vdACwKfysz+PetdsmvlmgRlK8Ad1tbHsjvRs/By2PR7uWEngXGjocTgqjDGMTFw==

And one can see that the signatures 256 look very different...

Thank you very much in advance !

Upvotes: 4

Views: 8924

Answers (1)

T.S.
T.S.

Reputation: 302

I just bumped into this while looking for a similar solution for a legacy software I am working on.

The extra As seen at the output for sha256 and sha384 are due to the fact that len is being defined as EVP_MAX_MD_SIZE which has a value of 64 and is the max length expected for sha512. Changing len to 32 (for sha256) fixes the issue reported by the OP.

Upvotes: 0

Related Questions