PHP。V4 Amazon S3签名。简单的例子

时间:2022-11-18 23:04:10

I my PHP application i used simple set of functions to upload to amazon S3. My code uses Signature version 2. It all worked fine. But it doesn't work for new regions where signature V2 is not supported.

我的PHP应用程序,我使用简单的函数集上传到amazon S3。我的代码使用了签名版本2。一切都工作得很好。但是,对于不支持签名V2的新区域,它不适用。

I try to implement signature V4 but it looks too complex. I just can not make working example for signature V4.

我尝试实现签名V4,但它看起来太复杂了。我只是无法为签名V4提供工作示例。

There is support of V4 sign in AWS SDK for PHP . But it is too complex for me. I can not use that SDK (because of PHP 5.2 and i can not upgrade it)

在AWS SDK中为PHP提供了V4的支持。但这对我来说太复杂了。我不能使用那个SDK(因为PHP 5.2,我不能升级它)

In my current code i have simple code for V2

在我现在的代码中,我有简单的V2代码。

$stringToSign="PUT\n\n$contentType\n$httpDate\nx-amz-acl:$acl\n";
$stringToSign.="/$resource";
$signature = $this->constructSig($stringToSign);
$req->addHeader("Authorization", "AWS " . $this->accessKeyId . ":" . $signature);

function constructSig($str) {
    $hasher = new Crypt_HMAC($this->secretKey, "sha1");
    $signature = $this->hex2b64($hasher->hash($str));
    return($signature);
}

Is it possible to have such simple constructSigV4 function to create new signature type?

有可能有这样简单的构造函数来创建新的签名类型吗?

Also, i see, it is needed to have bucket region for new type signature. If i don't know bucket region then what to do? Request bucket region each time before doing a request? I have buckets in different regions.

另外,我看到,需要有一个桶区域来进行新的类型签名。如果我不知道水桶区域怎么办?每次请求前请求bucket区域?我有不同区域的桶。

Update.

更新。

Simple example is there https://github.com/chrismeller/awstools/blob/master/aws/signature/v4.php

简单的例子是https://github.com/chrismeller/awstools/blob/master/aws/signature/v4.php。

I seems created the working example. Signature seems passed. I got errors like "Signature doesn't match". I then corrected till this error gone. But now i have other error:

我似乎创建了一个工作示例。签名似乎过去了。我有“签名不匹配”之类的错误。然后我更正,直到这个错误消失。但现在我有另一个错误:

Amazon response is :

亚马逊的反应是:

HTTP/1.1 411 Length Required

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>MissingContentLength</Code><Message>You must provide the Content-Length HTTP header.</Message>

But Content-Length is included in my request

但内容长度包含在我的请求中。

PUT /259001/checkmark-circle.png HTTP/1.1
Host: ******.s3.amazonaws.com
Content-Type: image/png
Content-Length: 2338
x-amz-acl: private
x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
X-AMZ-Date: Tue, 19 Jan 2016 07:33:01 -0500
Date: Tue, 19 Jan 2016 07:33:01 -0500
Authorization: AWS4-HMAC-SHA256 Credential=************/20160119/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-acl;x-amz-content-sha256;x-amz-date,Signature=c2bb290f2d54d31bc95785705530e10e0a8bde4c7b7dd1ef3b11a8fa7d96a57c

what can be wrong? Why it says Content-Length is missed if it is present?

什么是错误的吗?为什么说内容长度被忽略了?

1 个解决方案

#1


2  

See Retrieve bucket's objects without knowing bucket's region with AWS S3 REST API for how to learn the region of any bucket. tl;dr: you can ask any region of S3 to give you the location of a bucket, or you can use information embedded in the error that occurs if the region was wrong.

通过AWS S3 REST API了解如何学习任何bucket的区域,可以看到检索bucket的对象,而不需要了解bucket的区域。您可以请求S3的任何区域给您一个bucket的位置,或者您可以使用嵌入在错误中的信息,如果该区域是错误的。

Sqlbot's Best Practices for AWS, which is a book I haven't actually written (yet?), would tell you that the ideal solution for keeping track of each bucket's location is to canonicalize every S3 URI that you store with the appropriate regional hostname. For a bucket called example in us-west-2, valid URLs include these:

对于AWS来说,Sqlbot的最佳实践是,我还没有实际编写的一本书(然而?),它会告诉您,跟踪每个bucket的位置的理想解决方案是将您存储的每个S3 URI规范化为适当的区域主机名。对于一个在us-west-2中称为示例的bucket,有效的url包括以下内容:

https://example.s3.amazonaws.com/
https://example.s3-us-west-2.amazonaws.com/

Both of these will send requests to the correct region, because the first form *.s3.amazonaws.com uses DNS managed by S3 itself to automatically send requests to the correct regional endpoint, while the second form explicitly includes the regional endpoint in the hostname. Since there are consistent patterns across regions, you can relatively easily extract the correct region from the hostname if you internally store your URLs this way.

