7

在我的代码中,我需要使用各种算法(包括 CRC32)对文件进行哈希处理。由于我还在使用该Digest系列中的其他加密哈希函数,我认为为它们维护一个一致的接口会很好。

作为记录,我确实找到digest-crc了一个完全符合我要求的宝石。问题是,Zlib它是标准库的一部分,并且有一个我想重用的 CRC32 工作实现。此外,它是用 C 语言编写的,因此它应该提供与digest-crc纯 ruby​​ 实现相关的卓越性能。

Digest::CRC32起初实现实际上看起来很简单:

%w(digest zlib).each { |f| require f }

class Digest::CRC32 < Digest::Class
  include Digest::Instance

  def update(str)
    @crc32 = Zlib.crc32(str, @crc32)
  end

  def initialize; reset; end
  def reset; @crc32 = 0; end
  def finish; @crc32.to_s; end
end

一切看起来都正确:

crc32 = File.open('Rakefile') { |f| Zlib.crc32 f.read }
digest = Digest::CRC32.file('Rakefile').digest!.to_i
crc32 == digest
=> true

不幸的是,并非一切都有效:

Digest::CRC32.file('Rakefile').hexdigest!
=> "313635393830353832"

# What I actually expected was:
Digest::CRC32.file('Rakefile').digest!.to_i.to_s(16)
=> "9e4a9a6"

hexdigest基本上返回Digest.hexencode(digest)它与字节级别的摘要值一起使用。我不确定该函数是如何工作的,所以我想知道是否可以仅使用从Zlib.crc32.

4

3 回答 3

6

摘要期望摘要返回构成校验和的原始字节,即在 crc32 的情况下,构成该 32 位整数的 4 个字节。但是,您将返回一个包含该整数的以 10 为底的表示形式的字符串。

你想要类似的东西

[@crc32].pack('V')

将该整数转换为表示该整数的字节。一定要阅读 pack 及其各种格式说明符 - 有很多打包整数的方法取决于字节是否应该以本机字节序、大字节序、小字节序等形式呈现,所以你应该弄清楚哪个一个符合您的需求

于 2011-12-22T02:49:21.000 回答
3

它工作得很好,确保始终使用网络字节顺序,如下所示:

def finish; [@crc32].pack('N'); end
于 2014-10-03T22:22:24.263 回答
3

抱歉,这并不能真正回答您的问题,但它可能会有所帮助..

首先,在读取文件时,请确保传递“rb”参数。我可以看到您不在 Windows 上,但如果您的代码最终在 Windows 机器上运行,您的代码将无法正常工作,尤其是在读取 ruby​​ 文件时。示例:

crc32 = File.open('test.rb') { |f| Zlib.crc32 f.read }
#=> 189072290
digest = Digest::CRC32.file('test.rb').digest!.to_i
#=> 314435800
crc32 == digest
#=> false

crc32 = File.open('test.rb', "rb") { |f| Zlib.crc32 f.read }
#=> 314435800
digest = Digest::CRC32.file('test.rb').digest!.to_i
#=> 314435800
crc32 == digest
#=> true

以上将适用于所有平台和所有红宝石..我知道..但这不是你问的..

我很确定上面示例中的 hexdigest 和 digest 方法可以正常工作。

dig_file = Digest::CRC32.file('test.rb')

test1 = dig_file.hexdigest
#=> "333134343335383030"

test2 = dig_file.digest
#=> "314435800"

def hexdigest_to_digest(h)
  h.unpack('a2'*(h.size/2)).collect {|i| i.hex.chr }.join
end

test3 = hexdigest_to_digest(test1)
#=> "314435800"

所以我猜要么 .to_i.to_s(16) 正在抛出你的预期结果,或者你的预期结果可能是错误的?不确定,但一切顺利

于 2011-12-21T23:01:34.860 回答