2015-04-30 18 views
5

我正在構建一個HMAC API,並且我有用爪測試哈希的問題。PHP和爪REST客戶端之間的哈希不相似

在爪子我有這樣的有效載荷:

GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout 

和一個自定義的HMAC-SHA256變量(實際運作like this設置它在X-哈希頭

X-Hash: 4Cq2yehWumDcUk1dYyfhm6qWjJVBkOCB8o12f5l0WGE= 

在我的PHP API。我有同樣的事情:

GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout 

和使用:

hash_hmac('sha256', $this->getPayload(), '9a6e30f2016370b6f2dcfb6880501d7f2305d69bout', false); 

所以比較哈希值時:

Paw: 4Cq2yehWumDcUk1dYyfhm6qWjJVBkOCB8o12f5l0WGE= 
PHP: 6961b9d1f6e986c49d963cbebd691fa68dfa59b4ce3b7f05320c2d43eae3c7c3 

他們有很大的不同。任何想法爲什麼是這樣?

更新

爪代碼:

function evaluate(context){ 
    var loc = getLocation(context.getCurrentRequest().url); 

    var payload = ""; 
    payload += context.getCurrentRequest().method + ':'; 
    payload += loc.pathname + ':'; 
    payload += JSON.stringify(context.getCurrentRequest().body) + ':'; 
    payload += "9a6e30f2016370b6f2dcfb6880501d7f2305d69bout"; // Private key 
    return payload; 
}; 

function getLocation(href) { 
    var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/); 
    return match && { 
     protocol: match[1], 
     host: match[2], 
     hostname: match[3], 
     port: match[4], 
     pathname: match[5], 
     search: match[6], 
     hash: match[7] 
    } 
} 

PHP代碼(有很多評論):

if (strpos(strtoupper($authHeader), 'HMAC') !== 0) { 
    echo 'out'; 
    throw new HttpForbiddenException(); 
} 
else { 
    $hmacSignature = $app->request->headers()->get('X-Hash'); 
    $publicKey = $app->request->headers()->get('X-Public'); 

    if (empty($hmacSignature) || empty($publicKey)) { 
     echo 'out2'; 
     throw new HttpForbiddenException(); 
    } 
    else { 

     $this->hmacManager->setPublicKey($publicKey); 
     print '$publickey = ' . $publicKey . '<br>'; 

     // Validate if base64_encoded or not 
     if(base64_decode($hmacSignature, true) !== FALSE) { 
      $binaryString = base64_decode($hmacSignature); 
      $hmacSignature = bin2hex($binaryString); 
      print 'decoding ' . '<br>'; 
     } 
     $this->hmacManager->setHmacSignature($hmacSignature); 
     print '$hmacSignature = ' . $hmacSignature . '<br>'; 

     $this->hmacManager->setRequestMethod($app->request->getMethod()); 
     print 'method = ' . $app->request->getMethod() . '<br>'; 
     $this->hmacManager->setRequestResourceUri($app->request->getResourceUri()); 
     print 'uri = ' . $app->request->getResourceUri() . '<br>'; 

     $requestBody = $app->request()->getBody(); 
     if (Utils::isJson($requestBody)) { 
      $requestBody = json_decode($requestBody); 
     } 
     $this->hmacManager->setRequestBody(json_encode($requestBody)); 
     print 'body = ' . json_encode($requestBody) . '<br>'; 

     print 'private key = ' . $this->hmacManager->getPrivateKey() . '<br>'; 

     $payload = ''; 
     $payload .= $this->hmacManager->getRequestMethod() . ":"; 
     $payload .= $this->hmacManager->getRequestResourceUri() . ":"; 
     $payload .= $this->hmacManager->getRequestBody() . ":"; 
     $payload .= $this->hmacManager->getPrivateKey(); 
     print 'PHP payload [' . $payload . ']'; 
     $this->hmacManager->setPayload($payload); 

     $hmacValue = $this->hmacManager->generateHmac(); 
     $isValid = $this->hmacManager->isValid($this->hmacManager->generateHmac(), $hmacSignature); 

     if ($isValid !== true) { 
      echo 'out3'; 
      throw new HttpForbiddenException(); 
     } 
    } 
} 

generateHmac從另一個類:

public function generateHmac() 
{ 
    print 'Generating HMAC' . '<br>'; 
    $algorithm = $this->getAlgorithm(); 
    print 'algo ' . $algorithm . '<br>'; 
    $privateKey = $this->getPrivateKey(); 
    print 'privk ' . $privateKey . '<br>'; 

    if (empty($algorithm)) { 
     throw new \RuntimeException('Algorithm must be set and not empty'); 
    } elseif (empty($privateKey)) { 
     throw new \RuntimeException('Private key must be set and not empty'); 
    } 

    print 'payload ' . $this->getPayload() . '<br>'; 
    $hash = hash_hmac($this->getAlgorithm(), $this->getPayload(), $this->getPrivateKey(), false); 
    print 'php hasj: ' . $hash . '<br>'; 

    return $hash; 
} 

最後,這裏是輸出報表:

$publickey = 95f97b93560f951b4cae46c86d03d9b1a81d4ae8 
decoding 
$hmacSignature = e02ab6c9e856ba60dc524d5d6327e19baa968c954190e081f28d767f99745861 

method = GET 
uri = /hello/world 
body = "" 
private key = 9a6e30f2016370b6f2dcfb6880501d7f2305d69bout 
PHP payload [GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout] 

Generating HMAC 
algo sha256 
privk 9a6e30f2016370b6f2dcfb6880501d7f2305d69bout 
payload GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout 
php hash: 6961b9d1f6e986c49d963cbebd691fa68dfa59b4ce3b7f05320c2d43eae3c7c3 

希望它有幫助!

回答

4

爪子散列是base64編碼,而PHP的是十六進制。所以先解碼爪子散列:

$binary = base64_decode($pawHash); 
$hex = bin2hex($binary); 

然後將它與你自己的散列進行比較。

+0

我不能做相反的事嗎?在發送Paw之前解碼生成的散列,以便我的API保持原樣?或者也許檢測它是否是base64編碼的? – Vallieres

+0

仍然無法正常工作。我喜歡你說的(並檢查是否base64_decode(str,true)!== FALSE)以確保它是一個base64字符串,但它現在給我這個哈希:e02ab6c9e856ba60dc524d5d6327e19baa9​​68c954190e081f28d767f99745861仍然與我在PHP中有很大不同。 – Vallieres

+0

如果沒有看到代碼的其餘部分,很難說出可能的問題。例如,它可能是有效負載的問題。即使一個微小的差異和哈希看起來完全不同。 –