Waiting for Singularity

Thoughts on science, tech and other preoccupations

Decode This Message - Part 2

Working with MD5 hashes

Take a crack at decoding another secret message:

Here is an MD5 hash, b354e9b8c7a5fb1e073670a28f957032. You need to write a ruby program that uses brute force to determine the String value of the hash. Whoever gets the value, along with a working Ruby program, first wins a delicious prize!

Hints: All lowercase letters, No spaces, No underscores, No numbers, No characters other than letters a-z, 6 characters long

According to The Ruby Way: Solutions and Techniques in Ruby Programming, Third Edition: “The MD5 message-digest algorithm produces a 128-bit fingerprint or message digest of a message of arbitrary length. This is in the form of a hash, so the encryption is one-way and does not allow for the discovery of the original message from the digest.”

MD5 hashes have been used for encoding passwords, credit cards numbers and other sensitive data into databases. An MD5 hash is NOT encryption but is a one-way transaction; for sufficiently long strings, it is almost impossible to reverse engineer an MD5 hash to retrieve the original.

Sounds like a challenge!

Solution in Ruby (1)

require 'digest/md5'

def make_word
  word = []
  letters = %w(a b c d e f g h i j k l m n o p q r s t u v w x y z)
  6.times do
    word << letters.sample
  end
  return word.join().to_s
end

def make_hash(word)
  Digest::MD5.hexdigest(word)
end

def brute_force(key)
  message = make_word
  coded_message = make_hash(message)

  if coded_message == key
    puts "The message is #{message}"
    return false
  end
end

while true
  brute_force('b354e9b8c7a5fb1e073670a28f957032')
end

Solution in Ruby (2)

require 'digest/md5'
key = 'b354e9b8c7a5fb1e073670a28f957032'

def make_words
  word_list = []
  letters = %w(a b c d e f g h i j k l m n o p q r s t u v w x y z)
  words = letters.permutation(6).to_a
  words.each do |word|
    word_list << word.join()
  end
  return word_list
end

def make_hash(word)
  Digest::MD5.hexdigest(word)
end

def brute_force(key)
  word_list = make_words
  while true
    word_list.each do |message|
      coded_message = make_hash(message)
      if coded_message == key
        puts "The message is #{message}"
        return false
      end
    end
  end
end

brute_force('b354e9b8c7a5fb1e073670a28f957032')

Output

$ ruby md5_decoder.rb
The message is mangia

Bonus: The 5-second solution

Chances are your hash has been cracked at MD5Decrypter with its database of 43 billion unique decrypted MD5 hashes.

Thanks to Eric Kelly of Launch Academy for the original MD5 challenge which can be found in this gist: Secret Prize.