summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2014-11-26 18:10:58 -0800
committeriximeow <me@iximeow.net>2014-11-26 18:11:50 -0800
commit91b4cfc801b7c156c231ca60aba69a8d171e9226 (patch)
tree189262a5e86aea229374e9786edb08ff90d16d09 /src
parent31cac438b1571ba6ced29af4997cf9f1f5c3c6b7 (diff)
Challenge 8, 9
Diffstat (limited to 'src')
-rw-r--r--src/solvers/Challenge8.scala43
-rw-r--r--src/solvers/XorDecrypt.scala4
-rw-r--r--src/utils/ByteUtils.scala3
-rw-r--r--src/utils/ConversionUtils.scala2
-rw-r--r--src/utils/CryptoUtils.scala10
-rw-r--r--src/utils/StreamUtils.scala5
6 files changed, 64 insertions, 3 deletions
diff --git a/src/solvers/Challenge8.scala b/src/solvers/Challenge8.scala
new file mode 100644
index 0000000..5247075
--- /dev/null
+++ b/src/solvers/Challenge8.scala
@@ -0,0 +1,43 @@
+package ixee.cryptopals.solvers
+
+import scala.io.Source
+import ixee.cryptopals.utils.ByteUtils._
+import ixee.cryptopals.utils.StreamUtils._
+import ixee.cryptopals.utils.ConversionUtils._
+import ixee.cryptopals.utils.FunctionUtils._
+import ixee.cryptopals.utils._
+import io.github.marklister.base64.Base64._
+import javax.crypto.Cipher
+import javax.crypto.spec.SecretKeySpec
+
+object Challenge8 {
+ val path = "./data/8.txt"
+
+ lazy val ciphertext =
+ Source
+ .fromFile(path)
+ .getLines()
+ .toSeq
+ .map(hexStr2Bytes)
+ //.mkString
+ //.toByteArray
+
+ def run = {
+ ciphertext
+ .zipWithIndex
+ .map(x => (x._1.grouped(16).toStream, x._2 + 1)) //
+ // this might be decent, line #133 is #2 under this metric
+ // .map(x => (avgHammingDistance(x._1), x._2)).sortBy(_._1)
+ /*
+ * but looking for actual duplicate data is better:
+ * line 133 is #1 with six duplicate blocks,
+ * old #1 of 177 has 0 duplicate blocks.
+ */
+ .map(x => (dupBlocks(x._1), x._2)).sortBy(_._1 * -1)
+ .head
+ ._2
+ }
+
+ def dupBlocks(xs: Seq[Seq[Byte]]) =
+ pairsOf(xs).map(tup(_ == _)).count(_ == true)
+}
diff --git a/src/solvers/XorDecrypt.scala b/src/solvers/XorDecrypt.scala
index 83fa923..1a28637 100644
--- a/src/solvers/XorDecrypt.scala
+++ b/src/solvers/XorDecrypt.scala
@@ -30,7 +30,7 @@ object XorDecrypt {
}
def normalizedHammingDistanceForKeySize(xs: Seq[Byte], keySize: Int) = {
- val grouped = xs.grouped(keySize).toArray.dropRight(1)
+ val grouped = xs.grouped(keySize).toArray.init
// ez hack to drop non-`keySize` subcomponents of xs
(grouped.init zip grouped.tail).map(tup(hammingDistance(_, _))).reduce(_ + _) / (grouped.length - 1.0) / keySize
}
@@ -64,7 +64,7 @@ object XorDecrypt {
def findBestMultiByteKeyOfSize(keySize: Int)(ciphertext: Seq[Byte], inspectSet: Seq[Int] = Seq()): Seq[Byte] = {
// inspectSet is the set of key bytes for which we want debugging information
- ciphertext.grouped(keySize).toSeq.dropRight(1).transpose.zipWithIndex
+ ciphertext.grouped(keySize).toSeq.init.transpose.zipWithIndex
.map { case (byteCiphertext, idx) => {
if (inspectSet.contains(idx)) {
println("For idx = " + idx)
diff --git a/src/utils/ByteUtils.scala b/src/utils/ByteUtils.scala
index 18942c0..723164d 100644
--- a/src/utils/ByteUtils.scala
+++ b/src/utils/ByteUtils.scala
@@ -108,4 +108,7 @@ object ByteUtils {
def hammingDistance[T : BitOps : SizedNumeric](a: Seq[T], b: Seq[T]): Int =
(a xor b).map(_.bitsSet).reduce(_ @+ _)
+
+ def avgHammingDistance[T : BitOps : SizedNumeric](xs: Seq[Seq[T]]): Double =
+ xs.sliding(2).map({ case Stream(a: Seq[T], b: Seq[T]) => hammingDistance(a, b) }).reduce(_ @+ _) / xs.length.toDouble
}
diff --git a/src/utils/ConversionUtils.scala b/src/utils/ConversionUtils.scala
index 95d08ce..ec3f813 100644
--- a/src/utils/ConversionUtils.scala
+++ b/src/utils/ConversionUtils.scala
@@ -5,7 +5,7 @@ import FunctionUtils._
object ConversionUtils {
def hexStr2Bytes(s: String): Seq[Byte] =
- padToByte(s).grouped(2).map(byteStr2Byte).toSeq
+ padToByte(s).grouped(2).map(byteStr2Byte).toStream.force
def byteStr2Byte(str: String): Byte =
charSeq2Byte(str.toSeq)
diff --git a/src/utils/CryptoUtils.scala b/src/utils/CryptoUtils.scala
new file mode 100644
index 0000000..5418895
--- /dev/null
+++ b/src/utils/CryptoUtils.scala
@@ -0,0 +1,10 @@
+package ixee.cryptopals.utils
+
+object CryptoUtils {
+
+ def pkcs7pad(s: String, blockSize: Int) = {
+ val padLength = blockSize - (s.length % blockSize)
+ s + s"${padLength.toChar}" * padLength
+ }
+
+}
diff --git a/src/utils/StreamUtils.scala b/src/utils/StreamUtils.scala
index 4f803c0..be5246c 100644
--- a/src/utils/StreamUtils.scala
+++ b/src/utils/StreamUtils.scala
@@ -17,6 +17,11 @@ object StreamUtils {
def continuous[A](xs: Seq[A]): Stream[A] =
xs.to[Stream] append continuous(xs.to[Stream])
+ def pairsOf[A](xs: Seq[A]): Seq[(A, A)] =
+ (xs.init zip xs.tail.tails.toSeq) flatMap { case (elem, rest) =>
+ rest zip Stream.continually(elem)
+ }
+
/*
// Or just xs.to[Stream] ...
def fromSeq[A](xs: Seq[A]): Stream[A] =