summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2014-11-26 00:41:46 -0800
committeriximeow <me@iximeow.net>2014-11-26 00:41:46 -0800
commit31cac438b1571ba6ced29af4997cf9f1f5c3c6b7 (patch)
tree882c5dd5346f246ad5487f0510ae182e14d42624
parent8b3cc4835c4c77df9f207bd342ffd024f0f726e7 (diff)
Challenge 7
-rw-r--r--data/7.txt64
-rw-r--r--src/solvers/Challenge7.scala36
-rw-r--r--test/Set1Spec.scala85
3 files changed, 185 insertions, 0 deletions
diff --git a/data/7.txt b/data/7.txt
new file mode 100644
index 0000000..c02ff8a
--- /dev/null
+++ b/data/7.txt
@@ -0,0 +1,64 @@
+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
diff --git a/src/solvers/Challenge7.scala b/src/solvers/Challenge7.scala
new file mode 100644
index 0000000..ee1745a
--- /dev/null
+++ b/src/solvers/Challenge7.scala
@@ -0,0 +1,36 @@
+package ixee.cryptopals.solvers
+
+import scala.io.Source
+import ixee.cryptopals.utils.ByteUtils._
+import ixee.cryptopals.utils.ConversionUtils._
+import ixee.cryptopals.utils.FunctionUtils._
+import ixee.cryptopals.utils._
+import io.github.marklister.base64.Base64._
+import javax.crypto.Cipher
+import javax.crypto.spec.SecretKeySpec
+
+object Challenge7 {
+ val path = "./data/7.txt"
+
+ lazy val ciphertext =
+ Source
+ .fromFile(path)
+ .getLines()
+ .toSeq
+ .flatten
+ .mkString
+ .toByteArray
+
+ val key = new SecretKeySpec(
+ "YELLOW SUBMARINE".asBytes.toArray,
+ "AES"
+ )
+
+ def run = {
+ val cipher = Cipher.getInstance(
+ "AES/ECB/PKCS5Padding"
+ )
+ cipher.init(Cipher.DECRYPT_MODE, key)
+ new String(cipher.doFinal(ciphertext))
+ }
+}
diff --git a/test/Set1Spec.scala b/test/Set1Spec.scala
index 628889c..b017803 100644
--- a/test/Set1Spec.scala
+++ b/test/Set1Spec.scala
@@ -6,6 +6,7 @@ class Set1Spec extends IxeeSpec {
import ixee.cryptopals.utils.ConversionUtils._
import ixee.cryptopals.utils.ByteUtils._
+ import ixee.cryptopals.utils.StreamUtils._
import ixee.cryptopals.solvers._
"Set1" - {
@@ -46,6 +47,90 @@ class Set1Spec extends IxeeSpec {
(("Now that the party is jumping\n", 170))
}
}
+
+ "Challenge 5: repeating-key xor" - {
+ val sourceText = """|Burning 'em, if you ain't quick and nimble
+ |I go crazy when I hear a cymbal""".stripMargin
+
+ val key = "ICE"
+
+ val ciphertext =
+ sourceText.asBytes.to[Stream] xor key.asBytes.to[Stream].continually
+
+ ciphertext.hex mustBe(
+ Seq(
+ "0b3637272a2b2e63622c2e69",
+ "692a23693a2a3c6324202d62",
+ "3d63343c2a26226324272765",
+ "272a282b2f20430a652e2c65",
+ "2a3124333a653e2b2027630c",
+ "692b20283165286326302e27",
+ "282f"
+ ).mkString("")
+ )
+ }
+
+ "Challenge 6: break repeating-key xor" - {
+
+ "hamming distance should be computed correctly" in {
+
+ val textA = "this is a test"
+ val textB = "wokka wokka!!!"
+
+ hammingDistance(textA, textB) mustBe 37
+
+ }
+
+ "prioritizes likely key sizes" in {
+
+ val sourceText =
+ """|the quick brown fox jumps over the lazy dog
+ |This code is going to turn out to be surprisingly useful later on.
+ |Breaking repeating-key XOR ("Vigenere") statistically is obviously
+ | an academic exercise, a "Crypto 101" thing. But more people "know
+ | how" to break it than can actually break it, and a similar
+ | technique breaks something much more important.""".stripMargin.replace("\n", "")
+
+ val key = "ICE IS REALLY NICE"
+
+ val ciphertext = sourceText.asByteStream xor key.asByteStream.continually
+
+ val expectedKeySize = XorDecrypt.inferKeySize(ciphertext)
+
+ expectedKeySize mustBe key.length
+
+ }
+
+ "cracks multi-byte keys" in {
+ val sourceText =
+ """|the quick brown fox jumps over the lazy dog
+ |This code is going to turn out to be surprisingly useful later on.
+ |Breaking repeating-key XOR statistically is obviously
+ | an academic exercise, a "Crypto 101" thing. But more people "know
+ | how" to break it than can actually break it, and a similar
+ | technique breaks something much more important.""".stripMargin.replace("\n", "")
+
+ val key = "ICE IS REALLY NICE"
+
+ val ciphertext = sourceText.asByteStream xor key.asByteStream.continually
+
+ XorDecrypt.findBestMultiByteKey(ciphertext).take(key.length).asAscii mustBe key
+
+ XorDecrypt.crackForMultiByteKey(ciphertext) mustBe sourceText
+ }
+
+ "cracks the challenge text" in {
+
+ Challenge6.run mustBe Challenge6.expectation
+
+ }
+ }
+
+ "Challenge 7: AES/ECB mode" in {
+
+ Challenge7.run mustBe Challenge6.expectation
+
+ }
}
}