Skip to content

Instantly share code, notes, and snippets.

@marcofbb
Last active May 6, 2020 21:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcofbb/97c875bb51f2dc9740588f8e550aac77 to your computer and use it in GitHub Desktop.
Save marcofbb/97c875bb51f2dc9740588f8e550aac77 to your computer and use it in GitHub Desktop.
Signed manually url google storage PHP
<?php
/*
DOCS:
https://cloud.google.com/storage/docs/access-control/signed-urls
https://cloud.google.com/storage/docs/access-control/signing-urls-manually
Translate to PHP of code Python: https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/storage/signed_urls/generate_signed_urls.py
*/
function generate_signed_url_google($service_account_file, $bucket_name, $object_name, $subresource = null, $expiration=604800, $http_method='GET', $query_parameters = array(), $headers = array()){
date_default_timezone_set('UTC');
if($expiration > 604800){
echo 'Expiration Time can\'t be longer than 604800 seconds (7 days).';
return;
}
$google_credentials = json_decode(file_get_contents($service_account_file), true);
if(empty($google_credentials)){
echo 'Error credentials.';
return;
}
$escaped_object_name = implode('/', array_map('rawurlencode', explode('/', $object_name)));
$canonical_uri = '/'.$escaped_object_name;
$datetime_now = time();
$request_timestamp = date('Ymd\THis\Z', $datetime_now);
$datestamp = date('Ymd', $datetime_now);
$client_email = $google_credentials['client_email'];
$credential_scope = $datestamp.'/auto/storage/goog4_request';
$credential = $client_email.'/'.$credential_scope;
$host = $bucket_name.'.storage.googleapis.com';
$headers['host'] = $bucket_name.'.storage.googleapis.com';
$canonical_headers = '';
$signed_headers = '';
$ordered_headers = $headers;
ksort($ordered_headers, SORT_STRING);
foreach($ordered_headers as $key => $value){
$key = strtolower($key);
$value = ($value);
$canonical_headers .= $key.':'.$value."\n";
$signed_headers .= $key.';';
}
$signed_headers = substr($signed_headers, 0, -1);
$query_parameters['X-Goog-Algorithm'] = 'GOOG4-RSA-SHA256';
$query_parameters['X-Goog-Credential'] = $credential;
$query_parameters['X-Goog-Date'] = $request_timestamp;
$query_parameters['X-Goog-Expires'] = $expiration;
$query_parameters['X-Goog-SignedHeaders'] = $signed_headers;
if(!empty($subresource)){
$query_parameters[$subresource] = '';
}
$canonical_query_string = '';
$ordered_query_parameters = $query_parameters;
ksort($ordered_query_parameters, SORT_STRING);
foreach($ordered_query_parameters as $key => $value){
$key = rawurlencode($key);
$value = rawurlencode($value);
$canonical_query_string .= $key.'='.$value.'&';
}
$canonical_query_string = substr($canonical_query_string, 0, -1);
$canonical_request = implode("\n",array($http_method, $canonical_uri, $canonical_query_string, $canonical_headers, $signed_headers, 'UNSIGNED-PAYLOAD'));
$canonical_request_hash = hash('sha256', utf8_encode($canonical_request));
$string_to_sign = implode("\n",array('GOOG4-RSA-SHA256', $request_timestamp, $credential_scope, $canonical_request_hash));
$pkeyid = $google_credentials['private_key'];
if(!openssl_sign($string_to_sign,$signature,$pkeyid,'sha256')) {
$signature = 'none';
} else {
$signature = bin2hex($signature);
}
$scheme_and_host = 'https://'.$host;
$signed_url = $scheme_and_host.$canonical_uri.'?'.$canonical_query_string.'&x-goog-signature='.$signature;
return $signed_url;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment