From 6268e2c446d6d54b43668d859184d6f3a779fa3a Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 28 Nov 2014 03:40:17 -0800 Subject: Fix challenge 10 specs --- src/solvers/Challenge10.scala | 19 +++---------------- src/utils/CryptoUtils.scala | 8 ++++++++ src/utils/crypto/CBCCipher.scala | 8 +++++++- test/Set2Spec.scala | 31 +++++++++++++++++++++++++++++-- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/solvers/Challenge10.scala b/src/solvers/Challenge10.scala index 7880327..abc99f9 100644 --- a/src/solvers/Challenge10.scala +++ b/src/solvers/Challenge10.scala @@ -2,6 +2,7 @@ package ixee.cryptopals.solvers import scala.io.Source import ixee.cryptopals.utils.ByteUtils._ +import ixee.cryptopals.utils.CryptoUtils._ import ixee.cryptopals.utils.StreamUtils._ import ixee.cryptopals.utils.ConversionUtils._ import ixee.cryptopals.utils.FunctionUtils._ @@ -21,23 +22,9 @@ object Challenge10 { .toByteArray def run = { - def cbcBuilder = SchemeBuilder("AES", "YELLOW SUBMARINE".asBytes) + def builder = SchemeBuilder("AES", "YELLOW SUBMARINE".asBytes) .cbc(Stream.continually(0.toByte).take(16)) - val encInstance = cbcBuilder.encrypt - val decInstance = cbcBuilder.decrypt - - val s = "fooo bar frobnicator the quick brown fox jumps over the lazy dog".asBytes - - println(s) - val enc = encInstance.end(s) - val dec = decInstance.end(enc) - println(enc) - println(dec) - println(dec.startsWith(s)) - - val decInstance2 = cbcBuilder.decrypt - - decInstance2.end(ciphertext) + new String(cbcDecrypt(builder)(ciphertext).toArray) } } diff --git a/src/utils/CryptoUtils.scala b/src/utils/CryptoUtils.scala index 6c2849e..54e5034 100644 --- a/src/utils/CryptoUtils.scala +++ b/src/utils/CryptoUtils.scala @@ -11,4 +11,12 @@ object CryptoUtils { s ++ Stream.continually(padLength.toByte).take(padLength) } + def stripPkcs7Pad(s: Seq[Byte]): Seq[Byte] = + s.dropRight(s.last) + + def cbcEncrypt(builder: CbcBuilder)(data: Seq[Byte]) = + builder.encrypt.end(data) + + def cbcDecrypt(builder: CbcBuilder)(data: Seq[Byte]) = + stripPkcs7Pad(builder.decrypt.end(data)) } diff --git a/src/utils/crypto/CBCCipher.scala b/src/utils/crypto/CBCCipher.scala index 3bd0784..227b635 100644 --- a/src/utils/crypto/CBCCipher.scala +++ b/src/utils/crypto/CBCCipher.scala @@ -30,8 +30,14 @@ class CBCCipher(private[this] val cipher: Cipher, private[this] val iv: Seq[Byte // wouldn't hurt to invalidate this object afterward, but meh // TODO: strip padding! + // to do it right really requires writing decryption as its own part + // it's already obvious that's necessary, but to do padding stripping + // properly, the last block must be withheld until an end() call is made + // which is much different stateful behavior from encryption. + // + // in cryptoUtils for now. def end(): Seq[Byte] = - if (mode == Cipher.DECRYPT_MODE) + if (mode == Cipher.DECRYPT_MODE) Seq() else cipher.update((pkcs7pad(leftover, blockSize) xor state).toArray) def blockized(data: Seq[Byte]): (Seq[Seq[Byte]], Seq[Byte]) = diff --git a/test/Set2Spec.scala b/test/Set2Spec.scala index 7884b4e..d230a18 100644 --- a/test/Set2Spec.scala +++ b/test/Set2Spec.scala @@ -7,7 +7,9 @@ class Set2Spec extends IxeeSpec { import ixee.cryptopals.utils.ConversionUtils._ import ixee.cryptopals.utils.ByteUtils._ import ixee.cryptopals.utils.StreamUtils._ + import ixee.cryptopals.utils.CryptoUtils._ import ixee.cryptopals.utils._ + import ixee.cryptopals.utils.crypto.SchemeBuilder import ixee.cryptopals.solvers._ "Set2" - { @@ -23,7 +25,7 @@ class Set2Spec extends IxeeSpec { def challenge9spec(expected: Byte) = { val truncated = text.dropRight(expected) val padString = - CryptoUtils.pkcs7pad(truncated.toByteArray, 256).takeRight(expected) + pkcs7pad(truncated.asBytes, 256).takeRight(expected) val expectedPad = s"${expected.toChar}" * expected @@ -43,7 +45,32 @@ class Set2Spec extends IxeeSpec { "Challenge 10: Implement CBC mode" - { - + "encryption then decryption produces the original data" in { + + val text = """|what a nice string the quick brown fox + | and the lazy dog went for a jog in the park. + |In touch with the ground + |I'm on the hunt I'm after you + |Smell like I sound, I'm lost in a crowd + |And I'm hungry like the wolf + |Straddle the line in discord and rhyme + |I'm on the hunt I'm after you + |Mouth is alive with juices like wine + |And I'm hungry like the wolf + | the wolf ate both of them.""".stripMargin + + val builder = SchemeBuilder("AES", "foobar, a nice s".asBytes) + .cbc(Stream.from(10).take(16).map(_.toByte)) + + cbcDecrypt(builder)(cbcEncrypt(builder)(text.asBytes)) mustBe text.asBytes + + } + + "decrypts the example data" in { + + Challenge10.run mustBe Challenge6.expectation + + } } } -- cgit v1.1