Decode MD5, Brute Force

Haskell, 101 characters

import Data.Hash.MD5
main=interact$ \m->head.filter((==m).md5s.Str)$iterate([' '..'~']:)[]>>=sequence

Use it like so:

& ghc -O2 -o brute 42043-BruteForce.hs
& echo -n c-g | md5
bc098aea57599de26c8f17a9edbd492e
& echo -n bc098aea57599de26c8f17a9edbd492e | ./brute
c-g

This requires the common package MissingH.


PHP (155)

<?$a=[];function r($s){for($c=32;$c<127;$c++){$k=$s+chr($c);md5($k)=="92a7c9116fa52eb83cf4c2919599c24a"?die($k):array_push($a,$k)}r(array_shift($a))}r('');

Ungolfed:

<?
$a=[];
function r($s){
    for($c=32;$c<127;$c++){
        $k=$s+chr($c);
        md5($k)=="92a7c9116fa52eb83cf4c2919599c24a" ? die($k) : array_push($a,$k);
    }
    r(array_shift($a));
}
r('');

What it does is define an empty array $a, which will be our operations-to-do-later array. r is a recursive function and $s is the current string we're working with. We begin with an empty string, and loop through all the characters noted above, which are ASCII 32 to 127, and checking them all. While that happens, all of those are pushed onto the end of the array. Then, when all of the 1-length strings are done and all of them are put into the array, we now call r again with the first element in the array. Then, $s will be set to ASCII 32, and it will loop through 2 character strings that start with that character, checking them all and putting them at the end of the array. Since they are at the end, the next call to r will check ASCII 33 rather than them, since it is now the first one in the array. This prevents an infinite loop from occuring where it checks one ASCII 32 and then 2 ASCII 32's and then 3 ASCII 32's... etc.


Python (182 characters)

import sys,string as c,hashlib as h,itertools as i
m=sys.stdin.read()
j=''.join
print(next(j(v)for n in i.count()for v in i.product(*n*(c.printable,))if h.md5(j(v)).hexdigest()==m))

Example:

$ echo -n Hi! | md5sum
5360706c803a759e3a9f2ca54a651950  -
$ echo -n 5360706c803a759e3a9f2ca54a651950 | python2.7 decode.py
Hi!

The itertools module does most of the work, with .count() responsible for gradual escalation. The nested generator expression is filtered until we get a match on the MD5 hash.