PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.5.0
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.5.0
1.19.8 1.19.7 1.19.6 1.19.5 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.12.0 1.13.0 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.16.6 1.16.7 1.16.8 1.17.0 1.17.6 1.17.7 1.17.8 1.17.9 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.18.5 1.18.6 1.18.7 1.18.8 1.18.9 1.19.0 1.19.1 1.19.2 1.19.3 1.19.4 1.3.19 1.3.20 1.4.0 1.4.1 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.16 1.5.17 1.5.18 1.5.19 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.8.1 1.8.3 1.9.0 1.9.1 1.9.2
nitropack / nitropack-sdk / NitroPack / SDK / Api / SignedBase.php
nitropack / nitropack-sdk / NitroPack / SDK / Api Last commit date
Base.php 5 years ago Cache.php 5 years ago Integration.php 6 years ago RemoteConfigFetcher.php 6 years ago RequestMaker.php 5 years ago Response.php 6 years ago ResponseStatus.php 6 years ago SecureRequestMaker.php 5 years ago SignedBase.php 5 years ago Stats.php 6 years ago Tagger.php 6 years ago Url.php 6 years ago VariationCookie.php 6 years ago Warmup.php 6 years ago Webhook.php 6 years ago
SignedBase.php
135 lines
1 <?php
2 namespace NitroPack\SDK\Api;
3 use \NitroPack\Url;
4
5 // Src: http://php.net/manual/en/function.hash-equals.php
6 if(!function_exists('hash_equals')) {
7 function hash_equals($str1, $str2) {
8 if(strlen($str1) != strlen($str2)) {
9 return false;
10 } else {
11 $res = $str1 ^ $str2;
12 $ret = 0;
13 for($i = strlen($res) - 1; $i >= 0; $i--) $ret |= ord($res[$i]);
14 return !$ret;
15 }
16 }
17 }
18
19 class SignedBase extends Base {
20
21 private static $signatureHeader = 'X-Nitro-Signature';
22 private static $algorithm = 'sha512';
23
24 protected $secret;
25
26 public function __construct($siteId, $siteSecret) {
27 parent::__construct($siteId);
28 $this->secret = $siteSecret;
29 }
30
31 protected function addToBacklog($entry) {
32 $entry["siteSecret"] = $this->secret;
33 parent::addToBacklog($entry);
34 }
35
36 protected function makeRequest($path, $headers = array(), $cookies = array(), $type = 'GET', $bodyData=array(), $async = false, $verifySSL = false) {
37 // calculate request signature
38 $url = new Url($this->baseUrl . $path);
39 $noParamsPath = $url->getPath();
40 $params = array();
41 parse_str($url->getQuery(), $params);
42 $params = $params + $bodyData;
43 $headers[SignedBase::$signatureHeader] = static::calculateRequestSignature($noParamsPath, $params, static::getSignatureHeaders($headers), $this->secret);
44
45 // make the request
46 $http = parent::makeRequest($path, $headers, $cookies, $type, $bodyData, $async, $verifySSL);
47
48 if ($async) {
49 $http->setOnCompleteCallback(array($this, 'verifySignature'));
50 } else {
51 $this->verifySignature($http);
52 }
53
54 return $http;
55 }
56
57 protected function verifySignature($http) {
58 if ($http->getStatusCode() === ResponseStatus::OK) {
59 $responseHeaders = $http->getHeaders();
60 if (!isset($responseHeaders[strtolower(SignedBase::$signatureHeader)])) {
61 throw new \RuntimeException('Server did not include a signature for a request that was expected to be signed');
62 }
63 $signature = static::calculateResponseSignature($http->getBody(), static::getSignatureHeaders($responseHeaders), $this->secret);
64 if (!hash_equals($signature, $responseHeaders[strtolower(SignedBase::$signatureHeader)])) { // TODO move RemoteConfigFetcher::internal_hash_equals to a place where its accessible everywhere and use it here
65 throw new \RuntimeException('Server signature is wrong'); // TODO better message
66 }
67 }
68 }
69
70 /** Signature data:
71 * UrlPath|header1:value,header2:value|param1:value,param2:value
72 * if not using headers, we still expect their delimiter UrlPath||param1:value,param2:value
73 */
74 protected static function calculateRequestSignature($urlPath, $parameters, $headers, $secret) {
75 // do not include the header that specifies the signature
76 if (isset($headers[SignedBase::$signatureHeader])) {
77 unset($headers[SignedBase::$signatureHeader]);
78 }
79
80 $data = $urlPath;
81
82 ksort($headers);
83 $headersTemp = [];
84 foreach ($headers as $header => $value) {
85 $headersTemp[] = str_replace('-', '_', strtolower($header)) . ':' . $value;
86 }
87
88 $data .= '|' . implode(',', $headersTemp);
89 $headersTemp = null;
90
91 ksort($parameters);
92 $paramsTemp = [];
93 foreach ($parameters as $param => $value) {
94 if (is_array($value)) {
95 $paramsTemp[] = $param . ':' . json_encode($value);
96 } else {
97 $paramsTemp[] = $param . ':' . $value;
98 }
99 }
100
101 $data .= '|' . implode(',', $paramsTemp);
102 $paramsTemp = null;
103 return SignedBase::hmac($data, $secret);
104 }
105
106 protected static function getSignatureHeaders($headers) {
107 $signatureHeaders = [];
108 foreach ($headers as $header => $value) {
109 if (stripos($header, 'x-nitro-') !== false && strtolower($header) != strtolower(SignedBase::$signatureHeader)) {
110 $signatureHeaders[$header] = $value;
111 }
112 }
113
114 return $signatureHeaders;
115 }
116
117 protected static function calculateResponseSignature($data, $headers, $secret) {
118 ksort($headers);
119 $headersTemp = [];
120 foreach ($headers as $header => $value) {
121 $headersTemp[] = str_replace('-', '_', strtolower($header)) . ':' . $value;
122 }
123
124 $data = implode(',', $headersTemp) . '|' . $data;
125 $headersTemp = null;
126
127 return SignedBase::hmac($data, $secret);
128 }
129
130 private static function hmac($data, $secret) {
131 return hash_hmac(SignedBase::$algorithm, $data, $secret);
132 }
133
134 }
135