2016-09-16 29 views
0

使用Nodejs,我試圖生成XML消息的HMAC SHA256,base64編碼的簽名。我目前有使用PHP的簽名生成工作。問題與使用HMAC的數據的base64編碼

該過程看起來相當簡單,我可以用Nodejs生成base64編碼的值,但由於某些原因,該值不匹配,並且比我使用PHP短得多。

下面,我已經包含了一個示例PHP腳本和結果以及Nodejs實現和結果。使用Nodejs,我使用本地加密模塊。

// PHP implementation 

$xml = <<<EOD 
<?xml version='1.0' encoding='UTF-8'?> 
<dataset> 
    <record> 
    <id>1</id> 
    <first_name>Carlos</first_name> 
    <last_name>Ruiz</last_name> 
    <email>[email protected]</email> 
    <gender>Male</gender> 
    <ip_address>156.225.191.154</ip_address> 
    </record> 
</dataset> 
EOD; 

$secret = 'secret'; 
$sig = base64_encode(hash_hmac('sha256', $xml, $secret)); 

echo $sig; 

結果: ODhkYTc1YmQzNzc0NWUyNDJlNjY3YTY1NzZhYzFhZGYwOTJlMTIxODdjNzYxOWYyNGQxNGExOGVkYTIyZDQ0ZQ==

// Nodejs implementation 

var crypto = require('crypto'); 

fs.readFile('example.xml', 'utf-8', function(err, data) { 
    function sig(str, key) { 
    return crypto.createHmac('sha256', key) 
     .update(str) 
     .digest('base64'); 
    } 
    console.log(sig(data, 'secret')); 
}); 

結果: iNp1vTd0XiQuZnpldqwa3wkuEhh8dhnyTRShjtoi1E4=

我花了一天時間試圖弄清楚這一點,一年使用堆棧溢出+後,這是我的第一次題。

任何援助將不勝感激!

+0

我在你的第一個例子中看到你的XML文件不是一個文件,而是一個字符串。那麼....'example.xml'中的實際xml是什麼?也就是說,sha256打印是256位或32字節,base64轉換大約3/4,因此我們應該期望base64 HMAC打印長度大約爲42個字符。因此,Node.js的結果肯定是*看起來正確的長度(43個字符,用'='填充以對齊到4個字節),而PHP字符串絕對不會。它* waaaaay *太長了。 –

+0

感謝您的答覆,從mscdex的答案我能弄清楚我需要做什麼。正如他解釋的,在我的例子中,hash_hmac返回一個十六進制編碼的字符串,然後進行base64編碼。使用這些信息,我能夠通過使用'hex'作爲摘要來獲取我的nodejs代碼,轉換爲一個字符串並將該字符串編碼爲base64。 – oudelitonalituridalp

+0

只要你非常清楚**你沒有生成base64編碼的HMAC值,而是一個兩倍的字符串,這是你的軟件中優秀的睡眠錯誤。使消費代碼期望base64編碼的真正SHA-256 HMAC值是一個無限更好的解決方案。 –

回答

0

的這裏的問題是,PHP的hash_hmac()默認返回一個十六進制編碼的字符串(見$raw_output參數here),所以你的base64編碼的十六進制字符串,而不是實際的原始二進制結果。

所以更改此設置:

$sig = base64_encode(hash_hmac('sha256', $xml, $secret)); 

到:

$sig = base64_encode(hash_hmac('sha256', $xml, $secret, true)); 
+0

感謝您的回覆!我曾經想過,PHP是以某種/預期的方式運行的,我沒有想到要深入研究這方面的事情。 從你的答案,我能夠通過使用'十六進制'作爲摘要,轉換爲字符串和base64編碼,得到所需的結果。 – oudelitonalituridalp