为什么Go生成的hmac哈希与PHP和JavaScript不同?

为什么Go生成的hmac哈希与PHP和JavaScript不同?,go,cryptography,hmac,Go,Cryptography,Hmac,我开始在Go中编写代码,并尝试通过检查客户端发送的签名来执行简单的请求验证。乍一看,一切都很好,但经过几次验证真实请求的测试后,我发现Go正在生成一个笨拙的散列 为了证明Go后端和JavaScript签名之间的不一致性,我开发了同一个sign方法的PHP版本,它给了我与JavaScript版本相同的结果,因此我的期望是正确的 我为每种语言开发了一个样本测试:,和 那么,要在Go中实现PHP和JavaScript的相同结果,我应该怎么做 去 输出 PHP 输出 JavaScript 输出 PHP函

我开始在Go中编写代码,并尝试通过检查客户端发送的签名来执行简单的请求验证。乍一看,一切都很好,但经过几次验证真实请求的测试后,我发现Go正在生成一个笨拙的散列

为了证明Go后端和JavaScript签名之间的不一致性,我开发了同一个sign方法的PHP版本,它给了我与JavaScript版本相同的结果,因此我的期望是正确的

我为每种语言开发了一个样本测试:,和

那么,要在Go中实现PHP和JavaScript的相同结果,我应该怎么做

去 输出 PHP 输出 JavaScript 输出
PHP函数的工作方式与Go函数不同

从PHP文档中:

返回一个字符串,该字符串包含以小写形式计算的消息摘要 除非raw_输出设置为true,否则为十六进制,在这种情况下,原始二进制 返回消息摘要的表示形式。当 algo是未知的

因此,在本例中,Go对HMAC和返回的原始字节进行编码。在PHP中,我假设JS是b64编码从hmac返回的十六进制字符串

要在go中获得相同的结果,请用十六进制编码[]字节,然后用base64编码它


然而,一般来说,最好的做法是对字节进行操作,而不是对字节进行编码。如果您必须遵循以前的设计,请继续,否则您应该使用PHP函数中允许的原始输出选项,并且应该得到相同的结果。

您的PHP函数与go函数的工作方式不同

从PHP文档中:

返回一个字符串,该字符串包含以小写形式计算的消息摘要 除非raw_输出设置为true,否则为十六进制,在这种情况下,原始二进制 返回消息摘要的表示形式。当 algo是未知的

因此,在本例中,Go对HMAC和返回的原始字节进行编码。在PHP中,我假设JS是b64编码从hmac返回的十六进制字符串

要在go中获得相同的结果,请用十六进制编码[]字节,然后用base64编码它


然而,一般来说,最好的做法是对字节进行操作,而不是对字节进行编码。如果您必须遵循以前的设计,请继续,否则您应该使用PHP函数中允许的原始输出选项,并且应该得到相同的结果。

问题是,您的PHP和JavaScript代码都这样做:Base64HexHmackey,msg。你真的不需要双重编码

在PHP中,您可以简单地请求原始_编码而不是十六进制编码:

$macSum = hash_hmac('sha256', $data, 'secret', true);
为此,您需要包括enc-base64.js组件

var data='我的名字叫丹尼尔'; var mac=CryptoJS.HmacSHA256data,“secret”; var macSum=mac.toString; var data64=mac.toStringCryptoJS.enc.Base64 文件。写'mac:'+macSum+'| b64:'+data64; var data64=btoa‘我的名字叫丹尼尔’ 文档。写'b64:'+data64;
问题是PHP和JavaScript代码都是这样做的:Base64HexHmackey,msg。你真的不需要双重编码

在PHP中,您可以简单地请求原始_编码而不是十六进制编码:

$macSum = hash_hmac('sha256', $data, 'secret', true);
为此,您需要包括enc-base64.js组件

var data='我的名字叫丹尼尔'; var mac=CryptoJS.HmacSHA256data,“secret”; var macSum=mac.toString; var data64=mac.toStringCryptoJS.enc.Base64 文件。写'mac:'+macSum+'| b64:'+data64; var data64=btoa‘我的名字叫丹尼尔’ 文档。写'b64:'+data64;
为什么你用base64编码十六进制编码,这只会使它们更长?为什么你用base64编码十六进制编码,这只会使它们更长?谢谢你,从你的解释我理解这个问题。谢谢你,从你的解释我理解这个问题。
$data = 'My name is Danniel';

$macSum = hash_hmac('sha256', $data, 'secret');
$data64 = base64_encode($macSum);
echo sprintf('mac: %s | b64: %s', $macSum, $data64) . "\n";

$data64 = base64_encode('My name is Danniel');
echo sprintf('b64: %s', $data64) . "\n";
mac: 36acd171ffc530b3efa3aefc35d0b9f0907c96038547ec2330d4030f04a46968 | b64: MzZhY2QxNzFmZmM1MzBiM2VmYTNhZWZjMzVkMGI5ZjA5MDdjOTYwMzg1NDdlYzIzMzBkNDAzMGYwNGE0Njk2OA==
b64: TXkgbmFtZSBpcyBEYW5uaWVs
var data = 'My name is Danniel';

var mac = CryptoJS.HmacSHA256(data, 'secret');
var macSum = mac.toString();
var data64 = btoa(macSum)
console.log('mac: ' + macSum + ' | b64: ' + data64);

var data64 = btoa('My name is Danniel')
console.log('b64: ' + data64);
"mac: 36acd171ffc530b3efa3aefc35d0b9f0907c96038547ec2330d4030f04a46968 | b64: MzZhY2QxNzFmZmM1MzBiM2VmYTNhZWZjMzVkMGI5ZjA5MDdjOTYwMzg1NDdlYzIzMzBkNDAzMGYwNGE0Njk2OA=="
"b64: TXkgbmFtZSBpcyBEYW5uaWVs"
$macSum = hash_hmac('sha256', $data, 'secret', true);
var data64 = mac.toString(CryptoJS.enc.Base64);