Search code examples
copensslsha256hmachmacsha256

Convert Openssl HMAC SHA256 32-byte output to 64-byte string


I am using OpenSSL's HMAC SHA256 interface to hash a string:

unsigned char* res = HMAC(EVP_sha256(), key, key_len, data, data_len, result, result_len);

The size of the resulting hash `result_len` is 32 bytes. However, the interface I am programming to requires the SHA256 hash be 64 bytes.

I found this snippet of code, looping through the hashed output buffer and printing each byte:

for (unsigned int i = 0; i < result_len; i++)
{
    printf("%02hhX", result[i]);
}

https://stackoverflow.com/a/62458287/21129211

The above outputs the 64-bytes I am expecting (so the hash is correct).

However, I want to convert the buffer to 64 bytes, as a string. When I searched for and used base 64 decode (and encode) functions from here:

https://stackoverflow.com/a/41094722/1107474

Unfortunately the string returned (both encoding and decoding) bared no resemblance to the 64-byte expected value.

How can I convert the printf() output to a 64-byte string?


Solution

  • As commented by @dbush:

    char buf[ 64 + 1 ];
    char *at = buf;
    
    for (unsigned int i = 0; i < result_len; i++)
    {
        at += sprintf( at, "%02hhX", result[i] );
    }
    
    puts( buf ); // only for debugging purposes.
    

    You could investigate consolidating bytes (bit shifting) to have fewer calls to the powerhouse of sprintf(). That would entail knowing the Endian-ness of your architecture.

    EDIT
    There is also a standard lightweight version of converting bytes to hex. Do not forget to terminate the string after the loop has finished.

    char buf[ 64 + 1 ];
    char *at = buf;
    char *hex = "0123456789ABCDEF";
    for (unsigned int i = 0; i < result_len; i++)
    {
        unsigned char c = result[i];
        *at++ = hex[ c >>   4 ];
        *at++ = hex[ c &  0xF ];
    }
    *at = '\0';