1

In python to obtain the digest of the byte string, I do this

hashlib.sha224(b"Nobody inspects the spammish repetition").hexdigest()

Result: 'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'

to reverse result, I do this

hashlib.sha224(b"Nobody inspects the spammish repetition").hexdigest()[::-1]

Result: '2e109e97db885698cb12078e1e6dc055cd25f30c445cf8a54cb7334a'

I would like to do the same in C with Openssl.

I do this

#include <openssl/sha.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>

int main()
{
   unsigned char digest[SHA224_DIGEST_LENGTH];
   char string[] = "Nobody inspects the spammish repetition";
   SHA224((unsigned char*)&string, strlen(string), (unsigned char*)&digest);    

   char mdString[SHA224_DIGEST_LENGTH * 2 + 1];
   for (int i = 0; i < SHA224_DIGEST_LENGTH; i++)
       sprintf(&mdString[i * 2], "%02x", (unsigned int)digest[i]);
   printf("SHA224 digest: %s\n", mdString);

   return EXIT_SUCCESS;
}

but I don't know how, with C++, to get the same result as the reverse in python.

How can I achieve this?

Any help would be greatly appreciated. Thank you.

Edit: it's not the same as using std::reverse. It is not a duplicate of the question How do you reverse a string in place in C or C++?

My solution: Ref: Swapping the nibbles in a char element

for (uint16_t j=0; j < SHA224_DIGEST_LENGTH; j++)
    digest[j] = ((digest[j] & 0x0F) << 4) | ((digest[j] & 0xF0) >> 4);
std::reverse(std::begin(digest), std::end(digest));
LeMoussel
  • 5,290
  • 12
  • 69
  • 122
  • 5
    if you want to do that in C++ why do you write C code? – Slava Mar 07 '19 at 15:39
  • You need to apply `std::reverse` to result string, not digest, or change `sprintf` call so it would generate hex digits in reverse – Slava Mar 07 '19 at 15:53
  • I want to reverse the digest. Result string is just used to check that the reverse is OK. – LeMoussel Mar 07 '19 at 16:01
  • @LeMoussel Well, if you don't want to produce "e201e979bd886589bc2170e8e1d60c55dc523fc044c58f5ac47b33a4", then you don't want to reverse bytes. – eerorika Mar 07 '19 at 16:02
  • @eerorika You're right, but I don't speak English well and I realize how bad the title I gave to this question was. I don't know how to say that I would like to get the result '2e109e97db885698cb12078e1e6dc055cd25f30c445cf8a54cb7334a' – LeMoussel Mar 07 '19 at 16:06
  • @LeMoussel Half of a byte is a nibble. So, it appears that you want to reverse nibbles. Simplest solution is to reverse the `mdString` as suggested by Slava. You can convert the string back to the binary array if you need to. – eerorika Mar 07 '19 at 16:09
  • @eerorika I changed the title accordingly. – LeMoussel Mar 07 '19 at 16:26
  • @eerorika Thank you for your idea 'nibble'. I modified my article with the solution I found. – LeMoussel Mar 07 '19 at 16:50
  • @LeMoussel I've removed the duplicate closure. Feel free to answer post your own answer. – eerorika Mar 07 '19 at 16:53

1 Answers1

2

The obvious approach is to first reverse the byte array, followed by a std::for_each to nibble-swap each byte individually.

Or if you are making a copy, then you could do the nibble-swap as you go:

template<std::size_t N>
void nibble_reverse(char (&dest)[N], const char (&src)[N])
{
    static auto const nibble_swap =
        [](std::uint8_t c){ return c >> 4 | c << 4; };

    std::transform(std::crbegin(src), std::crend(src),
                   std::begin(dest),
                   nibble_swap);
}
Toby Speight
  • 27,591
  • 48
  • 66
  • 103