【问题标题】:AWS SignatureDoesNotMatch error but signing code seems valid as well as key pairAWS SignatureDoesNotMatch 错误,但签名代码和密钥对似乎都有效
【发布时间】:2016-03-03 02:55:35
【问题描述】:

感谢您的关注。

我正在尝试编写自己的轻量级 PHP 类来生成 AWS 身份验证标头。据我所知,它运行正常。我已经使用 AWS 文档中提供的示例测试了它的输出:http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html

而且我的代码生成的输出与每个示例完全相同,因此我相当有信心签名生成是正确的。

我还使用 AWS PHP SDK 测试了密钥和秘密,并证明它可以与以下代码一起使用:(密钥显然被混淆了 :))

require 'vendor/autoload.php';
use Aws\S3\S3Client;

$client = S3Client::factory(array(
   'key' => 'xxxxxxxxxxxxxxxxxxxx',
   'secret' => 'ssssssssssssssssssssssssssssssssssssssss',
   'scheme' => 'http'
));

$result = $client->listBuckets();

foreach ($result['Buckets'] as $bucket) {
    // Each Bucket value will contain a Name and CreationDate
    echo "{$bucket['Name']} - {$bucket['CreationDate']}\n";
}

(只是测试所以关键是写在我知道不正确的最佳实践的代码中:),然后切换到 HTTP 以便我可以使用 wireshark 检查输出)

wireshark 输出显示 SDK 中包含的标头与我之前链接的文档中提供的标头不匹配! AWS 文档站点上似乎有很多相互矛盾的文档。

由于我的签名生成代码与示例匹配,我怀疑使用 curl 发送请求时可能有问题?我已经尝试过 POST 和 GET 作为响应没有区别的方法。错误消息中的签名字符串和规范请求都与签名函数产生的匹配。

我的代码 sn-p 是:

printf("URL: $e\n");
if ($ch = curl_init("http://s3-eu-west-1.amazonaws.com".$e)){ // Create curl request object

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $curlHeaders = array();
    foreach ($awsobj->headers as $key => $val){
        $curlHeaders[] = $key.': '.$val;
    }
    $curlHeaders[] = 'Authorization: '.$ah['Authorization'];

    curl_setopt($ch, CURLOPT_HTTPHEADER, $curlHeaders);

    printf("CREQ:\n%s\n---", $awsobj->getCREQ());
    printf("STS:\n%s\n---", $awsobj->getSTS());

    $res = curl_exec($ch);

    var_dump($res);
}

它调用的 URL 是:http://s3-eu-west-1.amazonaws.com/?LocationConstraint=eu-west-1

带有符号的字符串:

AWS4-HMAC-SHA256
Sun, 29 Nov 2015 10:57:02 +0000
20151129/eu-west-1/s3/aws4_request
2b1435293edc751d0d80efc9016433a2635de23bc8c0d2e97d3a54c0cfadd74b

规范请求:

GET
/
LocationConstraint=eu-west-1
date:Sun, 29 Nov 2015 10:57:02 +0000
host:s3-eu-west-1.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

date;host;x-amz-content-sha256
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

(这些末尾没有返回)

来自 S3 的响应是:

<Error><Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>   

<StringToSign>AWS4-HMAC-SHA256
Sun, 29 Nov 2015 10:57:02 +0000
20151129/eu-west-1/s3/aws4_request
2b1435293edc751d0d80efc9016433a2635de23bc8c0d2e97d3a54c0cfadd74b</StringToSign>
<StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 53 75 6e 2c 20 32 39 20 4e 6f 76 20 32 30 31 35 20 31 30 3a 35 37 3a 30 32 20 2b 30 30 30 30 0a 32 30 31 35 31 31 32 39 2f 65 75 2d 77 65 73 74 2d 31 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 32 62 31 34 33 35 32 39 33 65 64 63 37 35 31 64 30 64 38 30 65 66 63 39 30 31 36 34 33 33 61 32 36 33 35 64 65 32 33 62 63 38 63 30 64 32 65 39 37 64 33 61 35 34 63 30 63 66 61 64 64 37 34 62</StringToSignBytes>
<CanonicalRequest>GET
/
LocationConstraint=eu-west-1
date:Sun, 29 Nov 2015 10:57:02 +0000
host:s3-eu-west-1.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

