我从身份验证源获取签名的有效负载,该身份验证源采用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_sig
和signature
以使它们显示为字符串,但我无法弄明白如何我需要更改预期的签名,以便我可以比较字节的字节数。
我显然可以解决这个问题,但只是转换字符串bar
,但这很脏,我只是不喜欢它。
我在哪里错了?我不理解的是什么?
答案 0 :(得分:2)
好消息是哈希计算似乎有效。
坏消息是你正在以脑死亡的方式接收哈希。出于某种原因,似乎作者认为这是一个好主意:
在原始二进制文件上使用 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
进行比较。
理想情况下,你应该和那些为你提供疯狂格式的人交谈,然后用一条线索来打他们......