summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2014-11-30 16:19:22 -0800
committeriximeow <me@iximeow.net>2014-11-30 16:19:22 -0800
commite025738f13bf9612a39f907329a547fb8fc66ebe (patch)
tree6bfb509b4b43912e63b5ce9519ef76bf696b6e60
parent077b1df51f501ed44c7e9a421301174ac7efeaeb (diff)
Challenge 12
-rw-r--r--src/solvers/Challenge12.scala8
-rw-r--r--src/utils/CryptoUtils.scala50
-rw-r--r--test/Set2Spec.scala12
3 files changed, 29 insertions, 41 deletions
diff --git a/src/solvers/Challenge12.scala b/src/solvers/Challenge12.scala
index b37b5e3..0db336c 100644
--- a/src/solvers/Challenge12.scala
+++ b/src/solvers/Challenge12.scala
@@ -11,14 +11,18 @@ import ixee.cryptopals.utils.crypto._
import io.github.marklister.base64.Base64._
object Challenge12 {
- val path = "./data/10.txt"
-
lazy val mysteryText =
"""|Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg
|aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq
|dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg
|YnkK""".stripMargin.replace("\n", "").toByteArray
+ val expectation = """|Rollin' in my 5.0
+ |With my rag-top down so my hair can blow
+ |The girlies on standby waving just to say hi
+ |Did you stop? No, I just drove by
+ |""".stripMargin
+
val key = """|Copy your oracle function to a new function that
| encrypts buffers under ECB mode using a consistent
| but unknown key (for instance, assign a single
diff --git a/src/utils/CryptoUtils.scala b/src/utils/CryptoUtils.scala
index 6fe6b19..2678895 100644
--- a/src/utils/CryptoUtils.scala
+++ b/src/utils/CryptoUtils.scala
@@ -59,8 +59,9 @@ object CryptoUtils {
def extractUnknownViaEcbOracle(encrypt: Seq[Byte] => Seq[Byte]) = {
val blockSize = detectEcbBlockSize(encrypt)
+ val baseCiphertext = encrypt(Seq())
def blocksIn(xs: Seq[Byte]) = xs.length / blockSize
- val baseBlockCount = blocksIn(encrypt(Seq()))
+ val baseBlockCount = blocksIn(baseCiphertext)
def rainbow(prefix: Seq[Byte]): Map[Seq[Byte], Byte] = {
(0 to 255)
@@ -73,7 +74,7 @@ object CryptoUtils {
.toMap
}
- def postfixRainbow(prefix: Seq[Byte]): Map[Seq[Byte], Byte] = {
+ def suffixRainbow(prefix: Seq[Byte]): Map[Seq[Byte], Byte] = {
(0 to 255)
.map(_.toByte)
.map(_ +: prefix)
@@ -85,7 +86,7 @@ object CryptoUtils {
}
def probeFirstBlockAndPaddings: (Seq[Byte], Map[Int, Seq[Byte]]) = {
- def prefix(known: Seq[Byte]) = (" " * (blockSize - 1 - known.length)).asBytes
+ def prefix(known: Seq[Byte]) = ("@" * (blockSize - 1 - known.length)).asBytes
def genRainbow(known: Seq[Byte]) = rainbow(prefix(known) ++ known)
def firstCryptedBlock(known: Seq[Byte]) = encrypt(prefix(known)).take(blockSize).toSeq
def nextByte(known: Seq[Byte]) = genRainbow(known)(firstCryptedBlock(known))
@@ -102,13 +103,9 @@ object CryptoUtils {
// this will always be Some(_) because
// somewhere between 0..blockSize WILL grow the text.
- firstLargerCiphertext.get._2
+ blockSize - firstLargerCiphertext.get._2
}
- val lastBlockSize = probeLastBlockSize
-
- println("Last block is " + lastBlockSize + " bytes")
-
val (firstBlock, ciphertexts) = probeFirstBlockAndPaddings
/*
* zip together cipher blocks so that they look like
@@ -116,7 +113,7 @@ object CryptoUtils {
* rot0b1, rot1b1, rot2b1, ...
*
*/
- val cipherBlocks: Seq[(Int, Seq[Seq[Byte]])] = ciphertexts.toSeq.sortBy(_._1).map(_ :-> { x =>
+ val cipherBlocks = ciphertexts.toSeq.sortBy(_._1).map(_ :-> { x =>
x.grouped(16).toSeq
})
@@ -128,10 +125,8 @@ object CryptoUtils {
val middleBlocks = curr._2.take(baseBlockCount).tail
- (ac._1 :+ middleBlocks, ac._2 :+ maybeLastBlock)
- }) :-> { _.flatten }
-
- println(lastBlocks.mkString("\n"))
+ (ac._1 :+ middleBlocks, maybeLastBlock +: ac._2)
+ }) :-> { _.flatten :+ baseCiphertext.takeRight(16)}
def breakLastBlock(blocks: Seq[Seq[Byte]]) = {
/*
@@ -140,30 +135,12 @@ object CryptoUtils {
* Y X 14 14 14 14 ... 14
* ... pkcs7
*/
- blocks.foldLeft(Seq[Byte]()) { (bytes, block) => {
+ // drop the first block because it will be 16 16 16 16 16 16 ... 16
+ blocks.tail.foldLeft(Seq[Byte]()) { (bytes, block) => {
val postfix = pkcs7pad("?".asBytes ++ bytes, blockSize).tail
- val b = postfixRainbow(postfix)(block)
- println("Got " + b)
- bytes :+ b
+ suffixRainbow(postfix)(block) +: bytes
}}
}
- // val lastBlockBytes = crackLastBlock(lastBlocks)
-// println("Also...")
-// println(rainbow(firstBlock.tail)(middleBlocks(1)(0)))
-
- val prefix = firstBlock.tail
- val currRainbow = rainbow(prefix)
- println(middleBlocks(0)(0))//ciphertexts(0).drop(16).take(16))
- val next = currRainbow(middleBlocks(0)(0))
- println("Next: " + new String(Array(next.toByte)))
- val nowPrefix = (prefix.tail :+ next)
- val r2 = rainbow(nowPrefix)
- val next2 = r2(ciphertexts(1).drop(16).take(16).toSeq)
- println("Next: " + new String(Array(next2.toByte)))
- val pref3 = (nowPrefix.tail :+ next2)
- val r3 = rainbow(pref3)
- val next3 = r3(ciphertexts(2).drop(16).take(16).toSeq)
- println("Next: " + new String(Array(next3.toByte)))
def breakBlock(plaintext: Seq[Byte], padded: Seq[Seq[Byte]]): Seq[Byte] =
padded.foldLeft(Seq[Byte]()) { (blockText: Seq[Byte], block: Seq[Byte]) => {
@@ -174,10 +151,7 @@ object CryptoUtils {
val middleBytes =
middleBlocks.transpose.init.foldLeft(firstBlock) { (plaintext, padded: Seq[Seq[Byte]]) =>
- println("Block " + padded(0))
- val bytes = breakBlock(plaintext, padded)
- println(".... Done!")
- plaintext ++ bytes
+ plaintext ++ breakBlock(plaintext, padded)
}
middleBytes ++ breakLastBlock(lastBlocks)
diff --git a/test/Set2Spec.scala b/test/Set2Spec.scala
index 156949b..f17f459 100644
--- a/test/Set2Spec.scala
+++ b/test/Set2Spec.scala
@@ -74,7 +74,7 @@ class Set2Spec extends IxeeSpec {
}
- "Challenge 11: ECB/CBC detection" - {
+ "Challenge 11: ECB/CBC detection" in {
val input = "keke" * 32
@@ -84,6 +84,16 @@ class Set2Spec extends IxeeSpec {
}
+ "Challenge 12: ECB Decryption with user-specified prefix" - {
+
+ "Extracts an unknown suffix from encrypted data" in {
+
+ new String(Challenge12.run.toArray) mustBe Challenge12.expectation
+
+ }
+
+ }
+
}
}