0

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?

bicoi77
  • 5
  • 4
  • 4
    Use `sprintf` to create a formatted string. – dbush Feb 02 '23 at 23:27
  • 3
    *Unfortunately the string returned (both encoding and decoding) bared no resemblance to the 64-byte expected value.* Because base64-encoding is not the hex encoding you did with your `printf()` loop. The base64 result of encoding 32 bytes will be about 44 bytes because base64 uses 4 ASCII `char` bytes to encode 3 binary bytes. The hex encoding your `printf()` does uses a much more limited set of `char` values and encodes each byte of data into *two* ASCII `char` values. – Andrew Henle Feb 02 '23 at 23:28
  • 2
    The string will occupy 65 bytes in total — you will need a null byte at the end to make it into a string rather than a byte array. You use `sprintf()` instead of `printf()` — carefully — to put the hex bytes in a string. Base64 encoding uses 4 output bytes for every 3 input bytes, which bears no resemblance to what you are after. – Jonathan Leffler Feb 02 '23 at 23:29

1 Answers1

1

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';
Fe2O3
  • 6,077
  • 2
  • 4
  • 20