簡體   English   中英

PHP hash_hmac()操作系統差異

[英]PHP hash_hmac() OS difference

我需要簽署我的Amazon Product API請求,執行此操作的可接受代碼如下。

base64_encode(hash_hmac('sha256', $request, $key, true));

當我在64位Linux上運行時,此方法效果很好,但在64位Windows 7上運行時卻失敗了。有沒有人知道如何調試hash_hmac為什么在64位Linux和64位Windows之間提供不同的輸出?

測試代碼:

<?php
$test = "GET
webservices.amazon.com
/onca/xml
AWSAccessKeyId=00000000000000000000&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=ItemAttributes%2COffers%2CImages%2CReviews&Service=AWSECommerceService&Timestamp=2009-01-01T12%3A00%3A00Z&Version=2009-01-06";
#echo $test;
echo base64_encode(hash_hmac('sha256', $test, '1234567890', true));

編輯上面的代碼的正確輸出是Nace+U3Az4OhN7tISqgs1vdLBHBEijWcBeCqL5xN9xg=錯誤的輸出是X0UTct9XSJ/3k2gu6noyKhTlksx5ZbH4qAbCyW3zX48=

非base64編碼的值是5f451372df57489ff793682eea7a322a14e592cc7965b1f8a806c2c96df35f8f表示不正確,而35a71ef94dc0cf83a137bb484aa82cd6f74b0470448a359c05e0aa2f9c4df718轉換為正確后的值是5f451372df57489ff793682eea7a322a14e592cc7965b1f8a806c2c96df35f8f (它是調用中的原始二進制輸出)

編輯2我現在的猜測是,即使Windows 7 OS是64位,PHP二進制文件也被編譯為32位,因為我在php.net網站上找不到64位版本。

編輯3我實際上現在很確定問題是二進制文件是32位的。 linux上的PHP最有可能使用OS版本來計算哈希,而Windows上的PHP實現了它自己的版本,即使兩個OS都是64位,也會導致32/64位的差異。

恭喜,歡迎來到行尾的美好世界。 您遇到的問題是一個經典的問題:* nix中的行尾為\\n ,而Windows中的行尾為\\r\\n 請嘗試以下操作:

$test = "GET\n".
"webservices.amazon.com\n".
"/onca/xml\n".
"AWSAccessKeyId=00000000000000000000&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=ItemAttributes%2COffers%2CImages%2CReviews&Service=AWSECommerceService&Timestamp=2009-01-01T12%3A00%3A00Z&Version=2009-01-06";

請注意,對於Amazon Seller Web Service,您的發布字符串中參數thats的順序也很重要,似乎它們具有對所有發布參數內部維護的排序順序,該順序用於准備以下字符串:用於生成簽名。 如果您使用畫板,則可以獲得參數的順序,我在任何文檔中都沒有注意到它。

您可以使用mhash()驗證輸出。 它遵循相同的算法。

 hash_hmac("sha256", "data", "key");

相當於

 bin2hex(mhash(MHASH_SHA256, "data", "key"));

因此,如果這兩者之間沒有區別,我推測錯誤在於sha256的實現。 無論哪種方式,這都是一個錯誤。 報告php.net並要求重新構建。

您還可以使用hash("sha256", "test"); 在兩個平台上進行調試,以進一步調試其中一個是否可以正常工作。 “測試”應變為9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

自從我弄清楚了這個問題后,就一直不願公開這個問題,很抱歉,就像大多數問題一樣,原來是PEBCAC。

答案不是32位還是64位,而是行尾。 Linux具有\\ n,而Windows具有\\ r \\ n。

將它們全部寫在一行上並顯式使用\\ n,它應該可以工作。

$test = "GET\nwebservices.amazon.com\n/onca/xml\nAWSAccessKeyId=00000000000000000000&ItemId=0679722769&Operation=ItemLookup&ResponseGroup=ItemAttributes%2COffers%2CImages%2CReviews&Service=AWSECommerceService&Timestamp=2009-01-01T12%3A00%3A00Z&Version=2009-01-06";
echo base64_encode(hash_hmac('sha256', $test, '1234567890', true));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM