summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/solvers/Challenge10.scala19
-rw-r--r--src/utils/CryptoUtils.scala8
-rw-r--r--src/utils/crypto/CBCCipher.scala8
-rw-r--r--test/Set2Spec.scala31
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
+
+ }
}
}