1

我正在编写一个与 Amazon EC2 API 交互的应用程序,因为我以前从未这样做过,所以我决定从像 DescribeRegions 这样简单的东西开始。

我在 C 中执行此操作,因此没有易于使用的库,因此我不得不将它与 libcurl 和 libcrypto 一起破解。完全披露,这是我第一次以编程方式与 AWS/EC2 API 交互,所以这很可能是一个愚蠢的新手错误。

我确实阅读了stackoverflow;这与该人试图从 bash 发送请求并且没有引用字符串的问题不同。我通过发送请求curl_easy_perform()

在阅读了我能找到的所有文档之后(对于这个示例,让我将 AAAAAAAAA 替换为我的 AWS 访问密钥,将 BBBBBBB 替换为我的密钥。

我构造了签名请求的参数部分,如下所述:

Action=DescribeRegions&AWSAccessKeyId=AAAAAAAA&SignatureMethod=HmacSHA256&"SignatureVersion=2&Timestamp=2013-09-22T02:12:27Z&Version=2013-08-15

并继续逃避它并生成一个签名请求

GET\n
ec2.amazonaws.com\n
/\n
Action%3DDescribeRegions%26AWSAccessKeyId%AAAAAAAAAAAA%26SignatureMethod%3DHmacSHA256%26SignatureVersion%3D2%26Timestamp%3D2013-09-22T02%3A12%3A27Z&Version=2013-08-15

然后我继续在上面构建一个签名(我们称之为 CCCCCCCC)

并提出一个请求,内容如下:

  https://ec2.amazonaws.com/?Action%3DDescribeRegions%26AWSAccessKeyId%3DAAAAAAAAAAAAA%26SignatureMethod%3DHmacSHA256%26SignatureVersion%3D2%26Timestamp%3D2013-09-22T02%3A12%3A27Z&Version=2013-08-15&Signature=CCCCCCCCCCC

当我发送这个时,我收到以下错误。

<?xml version="1.0" encoding="UTF-8"?>
<Response><Errors><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message></Error></Errors><RequestID>585f8932-d27b-42b3-b20e-453d8c7ee1ef</RequestID></Response>

我使用的签名机制是一个简单的 hmac_sha256;我还尝试了维基百科文章中引用的 hmac_sha256 库,可在此处下载

我已经验证我的签名算法是正确的,现在我只需要假设我正在签名的字符串不正确。

不幸的是,文档(AWS 文档)在这方面不够充分。

例如,它显示

添加查询字符串组件(名称-值对,不包括初始问号 (?) 作为 UTF-8 字符,根据 RFC 3986 进行 URL 编码(十六进制字符必须大写)并使用字典字节顺序排序。字典字节顺序区分大小写。

他们到底要我在这里整理什么?

非常感激任何的帮助。如果我在这里发布完整的源代码会有帮助吗?

4

2 回答 2

2

他们到底要我在这里整理什么?

一组键/值对中的键没有定义的排序顺序,但由于签名算法只能有一个正确的输出,因此根据定义只能有一个正确的输入......并且正确的输入是一个字符串是通过附加键/值对和排序的键来构造的。

在构建要签名的字符串时,您对查询字符串中的键(名称)进行排序。例如,“AWSAccessKeyId”在“SignatureMethod”之前,在“Timestamp”之前,等等。您使用排序的键构建字符串。

但我认为您遇到的另一个问题是:

继续逃避它并生成一个签名请求

...
Action%3DDescribeRegions%26AWSAccessKeyId%AAAAAAAAAAAA ...

等待。在构建此字符串时,您只需对键和值进行 urlencode(转义),而不是分隔符。它应该看起来更像这样:

Action=DescribeRegions&AWSAccessKeyId= ...

请注意,在示例中,您看到的唯一转义类似于时间戳中的转义,其中:变为%3A但查询字符串中的=an&未转义。您需要在构建字符串之前转义键和值,而不是之后。

于 2013-09-22T23:12:54.130 回答
0

感谢迈克尔和我现在看不到的另一个答案,谜团解开了。

完整的解决方案是这个......

  1. 正如迈克尔所说,各种键/值对必须按字母顺序排序,AWSAccessKeyId 位于 Action 之前(这是我犯了一个错误)。
  2. 我在签名请求的构造中对 = 和 & 进行了 URI 编码。
  3. HMAC_Final 按要求构造您的签名,但不会为您提供以空字符结尾的字符串;SHA256 的长度为 32 字节,并将空终止符放在正确的位置取决于您。

正确答案归功于迈克尔!

于 2013-09-23T00:07:22.220 回答