Skip to content

Instantly share code, notes, and snippets.

@romangrebennikov
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save romangrebennikov/60eaee612bc37715d87a to your computer and use it in GitHub Desktop.
Save romangrebennikov/60eaee612bc37715d87a to your computer and use it in GitHub Desktop.
scala-md5 for quest at thedeemon.livejournal.com/99218.html
name := "scala-md5"
version := "1.0"
scalaVersion := "2.11.6"
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.3.9"
libraryDependencies += "commons-codec" % "commons-codec" % "1.10"
package mdfive
import java.security.MessageDigest
import akka.actor.{Props, Actor, ActorSystem}
import org.apache.commons.codec.binary.Hex
import scala.annotation.tailrec
class RangeWorker(from:Array[Byte], to:Array[Byte]) extends Actor {
val digest = MessageDigest.getInstance("MD5")
@tailrec
private def nextPass(pass:Array[Byte], flipPosition:Int = 4):Array[Byte] = {
def nextChar(b:Byte):Byte = b match {
case 'z' => '0'
case '9' => 'a'
case c:Byte => (c+1).toByte
}
if (flipPosition < 1) {
null
} else if (pass(flipPosition) != '9') {
pass(flipPosition) = nextChar(pass(flipPosition))
pass
} else {
pass(flipPosition) = nextChar(pass(flipPosition))
nextPass(pass, flipPosition - 1)
}
}
// optimized version of hash compare
@tailrec
private def samehash(h1:Array[Byte], h2:Array[Byte], index:Int = 0):Boolean = {
if (index > 4)
true
else if (h1(index) != h2(index))
false
else
samehash(h1,h2,index+1)
}
def receive = {
case hash:Array[Byte] => {
var current = from
var found = false
while ((current != null) && !found) {
val currentHash = digest.digest(current)
if (samehash(hash, currentHash)) {
found = true
sender() ! Some(new String(current))
} else {
current = nextPass(current)
}
}
if (!found) sender() ! None
}
}
}
class Bruteforcer extends Actor {
val start = System.currentTimeMillis()
def ranges = Main.dic.map(c => Array(c,Main.start,Main.start,Main.start,Main.start) -> Array(c, Main.end, Main.end, Main.end, Main.end))
def receive = {
case hash:Array[Byte] =>
ranges.foreach {
case (from, to) =>
context.actorOf(Props(classOf[RangeWorker], from, to), name = s"worker_${new String(from)}_${new String(to)}") ! hash
}
case None => println(s"worker ${sender()} completed, no luck")
case Some(pass:String) => println(s"worker ${sender()} found password $pass, it took ${System.currentTimeMillis() - start}ms")
}
}
object Main {
val dic = "abcdefghijklmnopqrstuvwxyz0123456789".getBytes
val start = dic.head
val end = dic.last
def main(args: Array[String]) {
val system = ActorSystem.create("system")
val bf = system.actorOf(Props[Bruteforcer])
bf ! Hex.decodeHex("95ebc3c7b3b9f1d2c40fec14415d3cb8".toArray)
system.awaitTermination()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment