OpenSSL::HMAC.hexdigest PHP 等价物不会打印与 ruby 相同的结果
OpenSSL::HMAC.hexdigest PHP equivalent won't print the same result as ruby one
这是一个 ruby 代码,我需要将其转换为 PHP :
print OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), 'hello', Base64.encode64('bonjour'))
输出:
62ac34e5d28563d6a50272d660805d1f8c791e41
这是我的 PHP 代码:
echo hash_hmac('sha1', base64_encode('bonjour'), 'hello');
输出:
89ebf8bd3d92bf3283aa4c5f24072820258367e4
我找不到 62ac34...
的方法。
我也试过了:
echo hash_hmac('sha1', 'bonjour', 'hello'); // 1
echo hash_hmac('sha1', 'hello', 'bonjour'); // 2
echo hash_hmac('sha1', base64_encode('hello'), 'bonjour'); // 3
echo hash_hmac('sha1', 'hello', base64_encode('bonjour')); // 4
echo base64_encode(hash_hmac('sha1', 'hello', 'bonjour', TRUE)); //5
错也。输出:
bed443484cc49c41c053a11dd15e44d4f79c524f // 1
16923f8d6e9afd345cf947fc963cad73aa12b76c // 2
8e5989976296c76f0462fe33c6bc2dec48bdcb5a // 3
ca237e79f77e6d9739db45fc5d162da3a4036639 // 4
FpI/jW6a/TRc+Uf8ljytc6oSt2w= // 5
我完全绝望了。
编辑
@Casper的回答并没有完全符合我的预期。对于像 bonjour
这样的简单字符串,没有问题。但是当我输入一些更复杂的字符串,json 字符串或更长的字符串 (> 60) 时,问题就出现了。
首先,下面是Base64 Ruby module:
encode64(bin)
Returns the Base64-encoded version of bin. This method complies with RFC 2045. Line feeds are added to every 60 encoded characters.
因此,为了在 PHP 中获得相同的 base64 编码数据,我需要在每 60 个编码字符以及字符串末尾插入 \n
。为此,PHP 提供了 chunk_split() 函数。
因此,这些命令输出相同的字符串:
chunk_split(base64_encode($json), 60, '\n'); // PHP
Base64.encode64(json) # Ruby
但这并没有解决我的问题
PHP和Ruby的结果还是不一样的:
PHP :
$json = '{"data":["bonjour"],"id":true,"price":false,"oper":null}';
$base64 = chunk_split(base64_encode($json), 60, '\n');
$hash = hash_hmac('sha1', $base64, 'bonjour');
// Ouput from var_dump()
eyJkYXRhIjpbImJvbmpvdXIiXSwiaWQiOnRydWUsInByaWNlIjpmYWxzZSwi\nb3BlciI6bnVsbH0=\n // $base64
fd044c309bea13396ed8df47b5c606d950222ceb // $hash
现在 Ruby :
json_body = '{"data":["bonjour"],"id":true,"price":false,"oper":null}'
encoded_body = Base64.encode64(json_body)
hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), 'bonjour', encoded_body)
# Ouput from puts var.inspect
eyJkYXRhIjpbImJvbmpvdXIiXSwiaWQiOnRydWUsInByaWNlIjpmYWxzZSwi\nb3BlciI6bnVsbH0=\n # base64
e168f9efe96e9424e22de765c72018c5a3f3437f # hash
注意 $base64
PHP 和 base64
Ruby 变量是相同的。
我做错了什么?我不知道 Ruby,puts
和 .inspect
是调试我的代码的最佳方式吗?
似乎 Ruby 正在向 base64 编码的字符串添加换行符,而 PHP 不是。
Ruby:
Base64.encode64('bonjour')
=> "Ym9uam91cg==\n"
PHP:
base64_encode('bonjour')
=> "Ym9uam91cg=="
所以现在我们知道如何在 PHP 中修复它了:
hash_hmac('sha1', base64_encode('bonjour') . "\n", 'hello');
=> "62ac34e5d28563d6a50272d660805d1f8c791e41"
或在 Ruby 中修复它:
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"),
'hello', Base64.encode64('bonjour').chomp)
=> "89ebf8bd3d92bf3283aa4c5f24072820258367e4"
第 2 部分
在 PHP 中,以及在 Ruby 中,'\n'
与 "\n"
不同。第一个产生两个字符(\
后跟 n
),第二个产生换行符。
因此,要修复您的代码,您需要在字符串中使用换行符,而不是斜线+n:
$base64 = chunk_split(base64_encode($json), 60, "\n");
^^^^
您还可以使用 gsub
从 Ruby base64 编码字符串中去除换行符,这意味着您不需要在 PHP 代码中使用任何技巧:
encoded_body = Base64.encode64(json_body).gsub("\n", '')
这是一个 ruby 代码,我需要将其转换为 PHP :
print OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), 'hello', Base64.encode64('bonjour'))
输出:
62ac34e5d28563d6a50272d660805d1f8c791e41
这是我的 PHP 代码:
echo hash_hmac('sha1', base64_encode('bonjour'), 'hello');
输出:
89ebf8bd3d92bf3283aa4c5f24072820258367e4
我找不到 62ac34...
的方法。
我也试过了:
echo hash_hmac('sha1', 'bonjour', 'hello'); // 1
echo hash_hmac('sha1', 'hello', 'bonjour'); // 2
echo hash_hmac('sha1', base64_encode('hello'), 'bonjour'); // 3
echo hash_hmac('sha1', 'hello', base64_encode('bonjour')); // 4
echo base64_encode(hash_hmac('sha1', 'hello', 'bonjour', TRUE)); //5
错也。输出:
bed443484cc49c41c053a11dd15e44d4f79c524f // 1
16923f8d6e9afd345cf947fc963cad73aa12b76c // 2
8e5989976296c76f0462fe33c6bc2dec48bdcb5a // 3
ca237e79f77e6d9739db45fc5d162da3a4036639 // 4
FpI/jW6a/TRc+Uf8ljytc6oSt2w= // 5
我完全绝望了。
编辑
@Casper的回答并没有完全符合我的预期。对于像 bonjour
这样的简单字符串,没有问题。但是当我输入一些更复杂的字符串,json 字符串或更长的字符串 (> 60) 时,问题就出现了。
首先,下面是Base64 Ruby module:
encode64(bin)
Returns the Base64-encoded version of bin. This method complies with RFC 2045. Line feeds are added to every 60 encoded characters.
因此,为了在 PHP 中获得相同的 base64 编码数据,我需要在每 60 个编码字符以及字符串末尾插入 \n
。为此,PHP 提供了 chunk_split() 函数。
因此,这些命令输出相同的字符串:
chunk_split(base64_encode($json), 60, '\n'); // PHP
Base64.encode64(json) # Ruby
但这并没有解决我的问题
PHP和Ruby的结果还是不一样的:
PHP :
$json = '{"data":["bonjour"],"id":true,"price":false,"oper":null}';
$base64 = chunk_split(base64_encode($json), 60, '\n');
$hash = hash_hmac('sha1', $base64, 'bonjour');
// Ouput from var_dump()
eyJkYXRhIjpbImJvbmpvdXIiXSwiaWQiOnRydWUsInByaWNlIjpmYWxzZSwi\nb3BlciI6bnVsbH0=\n // $base64
fd044c309bea13396ed8df47b5c606d950222ceb // $hash
现在 Ruby :
json_body = '{"data":["bonjour"],"id":true,"price":false,"oper":null}'
encoded_body = Base64.encode64(json_body)
hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), 'bonjour', encoded_body)
# Ouput from puts var.inspect
eyJkYXRhIjpbImJvbmpvdXIiXSwiaWQiOnRydWUsInByaWNlIjpmYWxzZSwi\nb3BlciI6bnVsbH0=\n # base64
e168f9efe96e9424e22de765c72018c5a3f3437f # hash
注意 $base64
PHP 和 base64
Ruby 变量是相同的。
我做错了什么?我不知道 Ruby,puts
和 .inspect
是调试我的代码的最佳方式吗?
似乎 Ruby 正在向 base64 编码的字符串添加换行符,而 PHP 不是。
Ruby:
Base64.encode64('bonjour')
=> "Ym9uam91cg==\n"
PHP:
base64_encode('bonjour')
=> "Ym9uam91cg=="
所以现在我们知道如何在 PHP 中修复它了:
hash_hmac('sha1', base64_encode('bonjour') . "\n", 'hello');
=> "62ac34e5d28563d6a50272d660805d1f8c791e41"
或在 Ruby 中修复它:
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"),
'hello', Base64.encode64('bonjour').chomp)
=> "89ebf8bd3d92bf3283aa4c5f24072820258367e4"
第 2 部分
在 PHP 中,以及在 Ruby 中,'\n'
与 "\n"
不同。第一个产生两个字符(\
后跟 n
),第二个产生换行符。
因此,要修复您的代码,您需要在字符串中使用换行符,而不是斜线+n:
$base64 = chunk_split(base64_encode($json), 60, "\n");
^^^^
您还可以使用 gsub
从 Ruby base64 编码字符串中去除换行符,这意味着您不需要在 PHP 代码中使用任何技巧:
encoded_body = Base64.encode64(json_body).gsub("\n", '')