这两种方法都将向正确的区域发送请求,因为第一个表单*.s3.amazonaws.com使用S3自己管理的DNS自动将请求发送到正确的区域端点,而第二个表单则显式地包含主机名中的区域端点。由于跨区域的模式是一致的,所以如果您通过这种方式在内部存储url,您可以相对轻松地从主机名提取正确的区域。

N.B. The exception to the above is the us-east-1 region, which expects either s3.amazonaws.com or s3-external-1.amazonaws.com in the hostname, for legacy reasons. Your code will need to handle this case.

上述的例外是美国-东-1地区,由于遗留的原因,该地区的主机名是s3.amazonaws.com或s3-external-1.amazonaws.com。您的代码将需要处理这种情况。

Short of maintaining a configuration table of bucket-to-region mappings, storing S3 object references in this form is probably the best way to handle the region-specific authentication required by Signature Version 4.

缺少维护bucket-to-region映射的配置表,在此表单中存储S3对象引用可能是处理签名版本4所要求的区域特定身份验证的最佳方法。

At first glance, Signature V4 does look substantially more complicated than V2, and indeed, the signing code isn't as compact as what you've shown for V2, but if you managed to get V2 working, I'm confident that you can get V4 working.

乍一看,签名V4确实比V2要复杂得多,实际上,签名代码并不像您在V2中所显示的那样紧凑,但是如果您设法使V2工作,我相信您可以得到V4工作。

There is an official Signature Version 4 Test Suite which you should find very useful -- it gives you several sets of input (request) parameters, the correct end result, and perhaps most importantly, it gives you the results of the intermediate signing steps, so that you can isolate which section of your implementation is not generating the correct values for use in subsequent steps. Almost by definition, any slight error in your implementation of a signing algorithm will generate wildly incorrect results, which makes it difficult to pinpoint what you may be doing wrong. The test suite should definitely help you get your code on track.

有一个官方签名版本4测试套件,你应该找到非常有用的,它给你几套输入(请求)参数,正确的结果,也许最重要的是,它给你的结果中间签约的步骤,这样你就可以隔离部分的实现不是生成正确的值用于后续步骤。几乎从定义上来说,在您的签名算法实现过程中出现的任何微小错误都会产生非常不正确的结果,这使得您很难确定您可能做错了什么。测试套件一定会帮助您在轨道上获得代码。

The notable difference between V2 and V4 is that V4 involves creation of a signing key, which uses your secret key, the service, region, and date, and this signing key is used instead of using the secret key directly when ultimately signing the request.

V2和V4的显著区别在于V4涉及创建签名密钥,它使用您的秘密密钥、服务、区域和日期,而这个签名密钥将在最终签署请求时直接使用密钥。

V4 is, at first glance, a bit intimidating and likely to conjure responses of "it wasn't broken, so why did they fix it?" but V4 introduces security enhancements that make it a much more secure mechanism in general, and -- I'm speculating, here -- provides enhanced security for your credentials within the AWS infrastructure. How AWS has implemented it internally is not public information, but the logical construction of V4 shows that it prevents the individual AWS regions and services from needing to be in possession of your secret key. Within AWS, a given service only needs access to your signing key for a given date, region, and service, in order to authenticate your requests, which means AWS appears to have implemented V4 at least partially with an eye toward an internal application of the Principle of Least Privilege in their own infrastructure... which is commendable.

V4,乍一看,有点吓人,容易联想的反应”这不是坏了,那么为什么他们修理它吗?”但V4介绍安全改进,使其更安全机制一般来说,这里,我猜测,在AWS——为您的凭据提供增强的安全基础设施。AWS如何在内部实现它不是公开信息,但是V4的逻辑构建表明它阻止了单个AWS区域和服务需要拥有您的秘密密钥。在AWS,给定服务只需要访问你的签名密钥对于一个给定的日期,区域,和服务,为了验证你的请求,这意味着AWS似乎V4至少部分着眼于实现最小特权原则的内部应用程序自己的基础设施…这是值得称赞的。

#1


2  

See Retrieve bucket's objects without knowing bucket's region with AWS S3 REST API for how to learn the region of any bucket. tl;dr: you can ask any region of S3 to give you the location of a bucket, or you can use information embedded in the error that occurs if the region was wrong.

通过AWS S3 REST API了解如何学习任何bucket的区域,可以看到检索bucket的对象,而不需要了解bucket的区域。您可以请求S3的任何区域给您一个bucket的位置,或者您可以使用嵌入在错误中的信息,如果该区域是错误的。

Sqlbot's Best Practices for AWS, which is a book I haven't actually written (yet?), would tell you that the ideal solution for keeping track of each bucket's location is to canonicalize every S3 URI that you store with the appropriate regional hostname. For a bucket called example in us-west-2, valid URLs include these:

对于AWS来说,Sqlbot的最佳实践是,我还没有实际编写的一本书(然而?),它会告诉您,跟踪每个bucket的位置的理想解决方案是将您存储的每个S3 URI规范化为适当的区域主机名。对于一个在us-west-2中称为示例的bucket,有效的url包括以下内容:

https://example.s3.amazonaws.com/
https://example.s3-us-west-2.amazonaws.com/

Both of these will send requests to the correct region, because the first form *.s3.amazonaws.com uses DNS managed by S3 itself to automatically send requests to the correct regional endpoint, while the second form explicitly includes the regional endpoint in the hostname. Since there are consistent patterns across regions, you can relatively easily extract the correct region from the hostname if you internally store your URLs this way.

这两种方法都将向正确的区域发送请求,因为第一个表单*.s3.amazonaws.com使用S3自己管理的DNS自动将请求发送到正确的区域端点,而第二个表单则显式地包含主机名中的区域端点。由于跨区域的模式是一致的,所以如果您通过这种方式在内部存储url,您可以相对轻松地从主机名提取正确的区域。

N.B. The exception to the above is the us-east-1 region, which expects either s3.amazonaws.com or s3-external-1.amazonaws.com in the hostname, for legacy reasons. Your code will need to handle this case.

上述的例外是美国-东-1地区,由于遗留的原因,该地区的主机名是s3.amazonaws.com或s3-external-1.amazonaws.com。您的代码将需要处理这种情况。

Short of maintaining a configuration table of bucket-to-region mappings, storing S3 object references in this form is probably the best way to handle the region-specific authentication required by Signature Version 4.

缺少维护bucket-to-region映射的配置表,在此表单中存储S3对象引用可能是处理签名版本4所要求的区域特定身份验证的最佳方法。

At first glance, Signature V4 does look substantially more complicated than V2, and indeed, the signing code isn't as compact as what you've shown for V2, but if you managed to get V2 working, I'm confident that you can get V4 working.

乍一看,签名V4确实比V2要复杂得多,实际上,签名代码并不像您在V2中所显示的那样紧凑,但是如果您设法使V2工作,我相信您可以得到V4工作。

There is an official Signature Version 4 Test Suite which you should find very useful -- it gives you several sets of input (request) parameters, the correct end result, and perhaps most importantly, it gives you the results of the intermediate signing steps, so that you can isolate which section of your implementation is not generating the correct values for use in subsequent steps. Almost by definition, any slight error in your implementation of a signing algorithm will generate wildly incorrect results, which makes it difficult to pinpoint what you may be doing wrong. The test suite should definitely help you get your code on track.

有一个官方签名版本4测试套件,你应该找到非常有用的,它给你几套输入(请求)参数,正确的结果,也许最重要的是,它给你的结果中间签约的步骤,这样你就可以隔离部分的实现不是生成正确的值用于后续步骤。几乎从定义上来说,在您的签名算法实现过程中出现的任何微小错误都会产生非常不正确的结果,这使得您很难确定您可能做错了什么。测试套件一定会帮助您在轨道上获得代码。

The notable difference between V2 and V4 is that V4 involves creation of a signing key, which uses your secret key, the service, region, and date, and this signing key is used instead of using the secret key directly when ultimately signing the request.

V2和V4的显著区别在于V4涉及创建签名密钥,它使用您的秘密密钥、服务、区域和日期,而这个签名密钥将在最终签署请求时直接使用密钥。

V4 is, at first glance, a bit intimidating and likely to conjure responses of "it wasn't broken, so why did they fix it?" but V4 introduces security enhancements that make it a much more secure mechanism in general, and -- I'm speculating, here -- provides enhanced security for your credentials within the AWS infrastructure. How AWS has implemented it internally is not public information, but the logical construction of V4 shows that it prevents the individual AWS regions and services from needing to be in possession of your secret key. Within AWS, a given service only needs access to your signing key for a given date, region, and service, in order to authenticate your requests, which means AWS appears to have implemented V4 at least partially with an eye toward an internal application of the Principle of Least Privilege in their own infrastructure... which is commendable.

V4,乍一看,有点吓人,容易联想的反应”这不是坏了,那么为什么他们修理它吗?”但V4介绍安全改进,使其更安全机制一般来说,这里,我猜测,在AWS——为您的凭据提供增强的安全基础设施。AWS如何在内部实现它不是公开信息,但是V4的逻辑构建表明它阻止了单个AWS区域和服务需要拥有您的秘密密钥。在AWS,给定服务只需要访问你的签名密钥对于一个给定的日期,区域,和服务,为了验证你的请求,这意味着AWS似乎V4至少部分着眼于实现最小特权原则的内部应用程序自己的基础设施…这是值得称赞的。