Google Cloud signed URL with PHP - php

My needs are simple... One would think. I'm just trying to create a signed URL with a PHP script to prevent download abuse of a file hosted on Google Cloud Storage. I've found several examples, none that worked. This one came the closest:
<?php
$filepath = 'my file.zip'; // do not include the bucket name, no slash in the beginning
$bucket = 'mybucket';
$key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // key
$secret = 'xxxxxxxxxxxxxxxxxxxxxxx'; // secret
function getSignedGoogleCloudStorageUrl($filepath, $bucket, $secret, $key, $duration = 300)
{
$expires = new \DateTime('+ ' . $duration . ' seconds');
$seconds = $expires->format('U');
$objectPieces = explode('/', $filepath);
array_walk($objectPieces, function (&$piece) {
$piece = rawurlencode($piece);
});
$objectName = implode('/', $objectPieces);
$resource = sprintf(
'/%s/%s',
$bucket,
$objectName
);
$headers = []; // you may add any headers needed here
$toBeSignedArray = [
'GET',
'', // contentMd5, can be left blank
'', // contentType, can be left blank
$seconds,
implode("\n", $headers) . $resource,
];
$toBeSignedString = implode("\n", $toBeSignedArray);
$encodedSignature = urlencode(base64_encode(hash_hmac('sha1', $toBeSignedString, $secret, true)));
$query = [];
$query[] = 'GoogleAccessId=' . $key;
$query[] = 'Expires=' . $seconds;
$query[] = 'Signature=' . $encodedSignature;
return "https://storage.googleapis.com/{$bucket}/{$filepath}?" . implode('&', $query);
}
echo getSignedGoogleCloudStorageUrl($filepath, $bucket, $secret, $key);
?>
However, it always produces the same result after the 1st use until I clear the cache on the web server.
Any help or other working examples would be great. Thanks.

Related

OAuth in simple php without class

i want to generate the signature this code gives me using simple php with no oauth class:
$oauth = new OAuth($my_key, $my_secret);
$bodyHash = base64_encode(sha1($body_content, true)); //contains the body
$sig = $oauth->generateSignature('GET', $url, Array("oauth_body_hash" => $bodyHash));
what i have done so far is this:
$bodyHash = base64_encode(sha1($xml, true));
$result_data = array(
'oauth_body_hash' => $bodyHash
);
$result_data_keys = array_keys($result_data);
sort($result_data_keys);
$launch_params = array();
foreach ($result_data_keys as $key) {
array_push($launch_params, $key . "=" . rawurlencode($result_data[$key]));
}
$base_string = "POST&" . urlencode($sUrl) . "&" . rawurlencode(implode("&", $launch_params));
$signature = base64_encode(hash_hmac("sha1", $base_string, $my_secret, true));
but im not getting the same signature!
this is the simplified version of the problem i have posted earlier here: Building a body signed oauth xml request for LTI Outcomes service
any idea what im doing wrong?

Rewrite an HTTP request for Vuforia

Can anybody help me to rewrite the following request in curl or anything similar which is available in php 5.6? I'm new with http request in PHP and I'm not able to use the HttpRequest class cause it can't be found on the server. Other suggestions are welcome too. Maybe there is already a library?
$path = "content/images/calendarmotiv/";
$fail = true;
$tmp = $_FILES['imagetarget']['tmp_name'];
$name = basename($_FILES['imagetarget']['name']);
if(move_uploaded_file($tmp, $path.$name))
{
// http request body
$now = new DateTime('NOW');
$body = json_encode(array(
"name" => $name,
"width" => 1024.0,
"image_url" => base64_encode($path.$name),
"active_flag" => 1,
"application_metadata_url" => base64_encode($_POST["metadata"]))
);
$http_verb = "POST";
$content_md5 = md5($body);
$content_type = "application/json";
$date = str_replace("+0000", "GMT", $now->format(DateTime::RFC1123));
$request_path = "<a href='https://vws.vuforia.com/targets'> https://vws.vuforia.com/targets</a>";
// auth string for header
$string_to_sign = $http_verb . "\n" . $content_md5 . "\n" . $content_type . "\n" . $date . "\n" . $request_path;
$secret_key = "mykey";
$signature = hash_hmac("sha1", $string_to_sign, $secret_key);
$authstring = "VWS " . $secret_key . ":" . $signature;
// the request
$request = new HttpRequest($request_path, HttpRequest::METH_POST);
$request->setContentType($content_type);
$request->setBody($body);
$request->addHeaders(array(
"Date" => $date,
"Authorization" => $authstring));
$request->send();
echo $request->getRequestMessage();
echo $request->getResponseMessage();
}
I've created a Vuforia client class in PHP for basic operations with Vuforia target database:
https://github.com/FionNoir/VuforiaClient

