AWS API GET请求获得响应" SignatureDoesNotMatch"

时间:2016-06-21 15:40:20

标签: php api rest amazon-web-services get

我正在撰写AWS API请求以列出IAM AWS服务上的用户。我收到了错误消息。

<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
  <Error>
    <Type>Sender</Type>
    <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.

The Canonical String for this request should have been
    'GET
    /
    Action=ListUsers&amp;Version=2010-05-08&amp;X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Credential=AKIAIMPILWMPQSH57DNA%2F20160621%2Fus-east-1%2Fiam%2Faws4_request&amp;X-Amz-Date=20160621T142939Z&amp;X-Amz-SignedHeaders=host
    host:iam.amazonaws.com

    host
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'

The String-to-Sign should have been
    'AWS4-HMAC-SHA256
    20160621T142939Z
    20160621/us-east-1/iam/aws4_request
    c47728e278701ccaada8df76488c18449ada2f1b8aab6275a4bc0ada94af3ce2'
      </Message>
    </Error>
  <RequestId>9672bcf2-37bc-11e6-8b2d-6151d0618c53</RequestId>
</ErrorResponse>

正如你可以从我的代码中看到的那样,我的规范字符串与他们在错误响应中写的完全一样但是由于某种原因,当我计算哈希时,我的十六进制值与他们写的不同。 例如,在这个错误响应中,他们写道十六进制值应该是

`c47728e278701ccaada8df76488c18449ada2f1b8aab6275a4bc0ada94af3ce2` 

当我使用函数时 我的代码中的$hashedcanon = hash_hmac("sha256", $canonicalrequest, True);即将获得

`57fce72007b43c2621712b85e90fd38f0a1f2c7a3e84799fb9f477ed8546f86e`

这是我的代码。

<?php
$AWSAccessKeyId = "<myaccesskey>";
$SecretAccessKey = "<mysecretkey>";
$timestamp = date('Ymd',time()).'T'.date('His',time()).'Z';
$date = date('Ymd',time());
$url = 'https://iam.amazonaws.com';
$method = 'GET';                             
$postfields['Action'] = 'ListUsers';
$postfields['Version'] = '2010-05-08';
$postfields["X-Amz-Algorithm"] = 'AWS4-HMAC-SHA256';
$postfields['X-Amz-Credential'] = $AWSAccessKeyId.'/'.$date.'/us-east-1/iam/aws4_request';
$postfields['X-Amz-Date'] = $timestamp;
$postfields['X-Amz-SignedHeaders'] = 'host';

$canonicalized_query = array();
foreach ($postfields as $param => $value) {
    $param = str_replace("%7E", "~", rawurlencode($param));
    $value = str_replace("%7E", "~", rawurlencode($value));
    $canonicalized_query[] = $param . "=" . $value;
}
$canonicalized_query = implode("&", $canonicalized_query);

$canonicalrequest = $method."\n".
                "/\n".
                $canonicalized_query."\n".                    
                "host:iam.amazonaws.com\n".                    
                "\n".
                "host\n".
                "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";

$hashedcanon = hash_hmac("sha256", $canonicalrequest, True);

$string_to_sign = $postfields["X-Amz-Algorithm"]."\n".$timestamp."\n".$date."/us-east-1/iam/aws4_request\n".$hashedcanon;

$signingkey = hash_hmac("sha256",hash_hmac("sha256",hash_hmac("sha256",hash_hmac("sha256","AWS4".$SecretAccessKey,$date),"us-east-1"),"iam"),"aws4_request");

$signature = hash_hmac("sha256", $string_to_sign, $signingkey, True);

$postfields["X-Amz-Signature"] = $signature;              

$canonicalized_query = array();
foreach ($postfields as $param => $value) {
    $param = str_replace("%7E", "~", rawurlencode($param));
    $value = str_replace("%7E", "~", rawurlencode($value));
    $canonicalized_query[] = $param . "=" . $value;
}
$canonicalized_query = implode("&", $canonicalized_query);

