<?php
class AipHttpUtil
{
public static $PERCENT_ENCODED_STRINGS;
public static function __init()
{
AipHttpUtil::$PERCENT_ENCODED_STRINGS = array();
for ($i = 0; $i < 256; ++$i) {
AipHttpUtil::$PERCENT_ENCODED_STRINGS[$i] = sprintf("%%%02X", $i);
}
foreach (range('a', 'z') as $ch) {
AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord($ch)] = $ch;
}
foreach (range('A', 'Z') as $ch) {
AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord($ch)] = $ch;
}
foreach (range('0', '9') as $ch) {
AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord($ch)] = $ch;
}
AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord('-')] = '-';
AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord('.')] = '.';
AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord('_')] = '_';
AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord('~')] = '~';
}
public static function urlEncodeExceptSlash($path)
{
return str_replace("%2F", "/", AipHttpUtil::urlEncode($path));
}
public static function urlEncode($value)
{
$result = '';
for ($i = 0; $i < strlen($value); ++$i) {
$result .= AipHttpUtil::$PERCENT_ENCODED_STRINGS[ord($value[$i])];
}
return $result;
}
public static function getCanonicalQueryString(array $parameters)
{
if (count($parameters) == 0) {
return '';
}
$parameterStrings = array();
foreach ($parameters as $k => $v) {
if (strcasecmp('Authorization', $k) == 0) {
continue;
}
if (!isset($k)) {
throw new \InvalidArgumentException(
"parameter key should not be null"
);
}
if (isset($v)) {
$parameterStrings[] = AipHttpUtil::urlEncode($k)
. '=' . AipHttpUtil::urlEncode((string) $v);
} else {
$parameterStrings[] = AipHttpUtil::urlEncode($k) . '=';
}
}
sort($parameterStrings);
return implode('&', $parameterStrings);
}
public static function getCanonicalURIPath($path)
{
if (empty($path)) {
return '/';
} else {
if ($path[0] == '/') {
return AipHttpUtil::urlEncodeExceptSlash($path);
} else {
return '/' . AipHttpUtil::urlEncodeExceptSlash($path);
}
}
}
public static function getCanonicalHeaders($headers)
{
if (count($headers) == 0) {
return '';
}
$headerStrings = array();
foreach ($headers as $k => $v) {
if ($k === null) {
continue;
}
if ($v === null) {
$v = '';
}
$headerStrings[] = AipHttpUtil::urlEncode(strtolower(trim($k))) . ':' . AipHttpUtil::urlEncode(trim($v));
}
sort($headerStrings);
return implode("\n", $headerStrings);
}
}
AipHttpUtil::__init();
class AipSignOption
{
const EXPIRATION_IN_SECONDS = 'expirationInSeconds';
const HEADERS_TO_SIGN = 'headersToSign';
const TIMESTAMP = 'timestamp';
const DEFAULT_EXPIRATION_IN_SECONDS = 1800;
const MIN_EXPIRATION_IN_SECONDS = 300;
const MAX_EXPIRATION_IN_SECONDS = 129600;
}
class AipSampleSigner
{
const BCE_AUTH_VERSION = "bce-auth-v1";
const BCE_PREFIX = 'x-bce-';
public static $defaultHeadersToSign;
public static function __init()
{
AipSampleSigner::$defaultHeadersToSign = array(
"host",
"content-length",
"content-type",
"content-md5",
);
}
public static function sign(
array $credentials,
$httpMethod,
$path,
$headers,
$params,
$options = array()
) {
if (!isset($options[AipSignOption::EXPIRATION_IN_SECONDS])) {
$expirationInSeconds = AipSignOption::DEFAULT_EXPIRATION_IN_SECONDS;
} else {
$expirationInSeconds = $options[AipSignOption::EXPIRATION_IN_SECONDS];
}
$accessKeyId = $credentials['ak'];
$secretAccessKey = $credentials['sk'];
if (!isset($options[AipSignOption::TIMESTAMP])) {
$timestamp = gmdate('Y-m-d\TH:i:s\Z');
} else {
$timestamp = $options[AipSignOption::TIMESTAMP];
}
$authString = AipSampleSigner::BCE_AUTH_VERSION . '/' . $accessKeyId . '/'
. $timestamp . '/' . $expirationInSeconds;
$signingKey = hash_hmac('sha256', $authString, $secretAccessKey);
$canonicalURI = AipHttpUtil::getCanonicalURIPath($path);
$canonicalQueryString = AipHttpUtil::getCanonicalQueryString($params);
$headersToSign = null;
if (isset($options[AipSignOption::HEADERS_TO_SIGN])) {
$headersToSign = $options[AipSignOption::HEADERS_TO_SIGN];
}
$canonicalHeader = AipHttpUtil::getCanonicalHeaders(
AipSampleSigner::getHeadersToSign($headers, $headersToSign)
);
$signedHeaders = '';
if ($headersToSign !== null) {
$signedHeaders = strtolower(
trim(implode(";", $headersToSign))
);
}
$canonicalRequest = "$httpMethod\n$canonicalURI\n"
. "$canonicalQueryString\n$canonicalHeader";
$signature = hash_hmac('sha256', $canonicalRequest, $signingKey);
$authorizationHeader = "$authString/$signedHeaders/$signature";
return $authorizationHeader;
}
public static function getHeadersToSign($headers, $headersToSign)
{
$filter_empty = function($v) {
return trim((string) $v) !== '';
};
$headers = array_filter($headers, $filter_empty);
$trim_and_lower = function($str){
return strtolower(trim($str));
};
$temp = array();
$process_keys = function($k, $v) use(&$temp, $trim_and_lower) {
$temp[$trim_and_lower($k)] = $v;
};
array_map($process_keys, array_keys($headers), $headers);
$headers = $temp;
$header_keys = array_keys($headers);
$filtered_keys = null;
if ($headersToSign !== null) {
$headersToSign = array_map($trim_and_lower, $headersToSign);
$filtered_keys = array_intersect_key($header_keys, $headersToSign);
} else {
$filter_by_default = function($k) {
return AipSampleSigner::isDefaultHeaderToSign($k);
};
$filtered_keys = array_filter($header_keys, $filter_by_default);
}
return array_intersect_key($headers, array_flip($filtered_keys));
}
public static function isDefaultHeaderToSign($header)
{
$header = strtolower(trim($header));
if (in_array($header, AipSampleSigner::$defaultHeadersToSign)) {
return true;
}
return substr_compare($header, AipSampleSigner::BCE_PREFIX, 0, strlen(AipSampleSigner::BCE_PREFIX)) == 0;
}
}
AipSampleSigner::__init();