HuaweiSigner.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <?php
  2. namespace app\admin\common;
  3. define("BasicDateFormat", "Ymd\THis\Z");
  4. define("Algorithm", "SDK-HMAC-SHA256");
  5. define("HeaderXDate", "X-Sdk-Date");
  6. define("HeaderHost", "host");
  7. define("HeaderAuthorization", "Authorization");
  8. define("HeaderContentSha256", "X-Sdk-Content-Sha256");
  9. class HuaweiSigner
  10. {
  11. public $Key = '';
  12. public $Secret = '';
  13. function escape($string)
  14. {
  15. $entities = array('+', "%7E");
  16. $replacements = array('%20', "~");
  17. return str_replace($entities, $replacements, urlencode($string));
  18. }
  19. function findHeader($r, $header)
  20. {
  21. foreach ($r->headers as $key => $value) {
  22. if (!strcasecmp($key, $header)) {
  23. return $value;
  24. }
  25. }
  26. return NULL;
  27. }
  28. // Build a CanonicalRequest from a regular request string
  29. //
  30. // CanonicalRequest =
  31. // HTTPRequestMethod + '\n' +
  32. // CanonicalURI + '\n' +
  33. // CanonicalQueryString + '\n' +
  34. // CanonicalHeaders + '\n' +
  35. // SignedHeaders + '\n' +
  36. // HexEncode(Hash(RequestPayload))
  37. function CanonicalRequest($r, $signedHeaders)
  38. {
  39. $CanonicalURI = $this->CanonicalURI($r);
  40. $CanonicalQueryString = $this->CanonicalQueryString($r);
  41. $canonicalHeaders = $this->CanonicalHeaders($r, $signedHeaders);
  42. $signedHeadersString = join(";", $signedHeaders);
  43. $hash = $this->findHeader($r, HeaderContentSha256);
  44. if (!$hash) {
  45. $hash = hash("sha256", $r->body);
  46. }
  47. return "$r->method\n$CanonicalURI\n$CanonicalQueryString\n$canonicalHeaders\n$signedHeadersString\n$hash";
  48. }
  49. // CanonicalURI returns request uri
  50. function CanonicalURI($r)
  51. {
  52. $pattens = explode("/", $r->uri);
  53. $uri = array();
  54. foreach ($pattens as $v) {
  55. array_push($uri, $this->escape($v));
  56. }
  57. $urlpath = join("/", $uri);
  58. if (substr($urlpath, -1) != "/") {
  59. $urlpath = $urlpath . "/";
  60. }
  61. return $urlpath;
  62. }
  63. // CanonicalQueryString
  64. function CanonicalQueryString($r)
  65. {
  66. $keys = array();
  67. foreach ($r->query as $key => $value) {
  68. array_push($keys, $key);
  69. }
  70. sort($keys);
  71. $a = array();
  72. foreach ($keys as $key) {
  73. $k = $this->escape($key);
  74. $value = $r->query[$key];
  75. if (is_array($value)) {
  76. sort($value);
  77. foreach ($value as $v) {
  78. $kv = "$k=" . $this->escape($v);
  79. array_push($a, $kv);
  80. }
  81. } else {
  82. $kv = "$k=" . $this->escape($value);
  83. array_push($a, $kv);
  84. }
  85. }
  86. return join("&", $a);
  87. }
  88. // CanonicalHeaders
  89. function CanonicalHeaders($r, $signedHeaders)
  90. {
  91. $headers = array();
  92. foreach ($r->headers as $key => $value) {
  93. $headers[strtolower($key)] = trim($value);
  94. }
  95. $a = array();
  96. foreach ($signedHeaders as $key) {
  97. array_push($a, $key . ':' . $headers[$key]);
  98. }
  99. return join("\n", $a) . "\n";
  100. }
  101. function curlHeaders($r)
  102. {
  103. $header = array();
  104. foreach ($r->headers as $key => $value) {
  105. array_push($header, strtolower($key) . ':' . trim($value));
  106. }
  107. return $header;
  108. }
  109. // SignedHeaders
  110. function SignedHeaders($r)
  111. {
  112. $a = array();
  113. foreach ($r->headers as $key => $value) {
  114. array_push($a, strtolower($key));
  115. }
  116. sort($a);
  117. return $a;
  118. }
  119. // Create a "String to Sign".
  120. function StringToSign($canonicalRequest, $t)
  121. {
  122. date_default_timezone_set('UTC');
  123. $date = date(BasicDateFormat, $t);
  124. $hash = hash("sha256", $canonicalRequest);
  125. return "SDK-HMAC-SHA256\n$date\n$hash";
  126. }
  127. // Create the HWS Signature.
  128. function SignStringToSign($stringToSign, $signingKey)
  129. {
  130. return hash_hmac("sha256", $stringToSign, $signingKey);
  131. }
  132. // Get the finalized value for the "Authorization" header. The signature parameter is the output from SignStringToSign
  133. function AuthHeaderValue($signature, $accessKey, $signedHeaders)
  134. {
  135. $signedHeadersString = join(";", $signedHeaders);
  136. return "SDK-HMAC-SHA256 Access=$accessKey, SignedHeaders=$signedHeadersString, Signature=$signature";
  137. }
  138. public function Sign($r)
  139. {
  140. date_default_timezone_set('UTC');
  141. $date = $this->findHeader($r, HeaderXDate);
  142. if ($date) {
  143. $t = date_timestamp_get(date_create_from_format(BasicDateFormat, $date));
  144. }
  145. if (!@$t) {
  146. $t = time();
  147. $r->headers[HeaderXDate] = date(BasicDateFormat, $t);
  148. }
  149. $queryString = $this->CanonicalQueryString($r);
  150. if ($queryString != "") {
  151. $queryString = "?" . $queryString;
  152. }
  153. $signedHeaders = $this->SignedHeaders($r);
  154. $canonicalRequest = $this->CanonicalRequest($r, $signedHeaders);
  155. $stringToSign = $this->StringToSign($canonicalRequest, $t);
  156. $signature = $this->SignStringToSign($stringToSign, $this->Secret);
  157. $authValue = $this->AuthHeaderValue($signature, $this->Key, $signedHeaders);
  158. $r->headers[HeaderAuthorization] = $authValue;
  159. $curl = curl_init();
  160. $uri = str_replace(array("%2F"), array("/"), rawurlencode($r->uri));
  161. $url = $r->scheme . '://' . $r->host . $uri . $queryString;
  162. $headers = $this->curlHeaders($r);
  163. curl_setopt($curl, CURLOPT_URL, $url);
  164. curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  165. curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $r->method);
  166. curl_setopt($curl, CURLOPT_POSTFIELDS, $r->body);
  167. curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
  168. curl_setopt($curl, CURLOPT_NOBODY, FALSE);
  169. return $curl;
  170. }
  171. }