Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HMAC256 with OpenSSL 3

Tags:

c++

openssl

I am new to C++ so go easy :)

I have the following code snippet, however I am using OpenSSL 3, and the compiler is giving various errors: 'HMAC_CTX_new': Since OpenSSL 3.0. I understand that some of the APIs used below are now deprecated and need updating.

Can someone show me to update the below snippet to work with the updated APIs for OpenSSL 3?

const std::string secretKey = "secret";
std::vector<unsigned char> secretKeyByteArray(secretKey.begin(), secretKey.end());
std::vector<unsigned char> signature(signatureRawData.begin(), signatureRawData.end());
std::vector<unsigned char> signatureBytes(HMAC_MAX_MD_CBLOCK);
unsigned int signatureLength = 0;

HMAC_CTX* hmacCtx = HMAC_CTX_new();
HMAC_Init_ex(hmacCtx, secretKeyByteArray.data(), secretKeyByteArray.size(), EVP_sha256(), nullptr);
HMAC_Update(hmacCtx, signature.data(), signature.size());
HMAC_Final(hmacCtx, signatureBytes.data(), &signatureLength);
HMAC_CTX_free(hmacCtx);

std::ostringstream signatureHex;
for (const auto& c : signatureBytes)
    signatureHex << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c);

std::string requestSignatureHexString = signatureHex.str();
like image 759
Sam Avatar asked Dec 19 '25 18:12

Sam


1 Answers

Here's an example from the code that I use to generate SHA-256 HMAC for OpenSSL 1.1.1 or 3.0:

std::string GetHmacSha256(std::string key, std::string msg){
    unsigned int hash_len = 32;
    unsigned char hash[32] = {};

#if OPENSSL_API_COMPAT >= 0x30000000L
    if(!HMAC(EVP_sha256(), &key[0], key.length(),(unsigned char*)&msg[0], msg.length(), hash, &hash_len)){
      std::cout << "[ERROR]: HMAC Generation failed ";
      return {};
    } 
#else
    // This code will work with OpenSSL 1.1. but not with 1.0.1.
    HMAC_CTX *hmac = HMAC_CTX_new();
    HMAC_Init_ex(hmac, &key[0], key.length(), EVP_sha256(), nullptr);
    HMAC_Update(hmac, (unsigned char*)&msg[0], msg.length());
    HMAC_Final(hmac, hash, &hash_len);
    HMAC_CTX_free(hmac);        
#endif

    std::stringstream ss;
    ss << std::hex << std::setfill('0');
    for (size_t i = 0; i < hash_len; ++i) {
        ss << std::hex << std::setw(2)  << (unsigned int)hash[i];
    }

    return (ss.str());
}

Note: My build scripts exports the symbols OPENSSL_API_COMPAT=0x30000000L and OPENSSL_NO_DEPRECATED thus making OpenSSL 3.0 as the default with no deprecated APIs.

Details at:

  • https://www.openssl.org/docs/man3.1/man3/HMAC.html
  • https://www.openssl.org/docs/manmaster/man7/OPENSSL_API_COMPAT.html

Update:

Seems like HMAC() is available starting 1.1, so can just use that and no need for the #if.. else...

like image 77
kaushal Avatar answered Dec 21 '25 08:12

kaushal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!