zx/vendor/obs/esdk-obs-php/Obs/Internal/Signature/V4Signature.php

202 lines
6.2 KiB
PHP
Raw Permalink Normal View History

2024-07-02 15:32:59 +08:00
<?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, $utcTimeZone, $securityToken = false, $isCname = false)
{
parent::__construct($ak, $sk, $pathStyle, $endpoint, $methodName, $signature, $securityToken, $isCname);
$this->region = $region;
$this->utcTimeZone = $utcTimeZone;
}
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'];
} elseif (array_key_exists('X-Amz-Date', $result['headers'])) {
$time = $result['headers']['X-Amz-Date'];
} else {
// nothing handle
}
$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);
return hash_hmac('sha256', implode('', $stringToSign), $signingKey);
}
public function getCanonicalQueryString($pathArgs)
{
$queryStr = '';
ksort($pathArgs);
$index = 0;
foreach ($pathArgs as $key => $value) {
$queryStr .= $key . '=' . $value;
if ($index !== count($pathArgs) - 1) {
$queryStr .= '&';
}
$index++;
}
return $queryStr;
}
public function getCanonicalHeaders($headers)
{
$headersResult = [];
foreach ($headers as $key => $value) {
$headersResult[strtolower($key)] = $value;
}
ksort($headersResult);
$canonicalHeaderStr = '';
foreach ($headersResult 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)
{
$headersResult = [];
foreach ($headers as $key => $value) {
$headersResult[] = strtolower($key);
}
sort($headersResult);
$signedHeaders = '';
foreach ($headersResult as $key => $value) {
$signedHeaders .= $value;
if ($key !== count($headersResult) - 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);
}
}