我正在尝试实现AWS身份验证,但我陷入了HMAC SHA256的计算中。
在此示例中:https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
他们在计算
HMAC(HMAC(HMAC(HMAC("AWS4" + kSecret,"20150830"),"us-east-1"),"iam"),"aws4_request")
使用 kSecret 是 wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY
根据它们的函数结果是:c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9
我使用了自己的计算以及互联网上的 HMAC SHA256 生成器(它们匹配),我得到了:
8c028f7953b7f2b9fa6d2e816f7b15675dc2329c139e293b383759c5ba8af679
有人知道 AWS 如何计算他们的 HMAC SHA256 吗?
谢谢 干杯,
请注意,根据您链接的文档:
HMAC(key, data) 表示以二进制格式返回输出的 HMAC-SHA256 函数。每个哈希函数的结果将成为下一个哈希函数的输入。
即 HMAC() 返回一个
byte[]
而不是十六进制字符串。它期望输入为 string
或 byte[]
。如果输入是 string
,则其每个字符都会转换为 byte
。如果您的 hmac 函数在返回结果之前将哈希值转换为十六进制字符串,则在将其用作下一步的密钥时,您必须确保将其正确转换回 byte[]
。或者 - 最好 - 不要将中间结果转换为字符串,而只是将 byte[]
传递到下一步,仅将最终结果转换为字符串。
例如,考虑以下事项:
某些哈希函数
hash(key, value)
返回[255, 255]
作为结果(即具有两个字节的byte[]
)。当您将 byte[]
转换为十六进制字符串时,您将得到字符串 "ffff"
。但是,如果您将此字符串作为密钥传递到下一步,则大多数在线工具不会将此字符串视为十六进制表示,而只是将字符串的每个字符视为单个字节。即你的字符串"ffff"
将变成字节数组[102, 102, 102, 102]
,这显然是错误的并导致不同的哈希结果。
对于JS:
var secret = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";
var date = "20150830";
var region = "us-east-1";
var service = "iam";
var kdate = CryptoJS.HmacSHA256(date, "AWS4"+secret);
var kregion = CryptoJS.HmacSHA256(region, kdate);
var kservice = CryptoJS.HmacSHA256(service, kregion);
var ksigning = CryptoJS.HmacSHA256("aws4_request", kservice);
var hashInHex = CryptoJS.enc.Hex.stringify(ksigning);
console.log(hashInHex);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/enc-base64-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js"></script>
CryptoJS.HmacSHA256(data, key)
也像上面描述的那样处理它的输入。即,如果 key
是 string
,则在转换为字节数组时,键中的每个字符都被视为单个字节。当 key
已经是 byte[]
时,就按原样进行处理。并且 HmacSHA256
将哈希值返回为 byte[]
而不是字符串。
对于 C#
using System;
using System.Text;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var secret = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";
var date = "20150830";
var region = "us-east-1";
var service = "iam";
var kdate = h(Encoding.UTF8.GetBytes("AWS4"+ secret), Encoding.UTF8.GetBytes(date));
var kregion = h(kdate, Encoding.UTF8.GetBytes(region));
var kservice = h(kregion, Encoding.UTF8.GetBytes(service));
var ksigning = h(kservice, Encoding.UTF8.GetBytes("aws4_request"));
Console.WriteLine(BitConverter.ToString(ksigning).Replace("-","").ToLower());
}
public static byte[] h(byte[] key, byte[] buffer) {
var hmacsha256 = new HMACSHA256(key);
return hmacsha256.ComputeHash(buffer);
}
}
两种变体都提供了预期的输出。