11

I would like to be able to take an arbitrary string, run it through a hashing function (like MD5), and then interpret the resulting digest in base-36.

I know there already exists a Digest library in Ruby, but as far as I can tell I can't get at the raw bytes of a digest; the to_s function is mapped to hexdigest, which is, of course, base-16.

Shaggy Frog
  • 27,575
  • 16
  • 91
  • 128

2 Answers2

23

Fixnum#to_s accepts a base as the argument. So does string#to_i. Because of this, you can convert from the base-16 string to an int, then to base 36 string:

i = hexstring.to_i(16)
base_36 = i.to_s(36)
Sammy Larbi
  • 3,062
  • 3
  • 26
  • 21
  • Works great! But is it possible to extract the raw bytes of a Digest object somehow? – Shaggy Frog Mar 24 '11 at 00:14
  • Nothing built in that I know of, but this question/answer shows how you can convert a Fixnum or Bignum to it's 2's complement byte array: http://stackoverflow.com/questions/5284369/ruby-return-byte-array-containing-twos-complement-representation-of-bignum-fix – Sammy Larbi Mar 24 '11 at 12:01
  • For future reference; see my answer (currently below this one) to get the raw bytes of a digest. – Paul Annesley Dec 22 '11 at 04:40
3

You can access the raw digest bytes using Digest::Class#digest:

Digest::SHA1.digest("test")
# => "\xA9J\x8F\xE5\xCC\xB1\x9B\xA6\x1CL\bs\xD3\x91\xE9\x87\x98/\xBB\xD3"

Unfortunately from that point I'm not sure how to get it into base36 without first going via another number base like in Sammy Larbi's answer..

bytes = Digest::SHA1.digest("test")
Digest.hexencode(bytes).to_i(16).to_s(36)

Hopefully you can find a better way to go from raw bytes to base36.

Paul Annesley
  • 3,387
  • 22
  • 23