Last active
August 29, 2015 14:19
-
-
Save edbond/a2d3f22bf3e818e664c9 to your computer and use it in GitHub Desktop.
md5 bruteforce in Clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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