将PHP SHA1转换为Ruby

时间:2014-02-05 04:42:05

标签: php ruby sha1

我在PHP中有这个算法:

$encoded_key = 'WHllcnRGYTY3eWpUNjQ'; 
$decoded_key = base64_decode($encoded_key); 
// XyertFa67yjT64 
$params_string = implode('', $params); 
//U215250.00121715620http://partner.domain.ru/order/U215/successhttp://partner.domain.ru/order/U215/fail 
$raw_signature = hash_hmac('sha1', $params_string, $decoded_key, true); 
// Byte-encoded, hex: c6881d8665afbb46a93a16b34bd152878a19ab3a 

$encoded_signature = base64_encode($raw_signature); 
// xogdhmWvu0apOhazS9FSh4oZqzo= 

我正在尝试将此代码移植到Ruby并获得相同的结果,但Base64和OpenSSL无法帮助我。有谁知道什么是错的?

1 个答案:

答案 0 :(得分:2)

一个问题是您使用的是HMAC.hexdigest而不是HMAC.digest。您的PHP代码生成一个原始HMAC,然后在base 64中对其进行编码。因此,您需要在Ruby中执行相同的操作。

另一个问题是密钥的基本64解码步骤。您输入的密钥未正确填充,因此将被Ruby的base 64库截断。例如:

encoded_key = "WHllcnRGYTY3eWpUNjQ"

Base64.decode64(encoded_key)
#=> "XyertFa67yjT"
# incomplete!

Base64.decode64("#{encoded_key}=\n")
#=> "XyertFa67yjT64"
# this is what you actually want

填充和最终换行确保基本64位编码数据完整,因为它标志着结束。但是,可以手动添加填充并假设数据已完成:

require 'base64'
require 'openssl'

def base64_pad(unpadded_str)
  padding = case unpadded_str.size % 3
    when 1 then "=="
    when 2 then "="
  end
  "#{unpadded_str}#{padding}\n"
end

encoded_key = "WHllcnRGYTY3eWpUNjQ"
key = Base64.decode64(base64_pad(encoded_key))
#=> "XyertFa67yjT64"

string = "U215250.00121715620http://partner.domain.ru/order/U215/successhttp://partner.domain.ru/order/U215/fail"

Base64.encode64(OpenSSL::HMAC.digest('SHA1', key, string))
#=> "xogdhmWvu0apOhazS9FSh4oZqzo=\n"