Skip to content

Instantly share code, notes, and snippets.

@mloureiro
Last active June 19, 2016 11:46
Show Gist options
  • Save mloureiro/14503293c3cb2191e2f6 to your computer and use it in GitHub Desktop.
Save mloureiro/14503293c3cb2191e2f6 to your computer and use it in GitHub Desktop.
Generate a Google Signed URL
<?
/**
* Google Bucket GET file with signed string example
*/
require_once("vendor/autoload.php");
/*
* Helper Methods
*/
function googleBuildConfigurationString($method, $expiration, $file, array $options = [])
{
$allowedMethods = ['GET', 'HEAD', 'PUT', 'DELETE'];
// initialize
$method = strtoupper($method);
$contentType = $options['Content_Type'];
$contentMd5 = $options['Content_MD5']
? base64_encode($options['Content_MD5'])
: '';
$headers = $options['Canonicalized_Extension_Headers']
? $options['Canonicalized_Extension_Headers'] . PHP_EOL
: '';
$file = $file ? $file : $options['Canonicalized_Resource'];
// validate
if(array_search($method, $allowedMethods) === false)
{
throw new RuntimeException("Method '{$method}' is not allowed");
}
if(!$expiration)
{
throw new RuntimeException("An expiration date should be provided.");
}
return <<<TXT
{$method}
{$contentMd5}
{$contentType}
{$expiration}
{$headers}{$file}
TXT;
}
function googleSignString($p12FilePath, $string)
{
$certs = [];
if (!openssl_pkcs12_read(file_get_contents($p12FilePath), $certs, 'notasecret'))
{
echo "Unable to parse the p12 file. OpenSSL error: " . openssl_error_string(); exit();
}
$RSAPrivateKey = openssl_pkey_get_private($certs["pkey"]);
$signed = '';
if(!openssl_sign( $string, $signed, $RSAPrivateKey, 'sha256' ))
{
error_log( 'openssl_sign failed!' );
$signed = 'failed';
}
else
{
$signed = base64_encode($signed);
}
return $signed;
}
function googleBuildSignedUrl($serviceEmail, $file, $expiration, $signature)
{
return "http://storage.googleapis.com{$file}"
. "?GoogleAccessId={$serviceEmail}"
. "&Expires={$expiration}"
. "&Signature=" . urlencode($signature);
}
/*
* Initialization
*/
$serviceEmail = '<service-email>';
$p12FilePath = 'keys/google.certificate.p12';
$expiration = (new DateTime())->modify('+3hours')->getTimestamp();
$bucket = 'example';
$fileToGet = 'video.mp4';
/*
* Building!
*/
$file = "/{$bucket}/{$fileToGet}";
$string = googleBuildConfigurationString('GET', $expiration, $file);
$signedString = googleSignString($p12FilePath, $string);
$signedUrl = googleBuildSignedUrl($serviceEmail, $file, $expiration, $signedString);
?>
<html>
<body>
<style>pre {background: #eee;}</style>
<h2>String</h2>
<pre><?= $string ?></pre>
<br>
<h2>Final Url</h2>
<pre><?= $signedUrl ?></pre>
<br>
<video controls>
<source src="<?= $signedUrl ?>" type="video/mp4">
</video>
</body>
</html>
@johan-lejdung
Copy link

johan-lejdung commented Jun 19, 2016

Are you positive this works? I'm getting a 'SignatureDoesNotMatch' error.. And my although it looks like it signed the url and creates a correct signed string.

Edit: The problem seemed to be with the way the signString was constructed. It might be a problem isolated to me but sometimes i had one too few linebreaks between GET and the expire date :/. I resorted to build it myself

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment