Module: UrlHash

Defined in:
lib/url_hash.rb

Constant Summary collapse

DEFAULT_HASH_LENGTH =
8
ALGORITHM =
'aes-256-cfb8'

Class Method Summary collapse

Class Method Details

.from_hash(hash, options = {}) ⇒ Object

convert an hash, as produced by to_hash, back into the original integer

for example. UrlHash.to_hash(‘+xDdeave3’) -> 1001

options:

:key, :iv => provide these again if you are encrypting hashes


43
44
45
46
47
48
49
50
51
52
# File 'lib/url_hash.rb', line 43

def self.from_hash(hash, options = {})
  buffer = Base64.decode64(hash.tr("-", "+"))
  
  if (options.has_key? :key and options.has_key? :iv) 
    # encrypt the buffer
    buffer = self.encrypt(buffer, false, options)
  end
  
  buffer_to_int(buffer)
end

.to_hash(id, options = {}) ⇒ Object

convert an id (an integer) to a hash, a URL-compatible string.

for example. UrlHash.to_hash(1001) -> ‘+xDdeave3’

options:

:hash_length => how many characters to use for the hash. Defaults to 8.
  descreasing this increase the probability of a collision
:key, :iv => provide these two options if you want to encrypt the hash.
  otherwise, it will relatively trivial for users to predict your hashes,
  and to work out ids based on them. Decide for yourself if this is a problem.
  It is recommended to generate them using Digest::SHA2.hexdigest.


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/url_hash.rb', line 19

def self.to_hash(id, options = {})
  options = {:hash_length => DEFAULT_HASH_LENGTH}.merge(options)
  
  # buffers use all 256 bytes, hashes just 64, thus we can only use 3/4 the numbers
  #   -> 256 ** buffer_length <= 64 ** hash_length
  buffer_length = (3 * options[:hash_length] / 4).floor
  
  buffer = int_to_buffer(id, buffer_length)
  
  if (options.has_key? :key and options.has_key? :iv) 
    # encrypt the buffer
    buffer = self.encrypt(buffer, true, options)
  end
  
  # use -'s instead of + as we like that better
  Base64.encode64(buffer).tr("+", "-").strip
end