【问题标题】:Ruby hexdigest sha1 pack('H*') string encoding...Ruby hexdigest sha1 pack('H*') 字符串编码...
【发布时间】:2013-05-22 11:55:37
【问题描述】:

我遇到了一个编码问题...控制台中没有错误,但输出没有很好地编码。 我必须在字符串上使用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?:i?'而不是'{´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

【问题讨论】:

  • 你怎么知道输出应该是'{´p)ODýGΗ£Iô8ü:iÀ'。那应该是什么编码?
  • 我知道是因为我在 php 中执行了相同的脚本,并在浏览器中呈现。你可以看看bit.ly/bF6nNr的第二个参数我的铁路应用程序是utf8,我的服务器也是本地人。
  • 我不知道为什么你希望 pack 的结果是一个特定的 character 序列?通常对于像摘要这样的字节字符串,需要匹配特定的 byte 序列,并且需要使用明确定义的编码来发送或存储它(ASCII 中的十六进制摘要是一个简单但有空格的低效方案)。如果您确实希望将特定字符序列作为输出,然后编码为当前 Web 应用程序的输出,则在转换之前,您需要指定编码以将初始摘要字节解释为(我猜是 Latin-1)。
  • 在浏览器中渲染很容易破坏它,例如,如果您转储了一些原始字节并且浏览器将它们解释为 utf8
  • 注意hexdigestpack 行可以合并:Digest::SHA1.digest( data ) 在 Ruby 中是等价的,而且可能稍微快一些。

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


【解决方案1】:

这就是我所做的(我从 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')

get 方法在 PHP 中返回“e7RwKU9E%2FUcCzpejSfQ4BPw6acA%3D”,在 Ruby 中返回“cPf6I4ZP0qHQTSVgdKTbSspivzg=%0A”...

再次感谢

【讨论】:

    【解决方案2】:

    我认为这个“编码”问题的出现是由于调试了从 PHP 到 Ruby 的转换的其他部分。将消耗参数摘要的目标 API 看起来将接受在 Ruby 中构造的签名变量,如下所示(编辑:这是猜测,Ruby 和 PHP 在 URI 编码和 base64 默认值方面也可能存在相关差异): /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 的确切查询字符串的签名 - 我不知道)。可能是这样一个问题让您陷入了如何构建签名的兔子洞?

    【讨论】:

    • 好吧,我处理了参数的顺序。输入的字符串和 PHP 版本的完全一样……我把我的代码贴在下面了。
    • 好吧,我看不出 Ruby 和 PHP 有什么不同,但这可能只是因为我对 PHP 的了解不够。我有理由相信您的问题是 not 直接从摘要或 hexdigest/pack 中进行字符编码。
    • 谢谢你,尼尔,它现在可以工作了。下面回答。但是新的问题。如果您知道如何解决...再次感谢
    【解决方案3】:

    谢谢你们的帮助。 问题解决了。使用以下代码,我获得了与 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

    非常感谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 1970-01-01
      • 2014-03-03
      • 2015-08-25
      • 2021-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多