-
-
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: