Bash脚本上传AWS S3:规范请求哈希与AWS生成值不一致问题
问题:Bash脚本上传AWS S3时签名哈希不匹配(Linux环境适配)
使用场景
需编写纯Bash脚本实现AWS S3文件上传,部署到数百台无法安装AWS CLI、s3cmd等工具的Linux系统,已完成Mac平台的zsh版本,适配Linux时遇到签名验证失败问题。
问题详情
脚本生成的CanonicalRequest与AWS端一致,但计算出的canonical_request_hash和AWS StringToSign中要求的哈希值不匹配,触发AWS报错:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
相关代码片段
# Initial Canoncial Request String canonical_request="PUT /$file_name host:$aws_s3_host.s3.amazonaws.com x-amz-content-sha256:$file_sha256 x-amz-date:$now_time host;x-amz-content-sha256;x-amz-date $file_sha256" # THE CANONICAL REQUEST ABOVE IS WHAT AWS PRODUCES. ### # Generate Canonical Request Hash canonical_request_hash=$(echo -n $canonical_request | openssl dgst -sha256) ### # THE CANONICAL REQUEST HASH ABOVE IS DIFFERENT THAN WHAT AWS PRODUCES. # String that will be used to generate AWS Signature string_to_sign="AWS4-HMAC-SHA256 $now_time $now_date/$region/s3/aws4_request $canonical_request_hash"
已尝试方案
- 替换哈希计算命令:
sha256sum、openssl dgst -sha256 - 调整
echo的-n参数(添加/移除) - 将
canonical_request写入文件后再哈希文件
解决办法
问题出在两个关键细节:
1. 变量引用丢失换行符
Bash中直接使用echo -n $canonical_request时,变量内的换行符会被替换为空格,导致实际哈希的内容和原始CanonicalRequest不一致。必须用双引号包裹变量,并使用printf替代echo保证跨平台可靠性:
printf "%s" "$canonical_request"
2. Linux下openssl输出带前缀
Linux环境中openssl dgst -sha256的输出会包含SHA256(stdin)= 前缀,而AWS需要的是纯哈希值,需提取哈希部分。
结合两点,修改后的哈希计算代码:
# 用printf输出原始CanonicalRequest,提取openssl输出的纯哈希值 canonical_request_hash=$(printf "%s" "$canonical_request" | openssl dgst -sha256 | awk '{print $2}')
如果使用sha256sum,同样需要提取纯哈希:
canonical_request_hash=$(printf "%s" "$canonical_request" | sha256sum | awk '{print $1}')
修改后重新运行脚本,canonical_request_hash将和AWS要求的一致,签名验证即可通过。
内容的提问来源于stack exchange,提问作者questionallthings
相关产品推荐
相关产品推荐

