Skip to content

Instantly share code, notes, and snippets.

@edbond
Last active August 29, 2015 14:19
Show Gist options
  • Save edbond/a2d3f22bf3e818e664c9 to your computer and use it in GitHub Desktop.
Save edbond/a2d3f22bf3e818e664c9 to your computer and use it in GitHub Desktop.
md5 bruteforce in Clojure
(ns asajax.core
(:require [clojure.core.async :as async :refer [go chan go-loop <! >!]])
(:import [java.security MessageDigest]
[java.util Arrays])
(:use [criterium.core])
(:gen-class :main true))
;;;;;
(set! *warn-on-reflection* true)
(def ^MessageDigest md (MessageDigest/getInstance "MD5"))
(def target-hash
(.digest md (.getBytes "zzzzz")))
(defn md5 [bs]
(.digest md bs))
(def alphabet "0123456789abcdefghijklmnopqrstuvwxyz")
;; (def alphabet "0z")
(def last-a (byte (last alphabet)))
(def first-b (byte (first alphabet)))
(def next-byte
(assoc
(into {}
(map #(vector (byte %1) (byte %2)) alphabet (drop 1 alphabet)))
(byte (last alphabet))
(byte (first alphabet))))
(defn prn-byte-array [ba]
(prn (map char ba)))
(defn next-candidate
"Mutate! c to next variant"
[^bytes c]
(loop [i 4]
(let [x (aget c i)]
(if (and (> i 0) (= last-a x))
(do
(aset c i ^Byte first-b)
(recur (dec i)))
(aset c i ^Byte (get next-byte x))))))
(defn candidates [prefix cb]
(let [end (.getBytes (str prefix "zzzz"))
cur (.getBytes (str prefix "0000"))]
;; (prn-byte-array cur)
;; (prn-byte-array end)
(loop []
(cb cur)
(next-candidate cur)
(if (Arrays/equals cur end)
(cb end)
(recur)))))
(defn worker [in-chan out-chan]
(let [md (MessageDigest/getInstance "MD5")]
(go-loop []
(when-let [prefix (<! in-chan)]
(candidates prefix
#(if (Arrays/equals #^bytes (.digest ^MessageDigest md %)
#^bytes target-hash)
(async/put! out-chan %)))
(recur)))))
(defn find-password []
(let [proc-count (+ 2 (.. Runtime getRuntime availableProcessors))
in-chan (chan proc-count)
out-chan (chan)]
(dotimes [n (dec proc-count)]
(worker in-chan out-chan))
(async/onto-chan in-chan
(map char alphabet)
true)
(println "Password: " (apply str (map char (async/<!! out-chan))))))
(defn -main [& args]
(println (time (find-password))))
;; (time (find-password))
;; Password: zzzzz
;; "Elapsed time: 4055.050952 msecs"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment