如何计算用于AWS身份验证的HMAC SHA 256?

问题描述 投票:0回答:1

我正在尝试实现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个回答
3
投票

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

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);
    }
    
}

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

© www.soinside.com 2019 - 2024. All rights reserved.