Sinch voice callback request signin

I'm making app-to-phone app using Sinch.
I'm successfully providing the callback for ICE and ACE event without request signin.
But now, when I try to sign the request to make it more secure, it always fails to meet the requirement
I get my code from here : Trouble with authorization request
It works when I try to use data and application key from https://www.sinch.com/using-rest/#callbackrequestsigning
But when I try to use real data, it always fail.
$key = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxx";
$secret = 'my-app-secret';
$body = $request->getContent();
$timestamp = $request->input('timestamp');
$path = '/sinch/callback/' . $callbackType;
$content_type = "application/json";
$canonicalized_headers = "x-timestamp:" . $timestamp;
$content_md5 = base64_encode( md5( utf8_encode($body), true ));
$string_to_sign =
"POST\n".
$content_md5."\n".
$content_type."\n".
$canonicalized_headers."\n".
$path;
$signature = base64_encode(hash_hmac("sha256", utf8_encode($string_to_sign), base64_decode($secret), true));
$authorizationHeader = $request->header('Authorization');
$sinchAuthorizationHeader = str_replace('Application ', '', $authorizationHeader);
$sinchAuthorizationHeader = explode(':', $sinchAuthorizationHeader);
if($sinchAuthorizationHeader[0] == $key && $signature == $sinchAuthorizationHeader[1]) {
return true;
}
return false;
Any help would be appreciated.

AWS Multipart upload SDK not working

I need Help on AWS multi-part Upload using PHP 5.3
I am using
1. WAMP Server.
2. PHP 5.3
3. OS: Windows 8
I am trying to upload a Big file to My Amazon S3 bucket.
And tried in many ways. I followed the code procedure from
http://docs.aws.amazon.com/AmazonS3/latest/dev/LLuploadFilePHP.html
I wrote PHP code but I don't know what mistake I did.
My Code:
<?php
require_once './sdk/sdk.class.php';
use \AmazonS3;
$ufile = $_FILES['ufile'];
$filepath = $ufile['tmp_name'];
$bucket = '**My_bkt**';
var_dump($ufile);
print $keyname = \date("Y") . "/" . \date("F") . "/" . \date("d") . "/" . $ufile['name'] . "<BR />";
$api_key = "***my_api_key***";
$secret_key = "***my_secret_key***";
// Define a megabyte.
define('MB', 1048576);
// Instantiate the class
//$s3 = new AmazonS3();
$s3 = new AmazonS3(array(
'key' => $api_key,
'secret' => $secret_key,
));
// 1. Initiate a new multipart upload.
/* #var $response type */
$response = $s3->initiate_multipart_upload($bucket, $keyname);
// Get the Upload ID.
$upload_id = (string) $response->body->UploadId;
// 2. Upload parts.
// Get part list for a given input file and given part size.
// Returns an associative array.
$parts = $s3->get_multipart_counts(filesize($filepath), 3 * MB);
foreach ($parts as $i => $part) {
// Upload part and save response in an array.
$responses[] = $s3->upload_part($bucket, $keyname, $upload_id, array(
'fileUpload' => $filepath,
'partNumber' => ($i + 1),
'seekTo' => (integer) $part['seekTo'],
'length' => (integer) $part['length'],
)
);
}
// 3. Complete multipart upload. We need all part numbers and ETag values.
$parts = $s3->list_parts($bucket, $keyname, $upload_id);
$response = $s3->complete_multipart_upload($bucket, $keyname, $upload_id, $parts);
var_dump($response);
Please help me.
I know you're using the older SDK 1 here, so my answer doesn't apply directly to what you've posted. That said, SDK 1.x is no longer being updated and SDK 2.x is what all new work should be using (as per the AWS SDK for PHP team).
If you do update your project to use SDK 2, then take a look at S3Client::upload(). It should greatly simplify what you're trying to do here.
I have Updated My SDK and Changed My Code like bellow,
////////////////// AWS Code Begin ////////////////////
/////////////////////////// Step 1 /////////////////////////////
$ufile = $_FILES['Filedata'];
$filename = $ufile['tmp_name'];
$filesize = $ufile['size'];
/* * ************ Calculating Number of Parts ******************* */
$number_of_parts = 0;
$r = $filesize % PART; // Remainder
$q = floor($filesize / PART); // Quotient
if ($r != 0) {
$number_of_parts = $q + 1;
} else {
$number_of_parts = $q;
}
$bucket = 'isource123';
$keyname = date("Y") . "/" . date("F") . "/" . date("d") . "/" . $ufile['name'];
///////////////////////////// Step 2 /////////////////////////////
// Create a service builder using a configuration file
$aws = Aws::factory('./aws/Aws/Common/Resources/aws-config.php');
// Get the client from the builder by namespace
$client = $aws->get('S3');
$uploader = \Aws\S3\Model\MultipartUpload\UploadBuilder::newInstance()
->setClient($client)
->setSource($filename)
->setBucket($bucket)
->setKey($keyname)
->setOption('Metadata', array('Foo' => 'Bar'))
->setOption('CacheControl', 'max-age=3600')
->setConcurrency($number_of_parts)
->build();
try {
$uploader->upload();
echo "Upload complete.\n";
} catch (MultipartUploadException $e) {
$uploader->abort();
echo "Upload failed.\n";
}
I updated My SDK to version 2 and it's working fine.

All of a sudden, my Amazon S3 HTTP requests aren't working. Signature Does Not Match error. Help?

My code was working just fine a couple days ago. Then, all of a sudden, BAM: it stopped working. My PUTs stopped going through, with a SignatureDoesNotMatch error. Help?
require_once 'Crypt/HMAC.php';
require_once 'HTTP/Request.php';
function uploadFile($path_to_file, $store_file_as, $bucket, $debugmode = false) {
$S3_URL = "http://s3.amazonaws.com/";
$filePath = $path_to_file;
$contentType = 'audio/mpeg';
$keyId = 'THISISMYKEY, YES I DOUBLE CHECKED IT';
$secretKey = 'THIS IS MYSECRET, YES I DOUBLED CHECKED IT';
$key = $store_file_as;
$resource = $bucket . "/" . $key;
$acl = "public-read";
$verb = "PUT";
$httpDate = gmdate("D, d M Y H:i:s T");
$stringToSign = "PUT\n\naudio/mpeg\n$httpDate\nx-amz-acl:$acl\n/$resource";
$hasher =& new Crypt_HMAC($secretKey, "sha1");
$str = $hasher->hash($stringToSign);
$raw = '';
for ($i=0; $i < strlen($str); $i+=2) {
$raw .= chr(hexdec(substr($str, $i, 2)));
}
$signature = base64_encode($raw);
$req =& new HTTP_Request($S3_URL . $resource);
$req->setMethod('PUT');
$req->addHeader("content-type", $contentType);
$req->addHeader("Date", $httpDate);
$req->addHeader("x-amz-acl", $acl);
$req->addHeader("Authorization", "AWS " . $keyId . ":" . $signature);
$req->setBody(file_get_contents($filePath));
$req->sendRequest();
echo $req->getResponseBody();
}
Run your signature against the Amazon S3 JavaScript signature tester.
If the two signatures do not match, you know something is wrong with the keys or signing procedure.
If the two match, your keys and signing process are correct and the problem is somewhere else.
The JS tester is invaluable for troubleshooting signature generation problems.

Categories