我试图在coldfusion中模拟php函数。 Php输出如下;
<?php echo (strtoupper(hash_hmac('SHA256', 'a cow jumps over the moom', pack('H*','specialkey')))); ?>
E9C9E66592306F1BD27A3B1991C7650D4A8920D10E5FFDA955DA692225793F35
尝试CF时
<cfset z=hmac("a cow jumps over the moom", "specialkey","HMACSHA256")>
结果为1A905E37DC5F7544E170FB2D47743417AFC7CC0CE53188F30E78BC09D3A61ADF
显然与pack(H*
部分有关,就像我运行
<?php echo (strtoupper(hash_hmac('SHA256', 'a cow jumps over the moom', 'specialkey'))); ?>
结果是
1A905E37DC5F7544E170FB2D47743417AFC7CC0CE53188F30E78BC09D3A61ADF
如何在php中模拟pack(H*
?我需要在CF中返回结果E9C9E66592306F1BD27A3B1991C7650D4A8920D10E5FFDA955DA692225793F35
吗?
答案 0 :(得分:4)
虽然看起来双方都使用相同的密钥 - 但事实并非如此。
为了生成HMAC,PHP和CF必须首先将值解码为 binary ,并且该值实际上用作“密钥”。您获得不同结果的原因是双方正在以不同方式解码键值:PHP使用JVM默认值(即UTF-8,ASCII等)将其从hexadecimal解码为CF并将其解析为纯字符串。结果,PHP和CF生成完全不同的密钥,这就是HMAC代码不匹配的原因。
话虽如此,我注意到你的键值“specialkey”实际上并不是有效的十六进制字符串。所以在你花费大量时间在这之前,我的问题是PHP代码真的使用像“specialkey”这样的任意字符串,还是仅仅用于测试目的?如果实际代码使用有效的十六进制字符串,那么只需将二进制键传递给CF的HMAC函数,结果应该相同:
<强> ColdFusion的:强>
writeOutput( hmac("a cow jumps over the moom"
, binaryDecode("7370656369616c6b6579", "hex")
, "HMACSHA256"));
<强> PHP:强>
echo (strtoupper(hash_hmac('SHA256', 'a cow jumps over the moom', pack('H*','7370656369616c6b6579'))));
<强>结果:强>
1A905E37DC5F7544E170FB2D47743417AFC7CC0CE53188F30E78BC09D3A61ADF
更新:如果由于某种原因你确实需要使用任意字符串作为键,请查看Perl docs for pack(PHP函数所基于的)。
免责声明:我不是一个真正的PHP人,所以还有一点,但......基本上pack(H*)
将你的密钥字符串分成几对字符并将它们解释为十六进制。 “s”,“p”,“i”等无效字符转换为null或0:
sp --> 00 ("s" and "p" are invalid)
ec --> EC ("e" and "c" are valid hex)
ia --> 0A ("i" is invalid, "a" is valid)
lk --> 00 ("l" and "k" are both invalid)
ey --> E0 ("e" is valid, "y" is invalid)
生成的二进制文件是(十六进制):
00 EC 0A 00 E0
如果将该十六进制字符串解码为二进制并将其用作密钥:
hmac("a cow jumps over the moom", binaryDecode("00EC0A00E0", "hex"), "HMACSHA256")
CF返回与PHP相同的结果:
E9C9E66592306F1BD27A3B1991C7650D4A8920D10E5FFDA955DA692225793F35