7

我目前正在尝试开发一个应用程序来使用 cURL 和 c++ 将文件上传到 Amazon S3 存储桶。仔细阅读 S3 开发人员指南后,我开始使用 cURL 实现我的应用程序并按照开发人员指南的描述形成标题,经过大量试验和错误以确定创建 S3 签名的最佳方式,我现在面临 501 错误. 收到的标头表明我正在使用的方法未实现。我不确定我错在哪里,但这是我发送给亚马逊的 HTTP 标头:

PUT /test1.txt HTTP/1.1
Accept: */*
Transfer-Encoding: chunked
Content-Type: text/plain
Content-Length: 29
Host: [BucketName].s3.amazonaws.com 
Date: [Date]
Authorization: AWS [Access Key ID]:[Signature] 
Expect: 100-continue

出于安全原因,我截断了存储桶名称、访问密钥 ID 和签名。

我不确定我做错了什么,但我认为错误是由于 Accept 和 Transfer-Encoding 字段而产生的(不太确定)。所以谁能告诉我我做错了什么或者为什么我得到一个 501。

4

3 回答 3

6

您可以执行一个 bash 文件。这是一个示例upload.sh脚本,您可以将其运行为:sh upload.sh yourfile

#!/bin/bash
file=$1
bucket=YOUR_BUCKET
resource="/${bucket}/${file}"
contentType="application/x-itunes-ipa"
dateValue=`date -R`
stringToSign="PUT\n\n${contentType}\n${dateValue}\n${resource}"
s3Key=YOUR_KEY_HERE
s3Secret=YOUR_SECRET
echo "SENDING TO S3"
signature=`echo -en ${stringToSign} | openssl sha1 -hmac ${s3Secret} -binary | base64` 
curl -vv -X PUT -T "${file}" \
 -H "Host: ${bucket}.s3.amazonaws.com" \
 -H "Date: ${dateValue}" \
 -H "Content-Type: ${contentType}" \
 -H "Authorization: AWS ${s3Key}:${signature}" \
 https://${bucket}.s3.amazonaws.com/${file}

更多信息:http ://www.jamesransom.net/?p=58

http://www.jamesransom.net/?p=58

于 2014-10-07T12:53:57.373 回答
6

自从提出问题以来,游戏发生了显着变化,简单的授权标头不再适用,但使用 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 的有趣服务。

于 2019-12-11T22:36:59.283 回答
-6

已解决:在我的代码中缺少文件大小的 CURLOPT,现在一切正常

于 2009-09-30T08:04:39.573 回答