![](/img/trans.png)
[英]PHP: What is the difference between password_hash and 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.