Exception
11 months ago
CloudFrontClient.php
11 months ago
CookieSigner.php
11 months ago
Signer.php
11 months ago
UrlSigner.php
11 months ago
Signer.php
126 lines
| 1 | <?php |
| 2 | namespace Aws\CloudFront; |
| 3 | |
| 4 | /** |
| 5 | * @internal |
| 6 | */ |
| 7 | class Signer |
| 8 | { |
| 9 | private $keyPairId; |
| 10 | private $pkHandle; |
| 11 | |
| 12 | /** |
| 13 | * A signer for creating the signature values used in CloudFront signed URLs |
| 14 | * and signed cookies. |
| 15 | * |
| 16 | * @param $keyPairId string ID of the key pair |
| 17 | * @param $privateKey string Path to the private key used for signing |
| 18 | * @param $passphrase string Passphrase to private key file, if one exists |
| 19 | * |
| 20 | * @throws \RuntimeException if the openssl extension is missing |
| 21 | * @throws \InvalidArgumentException if the private key cannot be found. |
| 22 | */ |
| 23 | public function __construct($keyPairId, $privateKey, $passphrase = "") |
| 24 | { |
| 25 | if (!extension_loaded('openssl')) { |
| 26 | //@codeCoverageIgnoreStart |
| 27 | throw new \RuntimeException('The openssl extension is required to ' |
| 28 | . 'sign CloudFront urls.'); |
| 29 | //@codeCoverageIgnoreEnd |
| 30 | } |
| 31 | |
| 32 | $this->keyPairId = $keyPairId; |
| 33 | |
| 34 | if (!$this->pkHandle = openssl_pkey_get_private($privateKey, $passphrase)) { |
| 35 | if (!file_exists($privateKey)) { |
| 36 | throw new \InvalidArgumentException("PK file not found: $privateKey"); |
| 37 | } |
| 38 | |
| 39 | $this->pkHandle = openssl_pkey_get_private("file://$privateKey", $passphrase); |
| 40 | if (!$this->pkHandle) { |
| 41 | $errorMessages = []; |
| 42 | while(($newMessage = openssl_error_string()) !== false){ |
| 43 | $errorMessages[] = $newMessage; |
| 44 | } |
| 45 | throw new \InvalidArgumentException(implode("\n",$errorMessages)); |
| 46 | } |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | public function __destruct() |
| 51 | { |
| 52 | if (PHP_MAJOR_VERSION < 8) { |
| 53 | $this->pkHandle && openssl_pkey_free($this->pkHandle); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | /** |
| 58 | * Create the values used to construct signed URLs and cookies. |
| 59 | * |
| 60 | * @param string $resource The CloudFront resource to which |
| 61 | * this signature will grant access. |
| 62 | * Not used when a custom policy is |
| 63 | * provided. |
| 64 | * @param string|integer|null $expires UTC Unix timestamp used when |
| 65 | * signing with a canned policy. |
| 66 | * Not required when passing a |
| 67 | * custom $policy. |
| 68 | * @param string $policy JSON policy. Use this option when |
| 69 | * creating a signature for a custom |
| 70 | * policy. |
| 71 | * |
| 72 | * @return array The values needed to construct a signed URL or cookie |
| 73 | * @throws \InvalidArgumentException when not provided either a policy or a |
| 74 | * resource and a expires |
| 75 | * |
| 76 | * @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html |
| 77 | */ |
| 78 | public function getSignature($resource = null, $expires = null, $policy = null) |
| 79 | { |
| 80 | $signatureHash = []; |
| 81 | if ($policy) { |
| 82 | $policy = preg_replace('/\s/s', '', $policy); |
| 83 | $signatureHash['Policy'] = $this->encode($policy); |
| 84 | } elseif ($resource && $expires) { |
| 85 | $expires = (int) $expires; // Handle epoch passed as string |
| 86 | $policy = $this->createCannedPolicy($resource, $expires); |
| 87 | $signatureHash['Expires'] = $expires; |
| 88 | } else { |
| 89 | throw new \InvalidArgumentException('Either a policy or a resource' |
| 90 | . ' and an expiration time must be provided.'); |
| 91 | } |
| 92 | |
| 93 | $signatureHash['Signature'] = $this->encode($this->sign($policy)); |
| 94 | $signatureHash['Key-Pair-Id'] = $this->keyPairId; |
| 95 | |
| 96 | return $signatureHash; |
| 97 | } |
| 98 | |
| 99 | private function createCannedPolicy($resource, $expiration) |
| 100 | { |
| 101 | return json_encode([ |
| 102 | 'Statement' => [ |
| 103 | [ |
| 104 | 'Resource' => $resource, |
| 105 | 'Condition' => [ |
| 106 | 'DateLessThan' => ['AWS:EpochTime' => $expiration], |
| 107 | ], |
| 108 | ], |
| 109 | ], |
| 110 | ], JSON_UNESCAPED_SLASHES); |
| 111 | } |
| 112 | |
| 113 | private function sign($policy) |
| 114 | { |
| 115 | $signature = ''; |
| 116 | openssl_sign($policy, $signature, $this->pkHandle); |
| 117 | |
| 118 | return $signature; |
| 119 | } |
| 120 | |
| 121 | private function encode($policy) |
| 122 | { |
| 123 | return strtr(base64_encode($policy), '+=/', '-_~'); |
| 124 | } |
| 125 | } |
| 126 |