用于签名 AWS 请求的 HMAC SHA-256

HMAC SHA-256 for a signed AWS request

编辑:问题是我使用十六进制编码的字符串作为键,我应该使用原始字节。如何从 openssl 命令中获取原始字节?

---原题---

我正在尝试按照此处的说明创建已签名的 iam 请求:https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html

它基本上说要按照以下步骤生成签名密钥和签名:

signing key = HMAC(HMAC(HMAC(HMAC("AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY","20150830"),"us-east-1"),"iam"),"aws4_request")
signature = HexEncode(HMAC(signing key, "AWS4-HMAC-SHA256\n20150830T123600Z\n20150830/us-east-1/iam/aws4_request\nf536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59"))

我创建了以下 shell 脚本作为测试:

#!/usr/bin/env bash
set -euo pipefail

stringToSign="AWS4-HMAC-SHA256\n20150830T123600Z\n20150830/us-east-1/iam/aws4_request\nf536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59"

dateKey=$(echo -n "20150830" | openssl dgst -sha256 -hmac "AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY")
regionKey=$(echo -n "us-east-1" | openssl dgst -sha256 -hmac "$dateKey")
serviceKey=$(echo -n "iam" | openssl dgst -sha256 -hmac "$regionKey")
signingKey=$(echo -n "aws4_request" | openssl dgst -sha256 -hmac "$serviceKey")

echo "signing key: $signingKey"

signature=$(echo -n "$stringToSign" | openssl dgst -sha256 -hmac "$signingKey")

echo "signature: $signature"

输出为:

signing key: 8c028f7953b7f2b9fa6d2e816f7b15675dc2329c139e293b383759c5ba8af679
signature: 9fd29d6aaac30d0747da90c23a4b883a8bc02b439f35df255fa2f93f6c99f46f

dateKey 是 45fb073b035485bb42f64d8d242984f3431d02e31c35ba4b661d31bbec45378d

但是上面链接的文档说它应该是:

signing key: c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9
signature: 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7

如何生成正确的密钥和签名?

编辑——openssl 版本:

$ openssl version -a
LibreSSL 2.6.5
built on: date not available
platform: information not available
options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: information not available
OPENSSLDIR: "/private/etc/ssl"

How can I get the raw bytes out of the openssl command?

使用-binary选项。从 manpageopenssl dgst:

openssl dgst [-cd] [-binary] [-digest] [-hex] [-hmac key] ...

     -binary
             Output the digest or signature in binary form.

为了获得正确的签名,我还必须用实际的换行符替换要签名的字符串中的 \n 个字符。


工作脚本:

#!/usr/bin/env bash
set -euo pipefail

stringToSign="AWS4-HMAC-SHA256
20150830T123600Z
20150830/us-east-1/iam/aws4_request
f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59"

dateKey=$(echo -n "20150830" | openssl dgst -sha256 -binary -hmac "AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY")
regionKey=$(echo -n "us-east-1" | openssl dgst -sha256 -binary -hmac "$dateKey")
serviceKey=$(echo -n "iam" | openssl dgst -sha256 -binary -hmac "$regionKey")
signingKey=$(echo -n "aws4_request" | openssl dgst -sha256 -binary -hmac "$serviceKey")
signature=$(echo -n "$stringToSign" | openssl dgst -sha256 -hmac "$signingKey")
echo "signature: $signature"
# signature: 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7