diff options
Diffstat (limited to 'src/solvers')
| -rw-r--r-- | src/solvers/Challenge4.scala | 29 | ||||
| -rw-r--r-- | src/solvers/XorDecrypt.scala | 12 | 
2 files changed, 38 insertions, 3 deletions
diff --git a/src/solvers/Challenge4.scala b/src/solvers/Challenge4.scala new file mode 100644 index 0000000..f71f6c0 --- /dev/null +++ b/src/solvers/Challenge4.scala @@ -0,0 +1,29 @@ +package ixee.cryptopals.solvers + +import scala.io.Source +import ixee.cryptopals.utils.ByteUtils._ +import ixee.cryptopals.utils.ConversionUtils._ +import ixee.cryptopals.utils.FunctionUtils._ +import ixee.cryptopals.utils._ + +object Challenge4 { +  def findSingleCharacterXor(strings: Seq[Seq[Byte]]): (String, Int) = { +    strings +      .map(XorDecrypt.findBestSingleByteKey) +      .zip(strings) +      .zipWithIndex +      .map { pair => (pair._1._1, pair._1._2, pair._2) } +      .filter(_._1 != 0) +      .map { triplet => (XorDecrypt.decryptToAscii(triplet._2)(triplet._1), triplet._3) } +      .map { pair => (pair._1, TextScorer.score(pair._1.asBytes), pair._2) } +      .sortBy(_._2) +      .map { triplet => (triplet._1, triplet._3) } +      .head +  } + +  def run(inputFile: String) = { +    findSingleCharacterXor( +      Source.fromFile(inputFile).getLines().toSeq.map(hexStr2Bytes(_)) +    ) +  } +} diff --git a/src/solvers/XorDecrypt.scala b/src/solvers/XorDecrypt.scala index b7f7c43..6b82c34 100644 --- a/src/solvers/XorDecrypt.scala +++ b/src/solvers/XorDecrypt.scala @@ -2,18 +2,24 @@ package ixee.cryptopals.solvers  import ixee.cryptopals.utils._  import ixee.cryptopals.utils.ByteUtils._ +import ixee.cryptopals.utils.FunctionUtils._  object XorDecrypt {    implicit val freq = Frequencies.cornell40kSample -  def tryBestDecrypt(ciphertext: Seq[Byte]) = { -    val key = findBestSingleByteKey(ciphertext) +  def decryptToAscii(ciphertext: Seq[Byte])(key: Byte): String = {      new String((ciphertext xor Stream.continually(key)).toArray)    } +  def tryBestDecrypt(ciphertext: Seq[Byte]): String = { +    (findBestSingleByteKey _ :| decryptToAscii(ciphertext) _)(ciphertext) +  } +    def findBestSingleByteKey(ciphertext: Seq[Byte]): Byte =      candidates(ciphertext) -      .minBy(_._1)._2.toByte +      .reduceOption( (a: (Double, Int), b: (Double, Int)) => +        if (a._1 < b._1) a else b +      ).map(_._2.toByte).getOrElse(0.toByte)    def candidates(ciphertext: Seq[Byte]) =      (0 until 256)  | 
