123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- <?php
- namespace Aws\CloudFront;
- /**
- * @internal
- */
- class Signer
- {
- private $keyPairId;
- private $pkHandle;
- /**
- * A signer for creating the signature values used in CloudFront signed URLs
- * and signed cookies.
- *
- * @param $keyPairId string ID of the key pair
- * @param $privateKey string Path to the private key used for signing
- * @param $passphrase string Passphrase to private key file, if one exists
- *
- * @throws \RuntimeException if the openssl extension is missing
- * @throws \InvalidArgumentException if the private key cannot be found.
- */
- public function __construct($keyPairId, $privateKey, $passphrase = "")
- {
- if (!extension_loaded('openssl')) {
- //@codeCoverageIgnoreStart
- throw new \RuntimeException('The openssl extension is required to '
- . 'sign CloudFront urls.');
- //@codeCoverageIgnoreEnd
- }
- $this->keyPairId = $keyPairId;
- if (!$this->pkHandle = openssl_pkey_get_private($privateKey, $passphrase)) {
- if (!file_exists($privateKey)) {
- throw new \InvalidArgumentException("PK file not found: $privateKey");
- }
- $this->pkHandle = openssl_pkey_get_private("file://$privateKey", $passphrase);
- if (!$this->pkHandle) {
- $errorMessages = [];
- while(($newMessage = openssl_error_string()) !== false){
- $errorMessages[] = $newMessage;
- }
- throw new \InvalidArgumentException(implode("\n",$errorMessages));
- }
- }
- }
- public function __destruct()
- {
- if (PHP_MAJOR_VERSION < 8) {
- $this->pkHandle && openssl_pkey_free($this->pkHandle);
- }
- }
- /**
- * Create the values used to construct signed URLs and cookies.
- *
- * @param string $resource The CloudFront resource to which
- * this signature will grant access.
- * Not used when a custom policy is
- * provided.
- * @param string|integer|null $expires UTC Unix timestamp used when
- * signing with a canned policy.
- * Not required when passing a
- * custom $policy.
- * @param string $policy JSON policy. Use this option when
- * creating a signature for a custom
- * policy.
- *
- * @return array The values needed to construct a signed URL or cookie
- * @throws \InvalidArgumentException when not provided either a policy or a
- * resource and a expires
- * @throws \RuntimeException when generated signature is empty
- *
- * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
- */
- public function getSignature($resource = null, $expires = null, $policy = null)
- {
- $signatureHash = [];
- if ($policy) {
- $policy = preg_replace('/\s/s', '', $policy);
- $signatureHash['Policy'] = $this->encode($policy);
- } elseif ($resource && $expires) {
- $expires = (int) $expires; // Handle epoch passed as string
- $policy = $this->createCannedPolicy($resource, $expires);
- $signatureHash['Expires'] = $expires;
- } else {
- throw new \InvalidArgumentException('Either a policy or a resource'
- . ' and an expiration time must be provided.');
- }
- $signatureHash['Signature'] = $this->encode($this->sign($policy));
- $signatureHash['Key-Pair-Id'] = $this->keyPairId;
- return $signatureHash;
- }
- private function createCannedPolicy($resource, $expiration)
- {
- return json_encode([
- 'Statement' => [
- [
- 'Resource' => $resource,
- 'Condition' => [
- 'DateLessThan' => ['AWS:EpochTime' => $expiration],
- ],
- ],
- ],
- ], JSON_UNESCAPED_SLASHES);
- }
- private function sign($policy)
- {
- $signature = '';
-
- if(!openssl_sign($policy, $signature, $this->pkHandle)) {
- $errorMessages = [];
- while(($newMessage = openssl_error_string()) !== false) {
- $errorMessages[] = $newMessage;
- }
-
- $exceptionMessage = "An error has occurred when signing the policy";
- if (count($errorMessages) > 0) {
- $exceptionMessage = implode("\n", $errorMessages);
- }
- throw new \RuntimeException($exceptionMessage);
- }
- return $signature;
- }
- private function encode($policy)
- {
- return strtr(base64_encode($policy), '+=/', '-_~');
- }
- }
|