【问题标题】:How to compute HMAC SHA 256 for AWS authentication?如何为 AWS 身份验证计算 HMAC SHA 256?
【发布时间】:2021-05-23 05:57:24
【问题描述】:

我正在尝试实施 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")

kSecretwJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY

根据他们的函数的结果是:c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9

我在互联网上使用了我自己的计算以及 HMAC SHA256 生成器(它们匹配),我得到了:

8c028f7953b7f2b9fa6d2e816f7b15675dc2329c139e293b383759c5ba8af679

请问有人知道 AWS 如何计算他们的 HMAC SHA256 吗?

谢谢 干杯,

【问题讨论】:

    标签: amazon-web-services hmac


    【解决方案1】:

    请注意,根据您链接的文档:

    HMAC(key, data) 表示以二进制格式返回输出的 HMAC-SHA256 函数。每个哈希函数的结果成为下一个哈希函数的输入。

    即 HMAC() 返回 byte[] 而不是十六进制字符串。它还期望其输入为byte[]。如果您的 hmac 函数在返回结果之前将散列转换为十六进制字符串,则必须确保在将其用作下一步的键时将其正确转换回 byte[]。或者 - 最好 - 不要将中间结果转换为字符串,而只需将 byte[] 传递给下一步,仅将最终结果转换为字符串。

    例如考虑以下内容:

    一些散列函数hash(key, value) 返回[255, 255] 作为结果(即byte[] 有两个字节)。当您将 byte[] 转换为十六进制字符串时,您将获得字符串 "ffff"。但是如果你把这个字符串作为key传递到下一步,大多数在线工具不会把这个字符串当作十六进制表示,而只是把字符串的每个字符当作一个字节。即你的字符串"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) 也按上述方式处理其输入。即如果keystring,则在转换为字节数组时,键中的每个字符都被视为单个字节。当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);
        }
        
    }
    

    两种变体都提供了预期的输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-28
      • 2016-01-09
      • 1970-01-01
      • 2016-04-29
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 2011-10-21
      相关资源
      最近更新 更多