繁体   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