The request signature we calculated does not match AMAZON AWS PHP - php

I have looked at most samples of code based on this issue on stack overflow but I still cant get the request to work. I keep getting this error:
<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.
Here is my code:
$access_key = "ACCESS_KEY";
$associateTag = "AOSSOCIATE_TAG";
$secretkey = "SECRET_KEY";
$keywords = "harry%20potter";
$timestamp = gmdate("Y-m-d\TH:i:s\Z");
$operation = "AWSECommerceService";
function createSignature($operation,$timestamp,$secretkey){
$the_string=$operation.$timestamp;
return base64_encode(hash_hmac("sha256",$the_string,$secretkey,true));
}
$signature = createSignature ($operation,$timestamp,$secretkey);
$APIcall =
"http://ecs.amazonaws.com/onca/xml?".
"AWSAccessKeyId=$access_key&".
"AssociateTag=$associateTag&".
"BrowseNode=1000&".
"ItemPage=1&".
"Keywords=$keywords&".
"Operation=ItemSearch&".
"ResponseGroup=Medium&".
"SearchIndex=Books&".
"Service=AWSECommerceService&".
"Timestamp=$timestamp&".
"Version=2011-08-01&".
"Signature=$signature";
$response = simplexml_load_file($APIcall);
Can anyone help?

I had this issue long time and it worked for me with this code :
require_once 'Crypt/HMAC.php';
require_once 'HTTP/Request.php';
$keyId = "adasdasd";
$secretKey = "asdasdasdasdasd+";
function hex2b64($str) {
$raw = '';
for ($i=0; $i < strlen($str); $i+=2) {
$raw .= chr(hexdec(substr($str, $i, 2)));
}
return base64_encode($raw);
}
function constructSig($str) {
global $secretKey;
$str = utf8_encode($str);
$secretKey = utf8_encode($secretKey);
$hasher =& new Crypt_HMAC($secretKey, "sha1");
$signature = hex2b64($hasher->hash($str));
return ($signature);
}
$expire = time()+1000;
$resource = "/demo/files/clouds.jpg";
$date = gmdate("D, d M Y G:i:s T");
$mime = "image/jpeg";
$stringToSign = "PUT\n";
$stringToSign .= "\n";
$stringToSign .= "$mime\n";
$stringToSign .= "$date\n";
$stringToSign .= $resource;
$req =& new HTTP_Request("http://nameofmine.s3.amazonaws.com/files/clouds.jpg");
$req->setMethod("PUT");
$req->addHeader("Date",$date);
$req->addHeader("Authorization", "AWS " . $keyId . ":" . constructSig($stringToSign));
$req->addHeader("Content-Type",$mime);
$req->setBody(file_get_contents($file_path));
$req->sendRequest();
$responseCode = $req->getResponseCode();
$responseString = $req->getResponseBody();
echo $responseCode;
As you see you have to use Crypto, HTTP pear plugins

The function seems ok (it is the same as the one used in amazon AWS SDK) so make sure that there is no whitespace in front or after the copied key.

When I typed in my credentials by hand, I got the same error a couple of times.
Then I tried Console for Windows so I could copy/paste my credentials. This removed the error message. Either I sucked at typing, or sucked at reading.
Long story short: Don't type by hand, copy and past credentials to avoid typos.
EDIT:
My problem was when trying to add my credentials via EB CLIx3.

Related

How to perform HMAC-SHA1 with Base64 Encode?

I'm trying to setup an app to sign with my URLs so they may authenticate but I can't seem to figure out how to replicate the code that I'm trying from the following page: https://help.sendowl.com/help/signed-urls#example
order_id=12345&buyer_name=Test+Man&buyer_email=test%40test.com&product_id=123&signature=QpIEZjEmEMZV%2FHYtinoOj5bqAFw%3D
buyer_email=test#test.com&buyer_name=Test Man&order_id=12345&product_id=123
buyer_email=test#test.com&buyer_name=Test Man&order_id=12345&product_id=123&secret=t0ps3cr3t
publicStr&t0ps3cr3t
This is the steps:
First order the parameters (removing the signature) and unescape
them:
Next append your Signing secret:
Generate the key to sign with:
Perform the HMAC-SHA1 digest with Base 64 encode: QpIEZjEmEMZV/HYtinoOj5bqAFw=
The following is what I tried but end up not getting the same result:
$signKey = "t0ps3cr3t";
$signData = "buyer_email=test#test.com&buyer_name=Test Man&order_id=12345&product_id=123&secret=t0ps3cr3t";
$passData = hash_hmac("sha1", $signData, base64_decode(strtr($signKey)), true);
$passData = base64_encode($passData);
echo $passData;
I keep getting x8NXmAmkNBPYCXwtj65mdVJ8lPc=
I was able to replicate with the following: took me a bit to figure out something so simple.. been coding for 11 hours straight.
Thanks.
$data = "buyer_email=test#test.com&buyer_name=Test Man&order_id=12345&product_id=123&secret=t0ps3cr3t";
$key = "publicStr&t0ps3cr3t";
$pass1 = hash_hmac('sha1', $data, $key, true);
$pass = base64_encode($pass1);
echo $pass;
$pass will return "QpIEZjEmEMZV/HYtinoOj5bqAFw=", the correct value.
$current_timestamp = Carbon::now()->timestamp;
$signstring = "z001-line-anime-gif." . $current_timestamp . ".aaaabbbbccccdddd";
$secret = 'STG-7f*(:hsM-1_eQ_ZD175QgEoJhI$:oR.zEQ<z';
$sig = hash_hmac('sha1', $signstring, $secret);
$signature = hex2bin($sig);
$signature = base64_encode($signature);
return $signature;

Signature does not match in Amazon Web Services

I am writing a PHP code for AMAZON WEB SERVICES. This is my code.
<?php
function amazonEncode($text) {
$encodedText = "";
$j = strlen($text);
for ($i = 0; $i < $j; $i++) {
$c = substr($text, $i, 1);
if (!preg_match("/[A-Za-z0-9-_.~]/", $c)) {
$encodedText .= sprintf("%%%02X", ord($c));
} else {
$encodedText .= $c;
}
}
return $encodedText;
}
function amazonSign($url, $secretAccessKey) {
// 0. Append Timestamp parameter
$url .= "&Timestamp=" . gmdate("Y-m-dTH:i:sZ");
// 1a. Sort the UTF-8 query string components by parameter name
$urlParts = parse_url($url);
parse_str($urlParts["query"], $queryVars);
ksort($queryVars);
// 1b. URL encode the parameter name and values
$encodedVars = array();
foreach ($queryVars as $key => $value) {
$encodedVars[amazonEncode($key)] = amazonEncode($value);
}
// 1c. 1d. Reconstruct encoded query
$encodedQueryVars = array();
foreach ($encodedVars as $key => $value) {
$encodedQueryVars[] = $key . "=" . $value;
}
$encodedQuery = implode("&", $encodedQueryVars);
// 2. Create the string to sign
$stringToSign = "GET";
$stringToSign .= "n" . strtolower($urlParts["host"]);
$stringToSign .= "n" . $urlParts["path"];
$stringToSign .= "n" . $encodedQuery;
// 3. Calculate an RFC 2104-compliant HMAC with the string you just created,
// your Secret Access Key as the key, and SHA256 as the hash algorithm.
if (function_exists("hash_hmac")) {
$hmac = hash_hmac("sha256", $stringToSign, $secretAccessKey, TRUE);
} elseif (function_exists("mhash")) {
$hmac = mhash(MHASH_SHA256, $stringToSign, $secretAccessKey);
} else {
die("No hash function available!");
}
// 4. Convert the resulting value to base64
$hmacBase64 = base64_encode($hmac);
// 5. Use the resulting value as the value of the Signature request parameter
// (URL encoded as per step 1b)
$url .= "&Signature=" . amazonEncode($hmacBase64);
echo $url;
}
$url = 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=something&AssociateTag=something&Operation=ItemSearch&Keywords=Mustang&SearchIndex=Blended&Condition=Collectible&Timestamp=2016-08-08T12%3A00%3A00Z&Version=2013-08-01';
$SECRET_KEY = 'my_secret_key';
$url = amazonSign($url, $SECRET_KEY);
?>
This code returns me a URL. I use that URL inside my browser so that I can get my search results but using that URL gives me this error.
SignatureDoesNotMatchThe 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.
I am using these as AWSAccessKeyId and SECRET_KEY.
It's probably $stringToSign .= "n" should be $stringToSign .= "\n" but this might not be the only problem. If you use the official PHP SDK from Amazon instead of relying on custom scripts you'll have less issues.
The error you are seeing is usually a mistyped Access Key or Secret Access Key.
or the issue may be non-UTF-8 encoded string. Once i UTF-8 encoded it, the error will disappeared.
or if you sending a metadata with an empty value,than it will not work.
or if you not providing the Content-Length parameter than also such kind of issue can happen.

