From e025738f13bf9612a39f907329a547fb8fc66ebe Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 30 Nov 2014 16:19:22 -0800 Subject: Challenge 12 --- src/solvers/Challenge12.scala | 8 +++++-- src/utils/CryptoUtils.scala | 50 +++++++++++-------------------------------- test/Set2Spec.scala | 12 ++++++++++- 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 + + } + + } + } } -- cgit v1.1