Ruby hexdigest sha1 pack('H *')字符串编码...

时间:2013-05-27 15:32:10

标签: ruby-on-rails ruby character-encoding pack digest

我遇到编码问题...控制台没有错误,但输出编码不好。 我必须对字符串使用Digest::SHA1.hexdigest,然后必须 pack结果。

下面的例子应该输出'{'p)ODýGÎ-£Iô8ü:iÀ'但它输出'{?p)OD?GΗ?I?8?:i?'在控制台和'{ p)OD G^BΗ I 8^D :i '在日志文件中。

所以,我的变量pack等于'{?p)OD?G?I?8?:我?'而不是'{'p)ODýGÎ-£Iô8ü:iÀ'。这是一个大问题......我在Rails任务中这样做。 任何想法的人?

由于

# encoding: utf-8
require 'digest/sha1'

namespace :my_app do
    namespace :check do
        desc "Description"

        task :weather => :environment do

            hexdigest = Digest::SHA1.hexdigest('29d185d98c984a359e6e6f26a0474269partner=100043982026&code=34154&profile=large&filter=movie&striptags=synopsis%2Csynopsisshort&format=json&sed=20130527')
            pack = [hexdigest].pack("H*")

            puts pack # => {?p)OD?GΗ?I?8?:i?
            puts '{´p)ODýGΗ£Iô8ü:iÀ' # => {´p)ODýGΗ£Iô8ü:iÀ

        end
    end
end

3 个答案:

答案 0 :(得分:0)

我认为由于调试从PHP到Ruby的转换的其他部分,这个“编码”问题已经出现。使用params摘要的目标API看起来会接受在Ruby中构造的签名变量,如下所示(编辑:这是猜测,在URI编码和base64默认值中Ruby和PHP之间也可能存在相关差异):< / p>

require 'digest/sha1'
require 'base64'
require 'uri'

sig_data = 'edhefhekjfhejk8edfefefefwjw69partne...'
sig = URI.encode( Base64.encode64( Digest::SHA1.digest( sig_data ) ) )
 => "+ZabHg22Wyf7keVGNWTc4sK1ez4=%0A"

正在签名的参数中sig_data的确切构造也很重要。这是由PHP方法http_build_query生成的,我不知道将适用于输入参数的顺序或转义。如果您的Ruby版本以不同的顺序获取它们,或者以不同的方式逃避PHP,则签名将是错误的(编辑:实际上我们可能会在此处查找发送API的确切查询字符串上的签名 - 我不知道)。这可能是一个问题,导致你陷入了如何构建签名的兔子洞?

答案 1 :(得分:0)

这就是我所做的(我从PHP转换为Ruby)

# encoding: utf-8
require 'open-uri'
require 'base64'
require 'digest/sha1'

class Allocine

    $_api_url = 'http://api.allocine.fr/rest/v3'
    $_partner_key
    $_secret_key
    $_user_agent = 'Dalvik/1.6.0 (Linux; U; Android 4.2.2; Nexus 4 Build/JDQ39E)'

    def initialize (partner_key, secret_key)
        $_partner_key = partner_key
        $_secret_key = secret_key
    end

    def get(id)
        # build the params
        params = {  'partner' => $_partner_key,
                    'code' => id,
                    'profile' => 'large',
                    'filter' => 'movie',
                    'striptags' => 'synopsis,synopsisshort',
                    'format' => 'json' }

        # do the request
        response = _do_request('movie', params)

        return response
    end

    private
    def _do_request(method, params)

        # build the URL
        query_url = $_api_url + '/' + method

        # new algo to build the query
        http_build_query = Rack::Utils.build_query(params)
        sed = DateTime.now.strftime('%Y%m%d')
        sig = URI::encode(Base64.encode64(Digest::SHA1.digest($_secret_key + http_build_query + '&sed=' + sed)))

        return sig
    end
end

然后致电

allocine = Allocine.new(ALLOCINE_PARTNER_KEY, ALLOCINE_SECRET_KEY)
puts allocine.get('any ID')

获取方法返回PHP中的'e7RwKU9E%2FUcCzpejSfQ4BPw6acA%3D'和Ruby中的'cPf6I4ZP0qHQTSVgdKTbSspivzg =%0A'...

再次感谢

答案 2 :(得分:0)

谢谢你们的帮助。 问题解决了。使用以下代码,我获得与PHP完全相同的字符串:

http_build_query = Rack::Utils.build_query(params)
sed = DateTime.now.strftime('%Y%m%d')
sig = CGI::escape(Base64.strict_encode64(Digest::SHA1.digest($_secret_key + http_build_query + '&sed=' + sed)))

现在我还有另一个问题,我打开了new question here

非常感谢你。