Exemplo n.º 1
0
 /**
  * Signs request with signature version 4
  *
  * @param   Request      $request     Http Request
  * @param   string       $region      optional Overrides region as destination region for multi-regional operations
  * @param   string       $file        optional Path to the file transmitted in request for signature calculation
  *
  * @throws  QueryClientException
  */
 protected function signRequestV4($request, $region = null, $file = null)
 {
     $time = time();
     //Gets the http method name
     $httpMethod = $request->getRequestMethod();
     //Region is mandatory part for this type of authentication
     $region = $region ?: $this->getAws()->getRegion();
     //Gets host from the url
     $components = parse_url($request->getRequestUrl());
     $crd = gmdate('Ymd', $time) . '/' . $region . '/' . $this->getServiceName() . '/aws4_request';
     $opt = ['X-Amz-Algorithm' => 'AWS4-HMAC-SHA256', 'X-Amz-Credential' => $this->awsAccessKeyId . '/' . $crd, 'X-Amz-Date' => gmdate('Ymd\\THis\\Z', $time), 'X-Amz-Expires' => '86400'];
     $headers = ['X-Amz-Date' => $opt['X-Amz-Date']];
     //Calculating canonicalized query string
     $c11dQueryString = '';
     if (!empty($components['query'])) {
         $pars = (new QueryString($components['query']))->toArray();
         ksort($pars);
         $c11dQueryString = http_build_query($pars, null, '&', PHP_QUERY_RFC3986);
     }
     //Calculating payload
     if ($httpMethod == 'PUT' && isset($file)) {
         $headers['X-Amz-Content-Sha256'] = hash_file('sha256', $file);
     }
     if (!isset($headers['X-Amz-Content-Sha256'])) {
         $headers['X-Amz-Content-Sha256'] = hash('sha256', $request->getRawBody());
     }
     //Adding x-amz headers
     $request->addHeaders($headers);
     //Calculating canonical headers
     $allHeaders = $request->getHeaders();
     $allHeaders['X-Amz-SignedHeaders'] = 'host';
     $signedHeaders = ['host' => $components['host']];
     foreach ($allHeaders as $k => $v) {
         $lk = strtolower($k);
         //This x-amz header does not have to be signed
         if ($lk == 'x-amz-signedheaders') {
             continue;
         }
         if (preg_match('/x-amz-/i', $k) || $lk == 'content-type' || $lk == 'content-md5') {
             $signedHeaders[$lk] = $v;
         }
     }
     ksort($signedHeaders);
     $allHeaders['X-Amz-SignedHeaders'] = join(';', array_keys($signedHeaders));
     $canonicalHeaders = '';
     foreach ($signedHeaders as $k => $v) {
         $canonicalHeaders .= $k . ':' . $v . "\n";
     }
     $canonicalRequest = $httpMethod . "\n" . $components['path'] . "\n" . $c11dQueryString . "\n" . $canonicalHeaders . "\n" . $allHeaders['X-Amz-SignedHeaders'] . "\n" . $headers['X-Amz-Content-Sha256'];
     $stringToSign = $opt['X-Amz-Algorithm'] . "\n" . $opt['X-Amz-Date'] . "\n" . $crd . "\n" . hash('sha256', $canonicalRequest);
     $dateKey = hash_hmac('sha256', gmdate('Ymd', $time), "AWS4" . $this->secretAccessKey, true);
     $dateRegionKey = hash_hmac('sha256', $region, $dateKey, true);
     $dateRegionServiceKey = hash_hmac('sha256', $this->getServiceName(), $dateRegionKey, true);
     $signingKey = hash_hmac('sha256', 'aws4_request', $dateRegionServiceKey, true);
     //X-Amz-Signature
     $signature = hash_hmac('sha256', $stringToSign, $signingKey);
     $headers['Authorization'] = $opt['X-Amz-Algorithm'] . ' ' . 'Credential=' . $opt['X-Amz-Credential'] . ',' . 'SignedHeaders=' . $allHeaders['X-Amz-SignedHeaders'] . ',' . 'Signature=' . $signature;
     $request->addHeaders($headers);
 }