PHP hash_hmac()操作系统的区别

时间:2010-10-16 15:56:45

标签: php windows

我需要签署我的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表示正确的值转换为十六进制。 (它是调用中的原始二进制输出)

编辑2 我现在的猜测是,即使Windows 7操作系统是64位,PHP二进制文件编译为32位,因为我在php.net网站上找不到64位版本。

编辑3 我现在非常确定问题是二进制是32位。很可能Linux上的PHP使用操作系统版本来计算哈希,而Windows上的PHP实现了它自己的版本,即使两个操作系统都是64位,也会导致32/64位差异。

4 个答案:

答案 0 :(得分:3)

恭喜,欢迎来到精彩的终结世界。您遇到的问题是经典问题:* 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";

答案 1 :(得分:0)

您可以使用mhash()验证输出。它遵循相同的算法。

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

相当于

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

所以如果这两者之间没有区别,我猜测错误在于sha256的实现。无论哪种方式,这都是一个错误。在php.net上报告并要求新版本。

您还可以在两个平台上使用hash("sha256", "test");进行测试,以进一步调试哪个工作正常。 “test”应该成为9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

答案 2 :(得分:0)

自从我弄清问题以来,问题一直悬而未决,而且大多数问题通常都是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));

答案 3 :(得分:0)

请注意,对于亚马逊卖家网络服务,您的帖子字符串中的参数顺序也很重要,似乎他们有一个排序顺序,他们在内部维护所有post params,用于准备用于生成签名的字符串。如果你使用草图你可以得到参数的顺序,我没有注意到任何文档。

相关问题