In my code, I need to hash files using a variety of algorithms, including CRC32. Since I'm also using other cryptographic hash functions in the Digest
family, I thought it would be nice to maintain a consistent interface for them all.
For the record, I did find digest-crc
, a gem which does exactly what I want. The thing is, Zlib
is part of the standard library and has a working implementation of CRC32 that I'd like to reuse. Also, it is written in C so it should offer superior performance in relation to digest-crc
, which is a pure-ruby implementation.
Implementing Digest::CRC32
actually looked pretty straightforward at first:
%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
Everything looks right:
crc32 = File.open('Rakefile') { |f| Zlib.crc32 f.read }
digest = Digest::CRC32.file('Rakefile').digest!.to_i
crc32 == digest
=> true
Unfortunately, not everything works:
Digest::CRC32.file('Rakefile').hexdigest!
=> "313635393830353832"
# What I actually expected was:
Digest::CRC32.file('Rakefile').digest!.to_i.to_s(16)
=> "9e4a9a6"
hexdigest
basically returns Digest.hexencode(digest)
, which works with the value of the digest at the byte level. I'm not sure how that function works, so I was wondering if it is possible to achieve this with just the integer returned from Zlib.crc32
.