首页 文章

签名版本4在PHP中签名以访问API网关 endpoints

提问于
浏览
0

我正在尝试创建授权签名以访问IAM安全API网关 endpoints .

$alg = "SHA256";
$CanonicalRequest = "GET\n/dev/pets\n\nhost:3r4fgts8e5.execute-api.ap-northeast-1.amazonaws.com\nx-amz-date:".$dd."\n\nhost;x-amz-date\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";

$CR =  str_replace("\n", "", $CanonicalRequest);
            $CR = str_replace("\r", "", $CR);
            $CR = strtolower($CR);




$StringToSign  = "AWS4-HMAC-SHA256\n".$dd."\n".$date->format( 'Ymd' )."/ap-northeast-1/execute-api/aws4_request\n".hash( $alg, $CR )."";





// 1) HMACs
$kSecret = 'AWS4' . $secret_key;
$kDate = hash_hmac( $alg, $date->format( 'Ymd' ), $kSecret, true );     
$kRegion = hash_hmac( $alg, $region, $kDate, true );
$kService = hash_hmac( $alg, $service, $kRegion, true );
$kSigning = hash_hmac( $alg, 'aws4_request', $kService, true );     
$signature = hash_hmac( $alg, $StringToSign, $kSigning );       

$authorization = array(
    'Credential=' . $access_key . '/' . implode( '/', $scope ),
    'SignedHeaders=' . implode( ';', array_keys( $can_headers ) ),
    'Signature=' . $signature,
);
$authorization = $request['algorithm'] . ' ' . implode( ',', $authorization );
$request['Authorization'] = $authorization;

But I am getting "The request signature we calculated does not match the signature you provided" error

“message”:“我们计算的请求签名与您提供的签名不匹配 . 请检查您的AWS秘密访问密钥和签名方法 . 有关详细信息,请参阅服务文档 . \ n \ n此请求的规范字符串应该是\ n 'GET \ n的/ dev /宠物的\ n \ n主机:3r4fgts8e5.execute-api.ap-northeast-1.amazonaws.com \ NX-AMZ-日期:20161002T231640Z \ n \ n主机; X-AMZ-日期\ ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' \ n \ n字符串到标志应该是\ n'AWS4-HMAC-SHA256 \ n20161002T231640Z \ n20161002 / ap-northeast-1 / execute-api / aws4_request \ n0b8c12e0a5f21137c5739a9d26056dfb081218631a9adcf37db1d2e09a014c4e'\ n“

我的String-to-sign字符串是

"AWS4-HMAC-SHA256
20161002T231640Z
20161002/ap-northeast-1/execute-api/aws4_request
fb4f7ebdcb405bceed598ecc097267b929eeb3f8f075b1b7a776f53c8c8c6168"

这与AWS在签名中的预期完全不同 .

1 回答

  • 2

    这是解决方案

    private function signRequest(){
            $method ='GET';
            $uri = '/dev';
            $json = file_get_contents('php://input');
            $obj = json_decode($json);
    
    
            if(isset($obj->method))
            {
                $m = explode("|", $obj->method);
                $method = $m[0];
                $uri .= $m[1];
            }
    
    
            $secretKey = $this->session->data['aws_secret'];
            $access_key = $this->session->data['aws_key'];
            $token = $this->session->data['aws_token'];
            $region = 'ap-southeast-1';
            $service = 'execute-api';
    
            $options = array(); $headers = array();
            $host = "YOUR-API-HOST.execute-api.ap-southeast-1.amazonaws.com";
    //Or you can define your host here.. I am using API gateway.
    
    
            $alg = 'sha256';
    
            $date = new DateTime( 'UTC' );
    
            $dd = $date->format( 'Ymd\THis\Z' );
    
            $amzdate2 = new DateTime( 'UTC' );
            $amzdate2 = $amzdate2->format( 'Ymd' );
            $amzdate = $dd;
    
            $algorithm = 'AWS4-HMAC-SHA256';
    
    
            $parameters = (array) $obj->data;
    
               if($obj->data == null || empty($obj->data)) 
            {
                $obj->data = "";
            }else{
                $param = json_encode($obj->data);
                if($param == "{}")
                {
                    $param = "";
    
                }
    
            $requestPayload = strtolower($param);
            $hashedPayload = hash($alg, $requestPayload);
    
            $canonical_uri = $uri;
            $canonical_querystring = '';
    
            $canonical_headers = "content-type:"."application/json"."\n"."host:".$host."\n"."x-amz-date:".$amzdate."\n"."x-amz-security-token:".$token."\n";
            $signed_headers = 'content-type;host;x-amz-date;x-amz-security-token';
            $canonical_request = "".$method."\n".$canonical_uri."\n".$canonical_querystring."\n".$canonical_headers."\n".$signed_headers."\n".$hashedPayload;
    
    
            $credential_scope = $amzdate2 . '/' . $region . '/' . $service . '/' . 'aws4_request';
            $string_to_sign  = "".$algorithm."\n".$amzdate ."\n".$credential_scope."\n".hash('sha256', $canonical_request)."";
           //string_to_sign is the answer..hash('sha256', $canonical_request)//
    
            $kSecret = 'AWS4' . $secretKey;
            $kDate = hash_hmac( $alg, $amzdate2, $kSecret, true );
            $kRegion = hash_hmac( $alg, $region, $kDate, true );
            $kService = hash_hmac( $alg, $service, $kRegion, true );
            $kSigning = hash_hmac( $alg, 'aws4_request', $kService, true );     
            $signature = hash_hmac( $alg, $string_to_sign, $kSigning ); 
            $authorization_header = $algorithm . ' ' . 'Credential=' . $access_key . '/' . $credential_scope . ', ' .  'SignedHeaders=' . $signed_headers . ', ' . 'Signature=' . $signature;
    
            $headers = [
                        'content-type'=>'application/json', 
                        'x-amz-security-token'=>$token, 
                        'x-amz-date'=>$amzdate, 
                        'Authorization'=>$authorization_header];
            return $headers;
    
        }
    

相关问题