PHP, Dropbox API, OAuth signature and Non-latin symbols

I have the PHP application integrated with Dropbox API. It worked good but since some time ago it stopped to work with non-latin symbols.
For example, if i try to create a dropbox folder with the API and use Cyrillic letters in folder name then API requests fail with error {"error": "Unauthorized"}
I have the PHP function
function createOAuthSignature($apiurl, $params, $oauth_secret, $oauth_token_secret, $method='GET'){
$urlencoded_apiurl = urlencode($apiurl);
$urlencoded_params = urlencode($params);
$basestring = $method .'&'.$urlencoded_apiurl.'&'.$urlencoded_params;
$oauth_signature = base64_encode(hash_hmac('sha1', $basestring, $oauth_secret.'&'.$oauth_token_secret, true));
$oauth_signature = urlencode($oauth_signature);
return $oauth_signature;
}
And the calling code is
$fullname = $parent . $foldername;
$fullnameEnc = rawurlencode($fullname);
$apiurl = $this->api_url .'fileops/create_folder/';
$params = 'oauth_consumer_key='.$this->oauth_consumer_key
.'&oauth_nonce='. $this->createNonce()
.'&oauth_signature_method=HMAC-SHA1'
.'&oauth_timestamp='. time()
.'&oauth_token='.$oauth_token
.'&oauth_version=1.0'
.'&path='. $fullnameEnc
.'&root=dropbox';
$oauth_signature = $this->createOAuthSignature($apiurl, $params, $this->oauth_secret, $oauth_token_secret);
$params .= '&oauth_signature='.$oauth_signature;
$action = $apiurl .'?'. $params;
$s = $this->curl->get($action);
What can be the problem there? I presume it is related to signature generating. But what is wrong there? This code worked fine just couple weeks ago.
Thanks
As Greg mentioned in a comment above, we're investigating, but if you want to switch to PLAINTEXT signing, it's quite easy. Change createOAuthSignature to just do this:
function createOAuthSignature($apiurl, $params, $oauth_secret, $oauth_token_secret, $method='GET'){
return urlencode($oauth_secret.'&'.$oauth_token_secret);
}
And in the calling code, change the signature method to PLAINTEXT:
$params = ...
.'&oauth_signature_method=PLAINTEXT'
...

Getting error in Amazon product API sample code (PHP)