date;host;x-amz-content-sha256
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855</CanonicalRequest>
<CanonicalRequestBytes>47 45 54 0a 2f 0a 4c 6f 63 61 74 69 6f 6e 43 6f 6e 73 74 72 61 69 6e 74 3d 65 75 2d 77 65 73 74 2d 31 0a 64 61 74 65 3a 53 75 6e 2c 20 32 39 20 4e 6f 76 20 32 30 31 35 20 31 30 3a 35 37 3a 30 32 20 2b 30 30 30 30 0a 68 6f 73 74 3a 73 33 2d 65 75 2d 77 65 73 74 2d 31 2e 61 6d 61 7a 6f 6e 61 77 73 2e 63 6f 6d 0a 78 2d 61 6d 7a 2d 63 6f 6e 74 65 6e 74 2d 73 68 61 32 35 36 3a 65 33 62 30 63 34 34 32 39 38 66 63 31 63 31 34 39 61 66 62 66 34 63 38 39 39 36 66 62 39 32 34 32 37 61 65 34 31 65 34 36 34 39 62 39 33 34 63 61 34 39 35 39 39 31 62 37 38 35 32 62 38 35 35 0a 0a 64 61 74 65 3b 68 6f 73 74 3b 78 2d 61 6d 7a 2d 63 6f 6e 74 65 6e 74 2d 73 68 61 32 35 36 0a 65 33 62 30 63 34 34 32 39 38 66 63 31 63 31 34 39 61 66 62 66 34 63 38 39 39 36 66 62 39 32 34 32 37 61 65 34 31 65 34 36 34 39 62 39 33 34 63 61 34 39 35 39 39 31 62 37 38 35 32 62 38 35 35</CanonicalRequestBytes>
<RequestId>6C049EA89D65D27E</RequestId>
<HostId>HSGO1Iz6LIT5jkHHGM/XCI0ElnSDiQseb1CUcg4RxXjb+xplWoVCFbgJoT6CPvpCsoOSIS7m7VI=</HostId>

(修剪掉的访问密钥)

过去几天我一直在谷歌搜索和调整我的代码。我无法发现签名生成有任何问题,因为您可以看到我生成的 STS 和 CREQ 都与 S3 生成的匹配。我的代码通过并匹配上面链接中的所有示例,包括 Authentication 标头凭据。

我怀疑我是

  • 要么缺少 S3 希望我包含的内容(必需的标头,我已经搜索了这些但没有找到,无论有没有 LocationConstraint,输出都相同,如果我将其指向 us-east-1)。
  • 如何处理卷曲
  • 使用了错误类型的身份验证标头(正如我所说,SDK 生成的请求看起来完全不同,但也不符合文档所说的要求)。

根据 Rhythmic Fistman 的建议,我还尝试用 x-amz-date 标头替换 Date 标头,但这并没有解决问题。我的新标题的格式是:

x-amz-date:20151130T143334Z

创建于 2015 年 11 月 30 日 14:33

谢谢

【问题讨论】:

    标签: php amazon-web-services curl amazon-s3


    【解决方案1】:

    我发现了我的错误:/这与 curl 无关,而是与我进行签名的方式有关。

    我一直在通过测试流程每个阶段的输出并将结果与​​亚马逊示例给出的结果进行比较来测试我的代码。这些都通过了,所以我确定我的代码是正确的。

    但是,要签名的字符串的生成需要规范请求的哈希。在我的代码中,我有一个生成规范请求并将其输出的函数,但它也会生成它的哈希并将其存储在对象的公共变量中。我的要签名的字符串生成函数在要签名的字符串的生成中使用此变量。

    现在我的测试代码调用规范请求,测试它的输出是有效的,然后调用字符串签名并测试它的结果是有效的,它无意中导致哈希被创建。

    在我调用 API 的实际代码中,不需要输出实际的规范请求,因此从未创建过哈希,并且要签名的字符串无效。在生成签名后,我在尝试诊断问题时添加的输出被添加到代码的末尾。

    在意识到我的错误后,我刚刚在调用生成签名之前将调用移动到输出规范请求,嘿,它可以工作了!

    啊!

    认为最好在这里解释我的方式的错误,我承认这是我自己的愚蠢错误,如果编写代码能够查看流程的各个阶段,请确保它们不依赖于这些阶段,或者调用曝光方法才能正常工作。

    【讨论】:

    • 可以,但我需要再等 15 个小时才能让我这样做 :)(我最初发布时尝试过).. 可能是因为我的帐户是新帐户?
    【解决方案2】:

    我突然想到了两件事:

    1. 您没有添加 x-amz-date 标头
    2. 您要签名的字符串中的日期格式看起来错误。应该是ISO-8601(例如 20130524T000000Z)

    有一个example S3 calculation here。确保您的实现与测试中的输出匹配!

    【讨论】:

    • 根据 AWS API 文档,您必须提供日期标头或 x-amz-date,如果提供了 x-amz-date,则它应该优先。我已经重复了我的测试,但这次添加 x-amz-date 标头而不是日期并得到完全相同的响应(显然不同的哈希值:))我仍然得到完全相同的错误消息。
    猜你喜欢
    • 2014-04-22
    • 2015-09-10
    • 1970-01-01
    • 2014-12-31
    • 1970-01-01
    • 2020-09-22
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多