【问题标题】:HMAC SHA256 hash computation in C#C# 中的 HMAC SHA256 哈希计算
【发布时间】:2016-08-03 04:18:22
【问题描述】:

我需要使用 SHA256 哈希函数来计算 HMAC。我有一个以 base64 格式编码的密钥。还有一个在线工具可以正确计算 HMAC(已验证)。 http://www.freeformatter.com/hmac-generator.html 我写了如下代码sn-p:

var signatureHashHexExpected = "559bd871bfd21ab76ad44513ed5d65774f9954d3232ab68dab1806163f806447";
var signature = "123456:some-string:2016-04-12T12:44:16Z";
var key = "AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ=";

var shaKeyBytes = Convert.FromBase64String(key);
using (var shaAlgorithm = new System.Security.Cryptography.HMACSHA256(shaKeyBytes))
{
    var signatureBytes = System.Text.Encoding.UTF8.GetBytes(signature);
    var signatureHashBytes = shaAlgorithm.ComputeHash(signatureBytes);
    var signatureHashHex = string.Concat(Array.ConvertAll(signatureHashBytes, b => b.ToString("X2"))).ToLower();

    System.Diagnostics.Debug.Assert(signatureHashHex == signatureHashHexExpected);
}

问题: 我的代码没有生成正确的 HMAC。我使用不同的在线工具和替代的 C# 实现验证了不同的步骤。仅未确认从 base64 进行的转换。我错过了什么?

更新: 我的代码计算的signatureHashHex是“a40e0477a02de1d134a5c55e4befa55d6fca8e29e0aa0a0d8acf7a4370208efc”

回答: 该问题是由误导性文档引起的,该文档指出密钥以 Base64 格式提供。查看接受的答案:

var shaKeyBytes = System.Text.Encoding.UTF8.GetBytes(key);

【问题讨论】:

  • 你确定签名是用UTF8编码的吗?
  • 不,但我尝试了许多不同的编码,结果相同。
  • signatureHashHex的结果是什么?
  • @Ivar 我用计算值更新了我的问题。

标签: c# hash hmac


【解决方案1】:

您的结果是正确的,不同之处在于您链接到的工具为键值解码 Base64 并将其视为一系列字符。

例如要复制其结果,请将您的密钥视为字符串:

var shaKeyBytes = System.Text.Encoding.UTF8.GetBytes("AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ=");

产量

559bd871bfd21ab76ad44513ed5d65774f9954d3232ab68dab1806163f806447

(这显然不是正确的做法)

【讨论】:

  • 麻烦解释一下,为什么GetBytes(...)是“明显错误的”?如果我的关键词是"This_is_my_secret_keyphrase"怎么办?
  • 因为 Base64 字符串是一个编码的字节序列和应该使用的那些字节(解码后),而不是字符串本身。您无需订购新椅子,只需坐在盒子上即可。 ("This_is_my_secret_keyphrase" 不是 Base64)
  • 一个简单的字符串也是一个编码的字节序列。这只是解释的问题。存储密码短语的格式完全无关紧要,只要它可以转换为用于加密/解密的正确字节向量即可。 Convert.FromBase64String("VGhpc19pc19teV9zZWNyZXRfa2V5cGhyYXNl")System.Text.Encoding.UTF8.GetBytes("This_is_my_secret_keyphrase") 有什么区别?只需确保双方在相同的输入上使用相同的方法。我不记得要求密钥是 base64 字符串。
  • 我不明白争论的重点,GetBytes(...) 是“明显错误的”,因为它使用的值本来是要进行 Base64 解码的,但不是。
  • 伙计们,这个问题是由误导性文档引起的,该文档指出密钥是以 Base64 格式提供的。
【解决方案2】:

HMAC: 消息认证码,用于验证发送方数据的完整性,是只转发算法,作用于发送方和接收方都知道的共享密钥两者。在生成哈希值之前,我们必须对密钥和消息进行编码。我们可以使用编码 UTF8ASCIIEncoding 之一。

UTF8 编码:

var signature = "123456:some-string:2016-04-12T12:44:16Z";
var key = "AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ=";


var signatureBytes = System.Text.Encoding.UTF8.GetBytes(signature);
var shaKeyBytes = System.Text.Encoding.UTF8.GetBytes(key);

ASCIIEncoding 编码:

var signature = "123456:some-string:2016-04-12T12:44:16Z";
var key = "AgQGCAoMDhASFAIEBggKDA4QEhQCBAYICgwOEBIUAgQ=";

var signatureBytes = System.Text.ASCIIEncoding.GetBytes(signature);
var shaKeyBytes = System.Text.ASCIIEncoding.GetBytes(key);

现在我们可以在上面的代码中使用这个编码的消息和密钥了。

【讨论】:

    猜你喜欢
    • 2014-01-14
    • 2020-11-27
    • 2013-05-12
    • 2012-03-28
    • 2016-10-10
    • 2016-08-20
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    相关资源
    最近更新 更多