В C ++ (точнее, в C ++ 11) я хотел бы получить HMAC SHA512-хэш строки, содержащей символ NUL (символ ASCII, у которого все восемь битов установлены в 0).
Используя crypto ++, до сих пор мой подход был следующим:
std::string message("My\0Message",2+1+7);
std::string key_base64 = "MYSECRETKEY";
std::string key;
StringSource ss(key_base64, true, new Base64Decoder(new StringSink(key)));
std::string mac, encoded;
HMAC< SHA512 > hmac((byte*)key.c_str(), key.length());
StringSource(message,
true,
new HashFilter(hmac, new StringSink(mac))
); // StringSource
encoded.clear();
StringSource(mac,
true,
new Base64Encoder(new StringSink(encoded), false) // Base64Encoder. Pass argument 'false' to prevent insertion of line breaks
); // StringSource
std::cout << "Hashed message (Base64): " << encoded << std::endl;
Это не работает должным образом, когда символ NUL включен, как в message
строка выше.
Версия хеширования в кодировке Base64 (переменная mac
) Я получаю это
bXmQCkzhzq3J81vInF6IRtxXyd+mN8TRh8e3qHThJ+/RYVcgRkFZ9iStKnNaVsGgco/nisUeRpT3m388UR/BMg==
вместо ожидаемого
hUk4PX3mnqs943JnMR+ptW6f8+enIUGBd4x7sUA+Ug2squOFVF6ZdiCewSBDlGAwNuWf+9Uh0AqUkQV1vMNHxg==
РЕДАКТИРОВАТЬ
Ожидаемый результат можно получить из командной строки Bash следующим образом:
hex_encoded_secret=$(echo -n "MYSECRETKEY" | base64 --decode | xxd -p | tr '\n' ' ' | tr -d '[:space:]')
echo -ne "My\0Message" | openssl dgst -sha512 -mac HMAC -macopt hexkey:"${hex_encoded_secret}" -binary | base64 | tr -d '\n'
Это создает ожидаемый результат, как указано выше.
Это не работает должным образом, когда символ NUL включен, как в строке сообщения выше.
Конструктор, который вы использовали, должен быть в порядке, потому что машина использует std::string::size()
, и не std::string::c_str()
определить длину. Я подозреваю, что что-то еще не совсем правильно, например, проблема кодировки символов.
Вы используете std::string
конструктор StringSource
, Второй конструктор StringSource
принимает двоичную строку Возможно, вам повезет больше с этим в вашем производственном коде:
StringSource(reinterpret_cast<const byte*>(&message[0]),
message.size(),
true,
new HashFilter(hmac, new StringSink(mac))
); // StringSource
Также см StringSource
на Crypto ++ вики.
Других решений пока нет …