We have a large number of videos/audo/media hosted on a custom domain on S3 and have created a set of functions in order to sign the URLs and allow them to be both streamable and downloadable. The problem is that the signed URL of course never works. The error is:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
Of course if we take the bytecode returned from this page and input it into the Amazon S3 Signature Tester and grab the bytecode from there it works just fine. Even if the string to sign from our function as well as the decoded byte code in the Signature Tester are identical, it never works.
It's called via a small block of PHP code:
$headers = createS3parameters($expiry, $file_type);
$request = preg_replace("/^.*?:\/\/.*\//", "/", $bucketurl);
$signature = signRequest($request, $expiry, $s3secret, $headers, "GET", $file_type);
$signed_request = "$bucketurl?AWSAccessKeyId=$s3key&Expires=$expiry&$headers&Signature=$signature";
This is the function which actually signs it.
function signRequest($request, $expiration, $s3secret, $headers = '', $type = 'GET', $content_type = 'default')
{
if ($expiration == 0 || $expiration == null)
{
$expiration = time() + 315576000; // 10 years (never)
}
if (strcmp($content_type, 'default') == 0)
{
$content_type = "";
}
// S3 tester spits out this format
/*$string = "$type\n".
"\n\n".
"$expiration\n".
"/mybucket$request?$headers";*/
$string = "$type\n".
"\n".
"$content_type\n".
"$expiration\n".
"$headers\n".
"$request";
// must be in UTF8 format
$string = utf8_encode(trim($string));
// encode to binary hash using sha1. require S3 bucket secret key
$hash = hash_hmac("sha1",$string, $s3secret,false);
// sha1 hash must be base64 encoded
$hash = base64_encode($hash);
// base64 encoded sha1 hash must be urlencoded
$signature = rawurlencode($hash);
return $signature;
}
Which then creates a URL such as:
http://mybucket.s3.amazonaws.com/My_Boring_Video.wmv?AWSAccessKeyId=AKIAIEXAMPLE6GA3WYQ&Expires=1344160808&response-content-type=application/force-download&response-expires=1344160808&Signature=OTIxOTI0YjNjMTA1NjMyNmJjYTk0MGE2YWJkMmI5OWQ3MGM2ZGY0MQ%3D%3D
Which unfortunately doesn't work. Is there an obvious problem here I've been staring at far too long to properly figure out?