为什么我在评估HMAC时会在字节中获得两种不同的“格式”十六进制?

时间:2014-02-20 17:38:47

标签: c# encoding hex base64 hmac

我从身份验证源获取签名的有效负载,该身份验证源采用base64编码和URL编码格式。我在评估时会在某处感到困惑,并以不同的“格式”结束相似的数据。

这是我的代码:

//Split the message to payload and signature
string[] split = raw_message.Split('.');

//Payload
string base64_payload = WebUtility.UrlDecode(split[0]);
byte[] payload = Convert.FromBase64String(base64_payload);

//Expected signature
string base64_expected_sig = WebUtility.UrlDecode(split[1]);
byte[] expected_sig = Convert.FromBase64String(base64_expected_sig);

//Signature
byte[] signature = hmacsha256.ComputeHash(payload);

//Output as a string
var foo = System.Text.Encoding.UTF8.GetString(expected_sig);
var bar = BitConverter.ToString(signature);

预期签名(foo)如下所示: 76eba09fcb54877299dcbd1e1e35717e3bd42e066e7ecdb131c7d0161dec3418

计算的签名(bar)如下:

76-EB-A0-9F-CB-54-87-72-99-DC-BD-1E-1E-35-71-7E-3B-D4-2E-06-6E-7E-CD-B1-31-C7-D0-16-1D-EC-34-18

显然,在比较字节的字节时,这不起作用。

我发现我必须以不同的方式转换expected_sigsignature以使它们显示为字符串,但我无法弄明白如何我需要更改预期的签名,以便我可以比较字节的字节数。

我显然可以解决这个问题,但只是转换字符串bar,但这很脏,我只是不喜欢它。

我在哪里错了?我不理解的是什么?

1 个答案:

答案 0 :(得分:2)

好消息是哈希计算似乎有效。

坏消息是你正在以脑死亡的方式接收哈希。出于某种原因,似乎作者认为这是一个好主意:

  • 计算哈希(罚款)
  • 将此二进制数据转换为文本为十六进制(精细)
  • 通过应用ASCII / UTF-8 / anything-ASCII兼容编码将十六进制转换回二进制数据(为什么?)
  • 使用base64(what?)
  • 将结果转换回文本
  • 对结果进行URL编码(对于hex ...甚至不需要)

在原始二进制文件上使用 base64 十六进制是有道理的,但应用两者是疯狂的。

无论如何,你做同样的事情很容易。例如:

string hexSignature = string.Join("", signature.Select(b => b.ToString("x2")));
byte[] hexSignatureUtf8 = Encoding.UTF8.GetBytes(hexSignature);
string finalSignature = Convert.ToBase64String(hexSignatureUtf8);

现在应该匹配WebUtility.UrlDecode(split[1])

或者,您可以从结果中的内容向后工作,但我不会将十六进制解析为字节 - 保持上面的第一行会更简单,但使用:

string expectedHexBase64 = WebUtility.UrlDecode(split[1]);
byte[] expectedHexUtf8 = Convert.FromBase64String(expectedHexBase64);
string expectedHex = Encoding.UTF8.GetString(expectedHexUtf8);

然后将其与hexSignature进行比较。

理想情况下,你应该和那些为你提供疯狂格式的人交谈,然后用一条线索来打他们......