diff options
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/CryptoUtils.scala | 77 | 
1 files changed, 66 insertions, 11 deletions
| diff --git a/src/utils/CryptoUtils.scala b/src/utils/CryptoUtils.scala index fc33220..6fe6b19 100644 --- a/src/utils/CryptoUtils.scala +++ b/src/utils/CryptoUtils.scala @@ -59,6 +59,8 @@ object CryptoUtils {    def extractUnknownViaEcbOracle(encrypt: Seq[Byte] => Seq[Byte]) = {      val blockSize = detectEcbBlockSize(encrypt) +    def blocksIn(xs: Seq[Byte]) = xs.length / blockSize +    val baseBlockCount = blocksIn(encrypt(Seq()))      def rainbow(prefix: Seq[Byte]): Map[Seq[Byte], Byte] = {        (0 to 255) @@ -71,6 +73,17 @@ object CryptoUtils {          .toMap      } +    def postfixRainbow(prefix: Seq[Byte]): Map[Seq[Byte], Byte] = { +      (0 to 255) +        .map(_.toByte) +        .map(_ +: prefix) +        .map(encrypt) +        .map(_.take(16).toSeq) +        .zipWithIndex +        .map(_ :-> { _.toByte } ) +        .toMap +    } +      def probeFirstBlockAndPaddings: (Seq[Byte], Map[Int, Seq[Byte]]) = {        def prefix(known: Seq[Byte]) = (" " * (blockSize - 1 - known.length)).asBytes        def genRainbow(known: Seq[Byte]) = rainbow(prefix(known) ++ known) @@ -82,18 +95,19 @@ object CryptoUtils {      }      def probeLastBlockSize: Int = { -      val baseBlockCount = encrypt(Seq[Byte]()).length        val firstLargerCiphertext = (0 until blockSize)          .map(" " * _).map(_.asBytes).map(encrypt)          .zipWithIndex -        .find(_._1.length != baseBlockCount) +        .find(x => blocksIn(x._1) != baseBlockCount)          // this will always be Some(_) because          // somewhere between 0..blockSize WILL grow the text.        firstLargerCiphertext.get._2      } -    println("Last block is " + probeLastBlockSize + " bytes") +    val lastBlockSize = probeLastBlockSize + +    println("Last block is " + lastBlockSize + " bytes")      val (firstBlock, ciphertexts) = probeFirstBlockAndPaddings      /* @@ -102,19 +116,45 @@ object CryptoUtils {       * rot0b1, rot1b1, rot2b1, ...       *       */ -    val transposed = ciphertexts.toSeq.sortBy(_._1).map(_ :-> { x => -      val y = x.grouped(16).toSeq -      println(y.length) -      y +    val cipherBlocks: Seq[(Int, Seq[Seq[Byte]])] = ciphertexts.toSeq.sortBy(_._1).map(_ :-> { x => +      x.grouped(16).toSeq      }) +    val (middleBlocks, lastBlocks) = +      cipherBlocks.foldLeft((Seq[Seq[Seq[Byte]]](), Seq[Option[Seq[Byte]]]()))( (ac, curr) => { +        val maybeLastBlock = +          if (curr._2.length > baseBlockCount) Some(curr._2.last) +          else None + +        val middleBlocks = curr._2.take(baseBlockCount).tail + +        (ac._1 :+ middleBlocks, ac._2 :+ maybeLastBlock) +      }) :-> { _.flatten } + +    println(lastBlocks.mkString("\n")) + +    def breakLastBlock(blocks: Seq[Seq[Byte]]) = { +      /* +       * plaintext looks something like... +       * X 15 15 15 15 15 ... 15 +       * Y X  14 14 14 14 ... 14 +       * ... pkcs7 +       */ +      blocks.foldLeft(Seq[Byte]()) { (bytes, block) => { +        val postfix = pkcs7pad("?".asBytes ++ bytes, blockSize).tail +        val b = postfixRainbow(postfix)(block) +        println("Got " + b) +        bytes :+ b +      }} +    } +    // val lastBlockBytes = crackLastBlock(lastBlocks)  //    println("Also...") -//    println(rainbow(firstBlock.tail)(transposed(1)(0))) +//    println(rainbow(firstBlock.tail)(middleBlocks(1)(0)))      val prefix = firstBlock.tail      val currRainbow = rainbow(prefix) -    println(ciphertexts(0).drop(16).take(16)) -    val next = currRainbow(ciphertexts(0).drop(16).take(16).toSeq) +    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) @@ -125,7 +165,22 @@ object CryptoUtils {      val next3 = r3(ciphertexts(2).drop(16).take(16).toSeq)      println("Next: " + new String(Array(next3.toByte))) -    firstBlock +    def breakBlock(plaintext: Seq[Byte], padded: Seq[Seq[Byte]]): Seq[Byte] = +      padded.foldLeft(Seq[Byte]()) { (blockText: Seq[Byte], block: Seq[Byte]) => { +        val prefix = (plaintext ++ blockText).takeRight(blockSize - 1) +        val b = rainbow(prefix)(block) +        blockText :+ b +      }} + +    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 +      } + +    middleBytes ++ breakLastBlock(lastBlocks)    }  } | 
