| 1 |
<?php |
| 2 |
|
| 3 |
namespace Dudlewebs\WPMCS\s3\Aws\CloudFront; |
| 4 |
|
| 5 |
/** |
| 6 |
* @internal |
| 7 |
*/ |
| 8 |
class Signer |
| 9 |
{ |
| 10 |
private $keyPairId; |
| 11 |
private $pkHandle; |
| 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 ' . 'sign CloudFront urls.'); |
| 28 |
//@codeCoverageIgnoreEnd |
| 29 |
} |
| 30 |
$this->keyPairId = $keyPairId; |
| 31 |
if (!($this->pkHandle = \openssl_pkey_get_private($privateKey, $passphrase))) { |
| 32 |
if (!\file_exists($privateKey)) { |
| 33 |
throw new \InvalidArgumentException("PK file not found: {$privateKey}"); |
| 34 |
} |
| 35 |
$this->pkHandle = \openssl_pkey_get_private("file://{$privateKey}", $passphrase); |
| 36 |
if (!$this->pkHandle) { |
| 37 |
$errorMessages = []; |
| 38 |
while (($newMessage = \openssl_error_string()) !== \false) { |
| 39 |
$errorMessages[] = $newMessage; |
| 40 |
} |
| 41 |
throw new \InvalidArgumentException(\implode("\n", $errorMessages)); |
| 42 |
} |
| 43 |
} |
| 44 |
} |
| 45 |
public function __destruct() |
| 46 |
{ |
| 47 |
if (\PHP_MAJOR_VERSION < 8) { |
| 48 |
$this->pkHandle && \openssl_pkey_free($this->pkHandle); |
| 49 |
} |
| 50 |
} |
| 51 |
/** |
| 52 |
* Create the values used to construct signed URLs and cookies. |
| 53 |
* |
| 54 |
* @param string $resource The CloudFront resource to which |
| 55 |
* this signature will grant access. |
| 56 |
* Not used when a custom policy is |
| 57 |
* provided. |
| 58 |
* @param string|integer|null $expires UTC Unix timestamp used when |
| 59 |
* signing with a canned policy. |
| 60 |
* Not required when passing a |
| 61 |
* custom $policy. |
| 62 |
* @param string $policy JSON policy. Use this option when |
| 63 |
* creating a signature for a custom |
| 64 |
* policy. |
| 65 |
* |
| 66 |
* @return array The values needed to construct a signed URL or cookie |
| 67 |
* @throws \InvalidArgumentException when not provided either a policy or a |
| 68 |
* resource and a expires |
| 69 |
* |
| 70 |
* @link http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html |
| 71 |
*/ |
| 72 |
public function getSignature($resource = null, $expires = null, $policy = null) |
| 73 |
{ |
| 74 |
$signatureHash = []; |
| 75 |
if ($policy) { |
| 76 |
$policy = \preg_replace('/\\s/s', '', $policy); |
| 77 |
$signatureHash['Policy'] = $this->encode($policy); |
| 78 |
} elseif ($resource && $expires) { |
| 79 |
$expires = (int) $expires; |
| 80 |
// Handle epoch passed as string |
| 81 |
$policy = $this->createCannedPolicy($resource, $expires); |
| 82 |
$signatureHash['Expires'] = $expires; |
| 83 |
} else { |
| 84 |
throw new \InvalidArgumentException('Either a policy or a resource' . ' and an expiration time must be provided.'); |
| 85 |
} |
| 86 |
$signatureHash['Signature'] = $this->encode($this->sign($policy)); |
| 87 |
$signatureHash['Key-Pair-Id'] = $this->keyPairId; |
| 88 |
return $signatureHash; |
| 89 |
} |
| 90 |
private function createCannedPolicy($resource, $expiration) |
| 91 |
{ |
| 92 |
return \json_encode(['Statement' => [['Resource' => $resource, 'Condition' => ['DateLessThan' => ['AWS:EpochTime' => $expiration]]]]], \JSON_UNESCAPED_SLASHES); |
| 93 |
} |
| 94 |
private function sign($policy) |
| 95 |
{ |
| 96 |
$signature = ''; |
| 97 |
\openssl_sign($policy, $signature, $this->pkHandle); |
| 98 |
return $signature; |
| 99 |
} |
| 100 |
private function encode($policy) |
| 101 |
{ |
| 102 |
return \strtr(\base64_encode($policy), '+=/', '-_~'); |
| 103 |
} |
| 104 |
} |
| 105 |
|