-
-
Save mloureiro/14503293c3cb2191e2f6 to your computer and use it in GitHub Desktop.
<? | |
/** | |
* 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> |
Thanks for writing this up. I'm trying to figure this part out but this is kinda confusing. I've never seen anything like this. Care to elaborate?
return <<<TXT
{$method}
{$contentMd5}
{$contentType}
{$expiration}
{$headers}{$file}
TXT;
Each variable on the return string represents a line (or multiple in case of headers).
The required ones are method (called HTTP_VERB on goolge), expiration and the file.
So that will return a string similar to the examples at Sign Urls#Construct-the-String
For instance:
PUT
rmYdCNHKFXam78uCt7xQLw==
text/plain
1388534400
x-goog-acl:public-read
x-goog-meta-foo:bar,baz
/bucket/objectname
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
Notice:
If you're using the PHP API from Google you can use the
Google_Signer_P12::sign()
method, so it's possible to change sign method to: