【问题标题】:Hashing a string containing the NUL character in C++ using crypto++使用crypto++在C++中散列包含NUL字符的字符串
【发布时间】:2018-09-03 18:36:00
【问题描述】:

在 C++(准确地说是 C++11)中,我想获取包含 NUL 字符(所有八位都设置为 0 的 ASCII 字符)的字符串的 HMAC SHA512 哈希。

使用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 的字符串可以工作。可以从命令行获得预期的输出,如我上面原始问题的编辑所示。
  • 请发布一个 MCVE,包括完整的 C++ 代码和你真正的 bash 比较脚本。echo -n "MY_SECRET_KEY" | base64 --decode 不可能工作。
  • 您可能应该删除 OpenSSL 装置中的大部分命令。使用 echo -e 将完全相同的二进制字符串发送到 OpenSSL。开始对您的 OpenSSL 相关命令进行故障排除。
  • @jww:您在下面建议的编码确实存在问题。密钥 base64 字符串在末尾需要一个额外的 = 以使其成为 4 个字符的倍数。没有,不同的工具似乎对此进行了不同的解码。我现在设法让它工作,感谢您的帮助和在线 HMAC 生成器的链接

标签: c++ string hash crypto++ nul


【解决方案1】:

当 NUL 字符包含在上面的消息字符串中时,这将无法正常工作。

您使用的构造函数应该没问题,因为机器使用std::string::size(),而不是std::string::c_str() 来确定长度。我怀疑还有一些不太正确的地方,比如字符编码问题。

您正在使用StringSourcestd::string 构造函数。 StringSource 的第二个构造函数采用二进制字符串。在生产代码中使用它可能会更好:

StringSource(reinterpret_cast<const byte*>(&message[0]),
         message.size(),
         true,
         new HashFilter(hmac, new StringSink(mac))              
         ); // StringSource

另请参阅 Crypto++ wiki 上的 StringSource

【讨论】:

  • 感谢您指出 wiki 上的 StringSource 页面。我看过重载版本,但您的建议生成的输出与我的代码完全相同。我还验证了消息字符串确实包含 NUL 字符:message.size() 为 10。我还检查了 Base64 编码是否导致问题;二进制输出已经不同。还有其他建议或想法吗?
  • @JohnS。 - 使用 NIST 测试向量并通过 OpenSSL 装置运行它。我相信你会发现它没有得出正确的结果。您还可以使用在线计算器验证您的字符串。这个看起来不错,因为它需要十六进制:Online HMAC Generator
猜你喜欢
  • 2014-08-18
  • 2019-12-13
  • 1970-01-01
  • 2014-10-18
  • 2015-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多