8

我有一个Hash看起来像这样的数据结构():

{
    foo: "Test string",
    bar: [475934759, 5619827847]
}

我正在尝试从中创建一个校验和,Hash以检查将来是否相等。我尝试使用 的hash方法Hash,这产生了令人满意的漂亮哈希,但事实证明,在Hash重新启动解释器后,同样会产生不同的哈希。

我真的只是希望能够从Hash,StringArray实例创建一个 ~128 位校验和。

这可能吗?

4

3 回答 3

7

您可以根据对象的Marshal 转储JSON表示来计算您自己的哈希值。

这将计算 Marshal 转储的 MD5 哈希:

require 'digest/md5'

hash = {
  foo: "Test string",
  bar: [475934759, 5619827847]
}

Marshal::dump(hash)
#=> "\x04\b{\a:\bfooI\"\x10Test string\x06:\x06ET:\bbar[\ai\x04'0^\x1Cl+\b\x87\xC4\xF7N\x01\x00"

Digest::MD5.hexdigest(Marshal::dump(hash))
#=> "1b6308abdd8f5f6290e2825a078a1a02"

更新

您可以实施自己的策略,但我不建议更改核心功能:

class Hash
  def _dump(depth)
    # this doesn't cause a recursion because sort returns an array
    Marshal::dump(self.sort, depth)
  end

  def self._load(marshaled_hash)
    Hash[Marshal::load(marshaled_hash)]
  end
end

Marshal::dump({foo:1, bar:2})
#=> "\x04\bu:\tHash\e\x04\b[\a[\a:\bbari\a[\a:\bfooi\x06"

Marshal::dump({bar:2, foo:1})
#=> "\x04\bu:\tHash\e\x04\b[\a[\a:\bbari\a[\a:\bfooi\x06"

Marshal::load(Marshal::dump({foo:1, bar:2}))
#=> {:bar=>2, :foo=>1}
于 2013-10-15T11:56:29.323 回答
2

为了建立上面@Stefan 的答案,如果哈希的顺序很重要,请在将输出推送到 Mashall 之前对输出进行排序。

require 'digest/md5'

hash = {
  'foo'=> "Test string",
  'bar'=> [475934759, 5619827847]
}

puts Digest::MD5.hexdigest(Marshal::dump(hash.collect{|k,v| [k,v]}.sort{|a,b| a[0] <=> b[0]})) 
# 8509c564c0ae8dcb6c2b9b564ba6a03f

hash = {
  'bar'=> [475934759, 5619827847],
  'foo'=> "Test string"
}

puts Digest::MD5.hexdigest(Marshal::dump(hash.collect{|k,v| [k,v]}.sort{|a,b| a[0] <=> b[0]})) 
# 8509c564c0ae8dcb6c2b9b564ba6a03f 
于 2013-10-15T12:29:48.750 回答
1

如果您需要生成哈希内容的校验和,无论数据的顺序如何,使用 Marshal 或 sort 或其他技术都行不通。

到目前为止,我发现的唯一可靠方法如下:

require 'digest/md5'

hash1 = { "a" => 1, "b" => "2", c: { d: "3" } }
hash2 = { c: { d: "3" }, "a" => 1, "b" => "2" }

Digest::MD5.hexdigest(Marshal.dump(hash1)) # => "5def3b2cbdddd3aa6730b6d0527c2d79"
Digest::MD5.hexdigest(Marshal.dump(hash2)) # => "8155698ccfb05b8db01490e9b9634fd9"

Digest::MD5.hexdigest(hash1.to_s.chars.sort.join) # => "812bb65d65380fc1e620a9596806cc35"
Digest::MD5.hexdigest(hash2.to_s.chars.sort.join) # => "812bb65d65380fc1e620a9596806cc35"
于 2016-11-13T12:58:23.730 回答