错误:DescribeRegions API调用无效(Amazon AWS/EC2 API)

错误:DescribeRegions API调用无效(Amazon AWS/EC2 API),c,api,amazon-web-services,amazon-ec2,libcurl,C,Api,Amazon Web Services,Amazon Ec2,Libcurl,我正在编写一个与AmazonEC2API交互的应用程序,因为我以前从未这样做过,所以我决定从一些简单的东西开始,比如描述区域 我是用C语言编写的,所以没有易于使用的库,所以我不得不用libcurl和libcrypto一起破解它。完全公开,这是我第一次以编程方式与AWS/EC2API交互,所以这可能是一个愚蠢的新手错误 我确实读过stackoverflow;这与人员试图从bash发送请求时没有引用字符串的情况不同。我正在通过curl\u easy\u perform() 在阅读了所有我能找到的文档

我正在编写一个与AmazonEC2API交互的应用程序,因为我以前从未这样做过,所以我决定从一些简单的东西开始,比如描述区域

我是用C语言编写的,所以没有易于使用的库,所以我不得不用libcurl和libcrypto一起破解它。完全公开,这是我第一次以编程方式与AWS/EC2API交互,所以这可能是一个愚蠢的新手错误

我确实读过stackoverflow;这与人员试图从bash发送请求时没有引用字符串的情况不同。我正在通过
curl\u easy\u perform()

在阅读了所有我能找到的文档之后(对于本例,让我将aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

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

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
然后我在上面构造一个签名(我们称之为CCCC)

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

  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字符,表示URL 按照RFC 3986编码(十六进制字符必须大写)和 使用字典字节排序。字典字节排序 是区分大小写的

他们到底要我在这里分类什么

任何帮助都将不胜感激。如果我在这里发布完整的源代码会有帮助吗

他们到底要我在这里分类什么

一组键/值对中的键没有定义的排序顺序,但由于签名算法只能有一个正确的输出,因此根据定义只能有一个正确的输入…而正确的输入是一个字符串,它是通过将键/值对与已排序的键相加而构造的

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

但我认为你的另一个问题是:

继续转义并生成的签名请求

等等。在构建此字符串时,您仅对键和值进行URL编码(转义),而不是分隔符。它应该更像这样:

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

<现在,谜团已经解开了

完整的解决方案是

  • 正如Michael所说,必须对各种键/值对进行排序 按字母顺序排列,AWSAccessKeyId位于操作之前(即 我犯了一个错误)
  • 在构造签名请求时,我对URI进行了=和&编码
  • HMAC_Final根据请求构造您的签名,但不提供空值 终止字符串;由您自己决定SHA256是32 字节长,并将空终止符放在正确的位置
  • 正确答案归于迈克尔

    Action=DescribeRegions&AWSAccessKeyId= ...