自从提出问题以来,游戏发生了显着变化,简单的授权标头不再适用,但使用 UNIX shell 脚本执行仍然可行,如下所示。
确保“openssl”和“curl”在命令行可用。提示:仔细检查 openSSL 参数语法,因为这些可能因工具的不同版本而异;例如 openssl sha -sha256 ... 与 openssl sha256 ...
当心,一个额外的换行符或空格字符,否则单独使用 CRLF 代替 NewLine 字符会破坏签名。另请注意,您可能希望使用可能带有编码的内容类型,以防止通过通信媒体进行任何数据转换。然后,您可能需要在多个位置调整签名标头列表;请参阅AMAZON S3 API 文档,以了解在多个(冗余)位置的哈希计算中使用的标头信息的字母小写顺序等保持强制执行的众多约定。
# BERHAUZ Nov 2019 - curl script for file upload to Amazon S3 Buckets
test -n "$1" || {
echo "usage: $0 <myFileToSend.txt>"
echo "... missing argument file ..."
exit
}
yyyymmdd=`date +%Y%m%d`
isoDate=`date --utc +%Y%m%dT%H%M%SZ`
# EDIT the next 4 variables to match your account
s3Bucket="myBucket.name.here"
bucketLocation="eu-central-1"
s3AccessKey="THISISMYACCESSKEY123"
s3SecretKey="ThisIsMySecretKeyABCD1234efgh5678"
#endpoint="${s3Bucket}.s3-${bucketLocation}.amazonaws.com"
endpoint="s3-${bucketLocation}.amazonaws.com"
fileName="$1"
contentLength=`cat ${fileName} | wc -c`
contentHash=`openssl sha256 -hex ${fileName} | sed 's/.* //'`
canonicalRequest="PUT\n/${s3Bucket}/${fileName}\n\ncontent-length:${contentLength}\nhost:${endpoint}\nx-amz-content-sha256:${contentHash}\nx-amz-date:${isoDate}\n\ncontent-length;host;x-amz-content-sha256;x-amz-date\n${contentHash}"
canonicalRequestHash=`echo -en ${canonicalRequest} | openssl sha256 -hex | sed 's/.* //'`
stringToSign="AWS4-HMAC-SHA256\n${isoDate}\n${yyyymmdd}/${bucketLocation}/s3/aws4_request\n${canonicalRequestHash}"
echo "----------------- canonicalRequest --------------------"
echo -e ${canonicalRequest}
echo "----------------- stringToSign --------------------"
echo -e ${stringToSign}
echo "-------------------------------------------------------"
# calculate the signing key
DateKey=`echo -n "${yyyymmdd}" | openssl sha256 -hex -hmac "AWS4${s3SecretKey}" | sed 's/.* //'`
DateRegionKey=`echo -n "${bucketLocation}" | openssl sha256 -hex -mac HMAC -macopt hexkey:${DateKey} | sed 's/.* //'`
DateRegionServiceKey=`echo -n "s3" | openssl sha256 -hex -mac HMAC -macopt hexkey:${DateRegionKey} | sed 's/.* //'`
SigningKey=`echo -n "aws4_request" | openssl sha256 -hex -mac HMAC -macopt hexkey:${DateRegionServiceKey} | sed 's/.* //'`
# then, once more a HMAC for the signature
signature=`echo -en ${stringToSign} | openssl sha256 -hex -mac HMAC -macopt hexkey:${SigningKey} | sed 's/.* //'`
authoriz="Authorization: AWS4-HMAC-SHA256 Credential=${s3AccessKey}/${yyyymmdd}/${bucketLocation}/s3/aws4_request, SignedHeaders=content-length;host;x-amz-content-sha256;x-amz-date, Signature=${signature}"
curl -v -X PUT -T "${fileName}" \
-H "Host: ${endpoint}" \
-H "Content-Length: ${contentLength}" \
-H "x-amz-date: ${isoDate}" \
-H "x-amz-content-sha256: ${contentHash}" \
-H "${authoriz}" \
http://${endpoint}/${s3Bucket}/${fileName}
我必须承认,对于像我这样有点涉及密码学的人来说,亚马逊签名方案值得许多批评:
- 签署的信息有很多冗余,
- 5 步 HMAC 级联几乎颠倒了密钥种子和数据之间的语义,其中 1 步足以正确使用和相同的安全性
- 密钥的最后 12 个字符在这里是无用的,因为 SHA256 HMAC 的有效密钥长度是 ... 256 位,因此是 32 个字节,其中前 4 个始终以“AWS4”开头,只是没有目的。
- 整体 AWS S3 API 重新发明了 S/MIME 有效负载可以完成的标准
向批评者道歉,我无法抗拒。但是承认:它运行可靠,对许多公司有用,并且是具有丰富 API 的有趣服务。