Question

(This is a follow-up question to Padding the message in SHA256.)

(I am trying to implement the SHA-256 hash function in C++. I am doing this purely for fun and learning purposes.)

I have my string message with length message_length. I have appended the string with the bit 1 followed by 0s so that the length of the string is now 448 bits mod 512 bits.

I now need to append the string with the message_length as 64-bit big-endian integer to the string, but I can't quite figure out how to do this in C++.

For sake of argument then, lets say message_length is 3 bytes = 24 bits. 24 in hex is 18, so I would need to append 00 00 00 00 00 00 00 18 to the string.

So what I would like is a function that converts the integer 3 into the string 00 00 00 00 00 00 00 18 so that I can append this.

My question boils down to

How can I convert a 64bit integer to a big-endian byte array in C++

Was it helpful?

Solution

Edit: I just reread your question (in the intend to edit it). I think you misunderstood the format SHA256 expects you to use. Instead of appending the string 00 00 00 00 00 00 00 18 (each byte hex encoded and separated by spaces) for a message length of 24 you need to append the raw bytes 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 and 0x18. They do not represent any printable characters. See below for a way to get these bytes. My example uses an integer whose byte representation happens to contain only printable characters (in ASCII).

Btw., the reason you pad to 448 bits is that you have 64 bits left in the full block size of 512 bits so you can put the big-endian encoding of the message length in there.


You can extract a single byte of num using num>>(8*i) & 0xff where you will get the least significant byte for i=0 and the most significant byte of an unsigned long (64bit) with i=7. Iterating through all positions you can get each byte:

   unsigned long num = 0x626967656e646961L;
   //Store big endian representation in a vector:
   std::vector<unsigned char> bigEndian;
   for(int i=7; i>=0; i--){
      bigEndian.push_back( (num>>(8*i)) & 0xff );
   }

If you need it as a string you can convert it using the iterator constructor of a string:

   std::string bigEndianString(bigEndian.begin(),bigEndian.end());

Complete code with test output:

#include <iostream>
#include <string>
#include <vector>
int main() {
   unsigned long num = 0x626967656e646961L;

   //Store big endian representation in a vector:
   std::vector<unsigned char> bigEndian;
   for(int i=7; i>=0; i--){
      bigEndian.push_back( (num>>(8*i)) & 0xff );
   }

   //Convert vector to string:
   std::string bigEndianString(bigEndian.begin(),bigEndian.end());

   //Test correctness:
   for(std::vector<unsigned char>::const_iterator it = bigEndian.begin(); it != bigEndian.end(); ++it) {
       std::cout << std::hex << (int)*it << ' ';
   }
   std::cout << std::endl << bigEndianString << std::endl;

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top