2016-06-21 2 views
1

Im, пишущий запрос API AWS, чтобы перечислить пользователей в службе IAM AWS. И я получаю сообщение об ошибке.AWS API GET Запрос на получение ответа «SignatureDoesNotMatch»

<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, если он может поделиться им, поэтому я бросаю глаз и сравниваю и надеюсь, что смогу найти ошибку. Благодаря

+0

Любая причина, по которой вы не используете предоставленный для вас AWS SDK для PHP? https://aws.amazon.com/sdk-for-php/ –

+0

@MattHouser Меня попросили сделать это по этому пути – Standej

ответ

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

Ну, три вопроса ...

  • hash_hmac() принимает ключ в качестве третьего аргумента, а не логическое, а

  • вы не должны быть вычисления здесь есть hash_hmac(), и

  • вы хотите его в шестнадцатеричном виде, не бинарные, поэтому не проходите True.

Вы ищете только hash().

$hashedcanon = hash("sha256", $canonicalrequest); 

Заметьте, я не говорю, hash_hmac() не нужен в другом месте - только не на этой линии.

+0

Спасибо, Майкл, ты был прав. Это была одна из проблем, которые у меня были. Я исправляю то, что вы сказали мне, и канонический хеш был исправлен, но ошибка подписи осталась. Затем я открыл SDK-файлы и посмотрел в их коде, как они хэш-подпись, и это сработало. Я под вашим ответом напишу свой рабочий код только для других людей, если кому-то это понадобится. – Standej

0

Привет, ребята, я отправлю сейчас исправленный и рабочий код, только если кому-то это понадобится.

<?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>'; 

?> 
Смежные вопросы