HashDigest
Generates non-cryptographic digests of Hashes (and Arrays) indifferent to key type (string or symbol) and ordering.
Extracted from RemoteTable
.
Note plz
- You should use
HashDigest.digest3
for new applications.hexdigest
anddigest2
are legacy. -
digest2
is CASE SENSITIVE and has relatively high level of collisions - not recommended.
Example
Indifferent to key type
>> HashDigest.digest3(:a => 1)
=> "86eda770a6060824b090dd4df091e3bd4121279c"
>> HashDigest.digest3('a' => 1)
=> "86eda770a6060824b090dd4df091e3bd4121279c"
Indifferent to key order
>> HashDigest.digest3(:a => 1, 'b' => 2)
=> "d53cf64e768f4ef09c806bbe12258c78211b2690"
>> HashDigest.digest3(:b => 2, 'a' => 1)
=> "d53cf64e768f4ef09c806bbe12258c78211b2690"
Speed
If you're not on JRuby, having EscapeUtils
in your Gemfile
will make things much faster.
Algorithm
digest3
- Represent the hash as a URL querystring
- Sort by key
- SHA1 hexdigest
digest2 (deprecated and not recommended)
- Represent the hash as a URL querystring
- Sort by key
- MurmurHash3 V32 (this turned out to have too many collisions)
- Convert to base 36 to save space
Note: non-cryptographic and variable length. CASE SENSITIVE.
hexdigest (deprecated)
Basically represent the hash as a URL querystring, ordered by key, and MD5 that.
- Stringify keys
- Create an array of strings like "url_encode(key)=url_encode(value)" by going through each key in alphabetical order
- Join the array together with "&"
- MD5 hexdigest the joined string
To digest an array, just pretend it's a hash with keys like 1, 2, 3, etc.
Potential issues
- Meant for flat hashes, e.g. { :a => 1, :b => 2 } and not { :x => { :y => :z } }
Copyright
Copyright 2013 Seamus Abshere