$fullurl = $url.'/?'.$canonicalized_query;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $fullurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLINFO_HEADER_OUT, true); // enable tracking
$result = curl_exec($ch);      
$headerSent = curl_getinfo($ch, CURLINFO_HEADER_OUT );

?>`

所以一般来说我假设我计算了字符串的十六进制值,因为我和他们的规范字符串的十六进制值不一样。

当我将规范字符串复制/粘贴到http://hash.online-convert.com/sha256-generator时,我也很有趣。我得到第三个十六进制值(甚至不是我或他们的)。

如果有人需要更多信息我愿意提供它,或者如果任何人有任何API AWS的工作代码,如果它可以共享它,那么我会盯着比较并希望我能找到错误。 感谢

2 个答案:

答案 0 :(得分:2)

panel.setHeight("100%");

好吧,有三个问题......

  • $hashedcanon = hash_hmac("sha256", $canonicalrequest, True); 将键作为第三个参数,而不是布尔值,

  • 你不应该在这里计算HMAC摘要,所以hash_hmac()不是你想要的,

  • 你想要它是十六进制而不是二进制,所以不要通过hash_hmac()

您正在寻找hash()

True

注意,我不是说其他​​地方不需要$hashedcanon = hash("sha256", $canonicalrequest); - 只是不在这一行。

答案 1 :(得分:1)

大家好,如果其他人需要,我会发布现有的固定和正常工作的代码。

<?php

$AWSAccessKeyId = "<my access key>";
$SecretAccessKey = "<my secret key>";
$timestamp = date('Ymd',time()).'T'.date('His',time()).'Z';
$date =  date('Ymd',time());
$url = 'https://iam.amazonaws.com';
$method = 'GET';

$postfields['Action'] = 'ListUsers';
$postfields['Version'] = '2010-05-08';
$postfields["X-Amz-Algorithm"] = 'AWS4-HMAC-SHA256';
$postfields['X-Amz-Credential'] = $AWSAccessKeyId.'/'.$date.'/us-east-1/iam/aws4_request';
$postfields['X-Amz-Date'] = $timestamp;
$postfields['X-Amz-SignedHeaders'] = 'host';

$canonicalized_query = array();
foreach ($postfields as $param => $value) {
    $param = str_replace("%7E", "~", rawurlencode($param));
    $value = str_replace("%7E", "~", rawurlencode($value));
    $canonicalized_query[] = $param . "=" . $value;
}
$canonicalized_query = implode("&", $canonicalized_query);

$canonicalrequest = $method."\n".
                    "/\n".
                    $canonicalized_query."\n".                    
                    "host:iam.amazonaws.com\n".                    
                    "\n".
                    "host\n".
                    "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";

$hasedcanon = hash("sha256",$canonicalrequest, false);                  
$credentialScope =  $date."/us-east-1/iam/aws4_request";
$string_to_sign = "AWS4-HMAC-SHA256\n{$timestamp}\n{$credentialScope}\n{$hasedcanon}";

$dateKey = hash_hmac('sha256',$date,"AWS4{$SecretAccessKey}",true);
$regionKey = hash_hmac('sha256', "us-east-1", $dateKey, true);
$serviceKey = hash_hmac('sha256', "iam", $regionKey, true);
$key = hash_hmac('sha256','aws4_request',$serviceKey,true);

$signature = hash_hmac('sha256', $string_to_sign, $key);

$postfields["X-Amz-Signature"] = $signature;              

$canonicalized_query = array();
foreach ($postfields as $param => $value) {
    $param = str_replace("%7E", "~", rawurlencode($param));
    $value = str_replace("%7E", "~", rawurlencode($value));
    $canonicalized_query[] = $param . "=" . $value;
}
$canonicalized_query = implode("&", $canonicalized_query);

$fullurl = $url.'/?'.$canonicalized_query;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $fullurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLINFO_HEADER_OUT, true); // enable tracking
$xml = curl_exec($ch);      
$headerSent = curl_getinfo($ch, CURLINFO_HEADER_OUT );      

$doc = simplexml_load_string($xml);
echo '<pre>';
print_r($doc);
echo '</pre>';

?>