Как преобразовать 64-битное целое число в байтовый массив с прямым порядком байтов в C ++

(Это дополнительный вопрос к Заполнению сообщения в SHA256.)

(Я пытаюсь реализовать хеш-функцию SHA-256 на C ++. Я делаю это исключительно для развлечения и обучения.)

У меня есть строка message с длиной message_length. Я добавил к строке бит 1, за которым следует 0s, так что теперь длина строки составляет 448 бит по модулю 512 бит.

Теперь мне нужно добавить строку с message_length как 64-битное целое число с прямым порядком байтов к строке, но я не могу понять, как это сделать на C ++.

В качестве аргумента допустим, что message_length составляет 3 байта = 24 бита. 24 в шестнадцатеричном формате - это 18, поэтому мне нужно было бы добавить 00 00 00 00 00 00 00 18 к строке.

Итак, мне нужна функция, которая преобразует целое число 3 в строку 00 00 00 00 00 00 00 18, чтобы я мог добавить это.

Мой вопрос сводится к

Как преобразовать 64-битное целое число в байтовый массив с прямым порядком байтов в C ++


person Thomas    schedule 03.05.2014    source источник
comment
Ваш вопрос сводится к следующему: как преобразовать 64-битное целое число в байтовый массив с прямым порядком байтов в C ++. Если вы спросите об этом так, вы получите гораздо лучшие результаты, поскольку читателей, не знакомых с криптографией, не оттолкнет специфика SHA256.   -  person Perseids    schedule 04.05.2014
comment
@Perseids: Спасибо за предложение. Редактировал вопрос. Не стесняйтесь редактировать больше, если можете сделать это более понятным.   -  person Thomas    schedule 04.05.2014
comment
Я был уверен, что в stackoverflow должно что-то быть, но это было глубоко похоронено: stackoverflow.com/a/1701555/371137. И это: stackoverflow.com/ questions / 1522994 /   -  person Perseids    schedule 04.05.2014


Ответы (1)


Изменить: Я только что перечитал ваш вопрос (с намерением отредактировать его). Я думаю, вы неправильно поняли формат, который SHA256 ожидает от вас. Вместо добавления строки 00 00 00 00 00 00 00 18 (каждый байт в шестнадцатеричной кодировке и разделенных пробелами) для длины сообщения 24 вам нужно добавить необработанные байты 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 и 0x18. Они не представляют собой печатных символов. См. Ниже способ получить эти байты. В моем примере используется целое число, байтовое представление которого содержит только печатаемые символы (в ASCII).

Кстати, причина, по которой вы добавляете 448 бит, заключается в том, что у вас осталось 64 бита в полном размере блока в 512 бит, поэтому вы можете поместить туда кодировку с прямым порядком байтов длины сообщения.


Вы можете извлечь один байт num, используя num>>(8*i) & 0xff, где вы получите младший байт для i=0 и самый значимый байт для длинного байта без знака (64 бита) с i=7. Перебирая все позиции, можно получить каждый байт:

   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 );
   }

Если он вам нужен как строка, вы можете преобразовать его с помощью конструктора итератора строки:

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

Полный код с тестовым выводом:

#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;

}
person Perseids    schedule 04.05.2014