123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- <?php
- /**
- * Copyright 2019 Huawei Technologies Co.,Ltd.
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
- * this file except in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- *
- */
- namespace Obs\Internal\Signature;
- use Obs\Internal\Common\Model;
- class V4Signature extends AbstractSignature
- {
- const CONTENT_SHA256 = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
-
- protected $region;
-
- protected $utcTimeZone;
-
- public function __construct($ak, $sk, $pathStyle, $endpoint, $region, $methodName, $signature, $securityToken=false)
- {
- parent::__construct($ak, $sk, $pathStyle, $endpoint, $methodName, $signature, $securityToken);
- $this->region = $region;
- $this->utcTimeZone = new \DateTimeZone ('UTC');
- }
-
- public function doAuth(array &$requestConfig, array &$params, Model $model)
- {
- $result = $this -> prepareAuth($requestConfig, $params, $model);
-
- $result['headers']['x-amz-content-sha256'] = self::CONTENT_SHA256;
-
- $bucketName = $result['dnsParam'];
-
- $result['headers']['Host'] = $result['host'];
-
- $time = null;
- if(array_key_exists('x-amz-date', $result['headers'])){
- $time = $result['headers']['x-amz-date'];
- }else if(array_key_exists('X-Amz-Date', $result['headers'])){
- $time = $result['headers']['X-Amz-Date'];
- }
- $timestamp = $time ? date_create_from_format('Ymd\THis\Z', $time, $this->utcTimeZone) -> getTimestamp()
- :time();
-
- $result['headers']['Date'] = gmdate('D, d M Y H:i:s \G\M\T', $timestamp);
-
- $longDate = gmdate('Ymd\THis\Z', $timestamp);
- $shortDate = substr($longDate, 0, 8);
-
- $credential = $this-> getCredential($shortDate);
-
- $signedHeaders = $this->getSignedHeaders($result['headers']);
-
- $canonicalstring = $this-> makeCanonicalstring($result['method'], $result['headers'], $result['pathArgs'], $bucketName, $result['uriParam'], $signedHeaders);
-
- $result['cannonicalRequest'] = $canonicalstring;
-
- $signature = $this -> getSignature($canonicalstring, $longDate, $shortDate);
-
- $authorization = 'AWS4-HMAC-SHA256 ' . 'Credential=' . $credential. ',' . 'SignedHeaders=' . $signedHeaders . ',' . 'Signature=' . $signature;
-
- $result['headers']['Authorization'] = $authorization;
-
- return $result;
- }
-
- public function getSignature($canonicalstring, $longDate, $shortDate)
- {
- $stringToSign = [];
- $stringToSign[] = 'AWS4-HMAC-SHA256';
-
- $stringToSign[] = "\n";
-
- $stringToSign[] = $longDate;
-
- $stringToSign[] = "\n";
- $stringToSign[] = $this -> getScope($shortDate);
- $stringToSign[] = "\n";
-
- $stringToSign[] = hash('sha256', $canonicalstring);
-
- $dateKey = hash_hmac('sha256', $shortDate, 'AWS4' . $this -> sk, true);
- $regionKey = hash_hmac('sha256', $this->region, $dateKey, true);
- $serviceKey = hash_hmac('sha256', 's3', $regionKey, true);
- $signingKey = hash_hmac('sha256', 'aws4_request', $serviceKey, true);
- $signature = hash_hmac('sha256', implode('', $stringToSign), $signingKey);
- return $signature;
- }
-
- public function getCanonicalQueryString($pathArgs)
- {
- $queryStr = '';
-
- ksort($pathArgs);
- $index = 0;
- foreach ($pathArgs as $key => $value){
- $queryStr .= $key . '=' . $value;
- if($index++ !== count($pathArgs) - 1){
- $queryStr .= '&';
- }
- }
- return $queryStr;
- }
-
- public function getCanonicalHeaders($headers)
- {
- $_headers = [];
- foreach ($headers as $key => $value) {
- $_headers[strtolower($key)] = $value;
- }
- ksort($_headers);
-
- $canonicalHeaderStr = '';
-
- foreach ($_headers as $key => $value){
- $value = is_array($value) ? implode(',', $value) : $value;
- $canonicalHeaderStr .= $key . ':' . $value;
- $canonicalHeaderStr .= "\n";
- }
- return $canonicalHeaderStr;
- }
-
- public function getCanonicalURI($bucketName, $objectKey)
- {
- $uri = '';
- if($this -> pathStyle && $bucketName){
- $uri .= '/' . $bucketName;
- }
-
- if($objectKey){
- $uri .= '/' . $objectKey;
- }
-
- if($uri === ''){
- $uri = '/';
- }
- return $uri;
- }
-
- public function makeCanonicalstring($method, $headers, $pathArgs, $bucketName, $objectKey, $signedHeaders=null, $payload=null)
- {
- $buffer = [];
- $buffer[] = $method;
- $buffer[] = "\n";
- $buffer[] = $this->getCanonicalURI($bucketName, $objectKey);
- $buffer[] = "\n";
- $buffer[] = $this->getCanonicalQueryString($pathArgs);
- $buffer[] = "\n";
- $buffer[] = $this->getCanonicalHeaders($headers);
- $buffer[] = "\n";
- $buffer[] = $signedHeaders ? $signedHeaders : $this->getSignedHeaders($headers);
- $buffer[] = "\n";
- $buffer[] = $payload ? strval($payload) : self::CONTENT_SHA256;
-
- return implode('', $buffer);
- }
-
- public function getSignedHeaders($headers)
- {
- $_headers = [];
-
- foreach ($headers as $key => $value) {
- $_headers[] = strtolower($key);
- }
-
- sort($_headers);
-
- $signedHeaders = '';
-
- foreach ($_headers as $key => $value){
- $signedHeaders .= $value;
- if($key !== count($_headers) - 1){
- $signedHeaders .= ';';
- }
- }
- return $signedHeaders;
- }
-
- public function getScope($shortDate)
- {
- return $shortDate . '/' . $this->region . '/s3/aws4_request';
- }
-
- public function getCredential($shortDate)
- {
- return $this->ak . '/' . $this->getScope($shortDate);
- }
- }
|