I downloaded Product Advertising PHP Soap Library and was going through the sample codes. I configured the value of 'AWS_API_KEY', 'AWS_API_SECRET_KEY', 'AWS_ASSOCIATE_TAG', 'AWS_ANOTHER_ASSOCIATE_TAG' in sampleSettings.php file. I'm getting the below mentioned error in my browser while trying to access 'sampleItemSearch.php'.
SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl' : Start tag expected, '<' not found
I tried to take help help from Link: https://forums.aws.amazon.com/thread.jspa?messageID=270273 but it did not work.
Note: I have tried to run the below url in browser and got the following output:
$request="http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&AssociateTag=ASSOCIATETAG01-20&AWSAccessKeyId=MY_ACCESS_KEY_ID&Operation=ItemSearch&Version=2011-08-01&SearchIndex=Books&Keywords=harry%20potter&Timestamp=2013-04-10T12%3A44%3A42.000Z&Signature=ASasd5645AdSG878asdHsaHJ9YTefl1F6i0%3D";
Please suggest what I should do.
I solved it at last. Below mentioned code is working fine.
AWSAccessKeyId = "*******************";
$SecretAccessKey = "******************************";
$AssociateTag = "***************";
$ItemId = '****'; //10 or 13 digit isbn
$Timestamp = gmdate("Y-m-d\TH:i:s\Z");
$Timestamp = str_replace(":", "%3A", $Timestamp);
$ResponseGroup = "ItemAttributes,Images";
$ResponseGroup = str_replace(",", "%2C", $ResponseGroup);
$String = "AWSAccessKeyId=$AWSAccessKeyId&AssociateTag=$AssociateTag&IdType=ISBN&ItemId=$ItemId&Operation=ItemLookup&ResponseGroup=$ResponseGroup&SearchIndex=Books&Service=AWSECommerceService&Timestamp=$Timestamp&Version=2011-08-01";
$String = str_replace("\n", "", $String);
$Prepend = "GET\nwebservices.amazon.com\n/onca/xml\n";
$PrependString = $Prepend . $String;
$Signature = base64_encode(hash_hmac("sha256", $PrependString, $SecretAccessKey, True));
$Signature = str_replace("+", "%2B", $Signature);
$Signature = str_replace("=", "%3D", $Signature);
$BaseUrl = "http://webservices.amazon.com/onca/xml?";
$SignedRequest = $BaseUrl . $String . "&Signature=" . $Signature;
$XML = simplexml_load_file($SignedRequest);
print_r($xml); // output

Max CDN purge through API

I am trying to purge a file through the MaxCDN API but it's not working. Here's the code I'm using. The print_r doesn't return any result.
function purge() {
date_default_timezone_set('America/Los_Angeles');
$date = date('c');
$apiid = 'myapiid';
$apikey = 'myapi';
$auth_key = hash('sha256', $date.':'.$apikey.':purge');
$url = 'http://softsailor.alexdumitru.netdna-cdn.com/wp-content/themes/ss3/includes/sprite.jpg';
if (!class_exists('IXR_Client')) {
require_once (ABSPATH . WPINC . '/class-IXR.php');
}
$client = new IXR_Client('api.netdna.com','/xmlrpc/cache',80);
$client->timeout = 30;
$client->query('cache.purge', $apiid, $auth_string, $date, $url);
print_r($client->getResponse());
}
I turned debug on and I'm getting the following error
Something went wrong - -32300 : transport error - HTTP status code was not 200
Hey Alex. I work at MaxCDN and here is a code example that I took from our Wiki:
<?php
date_default_timezone_set('America/Los_Angeles');
include("lib/xmlrpc.inc");
$cur = date('c');
$apiKey = 'api-key';
$apiUserId = 'api-user-id';
$namespace = 'cache';
$method = 'purge';
$authString = hash('sha256', $cur . ':' . $apiKey . ':' . $method);
// this is the url to purge
$url= 'http://static.jdorfman.netdna-cdn.com/static/images/frugal-it-logo.png';
$f=new xmlrpcmsg("$namespace.$method", array(php_xmlrpc_encode($apiUserId),
php_xmlrpc_encode($authString), php_xmlrpc_encode($cur),
php_xmlrpc_encode($url)));
$c=new xmlrpc_client("/xmlrpc/cache", "api.netdna.com", 80,'http11');
$r=&$c->send($f);
print_r($r);
?>
If you have any other questions or concerns feel free to get in contact with me: jdorfman at maxcdn dot com
jdorfman's example dumps the entire raw response but if you are like me you want to get it into data objects using php
Here are some helpful tips:
$r->serialize() to access just the raw XML response
to convert to JSON use this:
$xml = simplexml_load_string($r->serialize());
echo json_encode($xml);

Categories