You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HMAC SHA256内层哈希正常但外层哈希结果错误求助

HMAC-SHA256外层Hash结果不符的排查建议

问题背景

实现NIST标准的HMAC-SHA256时,内层Hash(Hash((Key^ipad)||text))结果符合预期,但外层Hash(Hash((Key^opad)||H_1))结果错误。已知K0、K0ipad、K0opad、内层Hash结果均正确,外层得到的ASCII结果为218135127ad7a8e5967ce7b47499214d1df46a9589eb0bec7637c86021fd928d,预期是8BB9A1DB9806F20DF7F77B82138C7914D174D59E13DC4D0169C9057B133E1D62。

相关代码片段:

// Up to this point ipad, opad, K0, both XORs all match the expected values

const std::array<uint32_t, 8>& h_output_1 = Hash<BUFFER_SIZE>(&xor_1[0], 64, &message[0], message_length);
// This is correct
LOG("H_1: " << sha256::GetASCIIRepresentation(h_output_1));

const std::array<uint32_t, 8>& h_output_2 = Hash<BUFFER_SIZE>(&xor_2[0], 64, &h_output_1[0], 32);
// This is NOT correct
LOG("H_2: " << sha256::GetASCIIRepresentation(h_output_2));

排查方向

1. 检查内层输出的字节序匹配问题

SHA-256的最终状态(8个uint32_t)是大端字节序定义的,但内存中uint32_t的存储默认是主机字节序(多数系统为小端)。

  • 若直接将h_output_1的内存布局(小端字节)传给外层Hash,相当于每个uint32_t的字节顺序被反转,外层输入会完全错误。
  • 验证方式:将h_output_1的每个uint32_t转换为大端字节序后拼接成32字节缓冲区,对比该缓冲区的十六进制与NIST示例中H_1的十六进制是否一致。

2. 确认Hash函数的拼接逻辑

Hash(buffer1, len1, buffer2, len2)的拼接逻辑需严格符合预期:

  • 检查函数是否将len2当成uint32_t的个数而非字节数(比如误将32字节解读为8个uint32_t,导致读取64字节越界数据)。
  • 手动构造(K0^opad)||H_1的正确字节流,用独立SHA-256工具计算结果,再dump代码中外层Hash的实际输入字节流,对比两者是否完全一致。

3. 验证uint32_t数组到字节流的转换

传递&h_output_1[0]给Hash时,需确保转换为32字节的正确字节流:

  • 若GetASCIIRepresentation是将每个uint32_t按大端转十六进制(如0x12345678转"12345678"),但传给Hash的是内存中小端字节,会出现H_1显示正确但外层输入错误的情况。
  • 测试方案:将h_output_1的每个uint32_t按大端转换为4字节,拼接成32字节数组后替换&h_output_1[0]传给外层Hash,查看结果是否符合预期。

4. 核对外层Hash的输入完整性

完整dump外层Hash的输入(opad + H_1字节流),与NIST示例中的对应输入逐字节对比:

  • NIST HMAC示例的外层输入是(K0^opad)拼接内层Hash的字节结果,而非uint32_t状态的内存布局,确保输入完全匹配。

内容的提问来源于stack exchange,提问作者intrigued_66

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 11:55:31