summaryrefslogtreecommitdiff
path: root/test/Set1Spec.scala
blob: 7230d50844482c7cb9cf5016fc77f1a0c8aabf88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package ixee.cryptopals.test

import com.ixee.IxeeSpec

class Set1Spec extends IxeeSpec {

  import ixee.cryptopals.utils.ConversionUtils._
  import ixee.cryptopals.utils.ByteUtils._
  import ixee.cryptopals.utils.StreamUtils._
  import ixee.cryptopals.solvers._

  "Set1" - {

    "Challenge 1: converts from a hex string to base64" in {

      hexStr2Base64String(
        "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"
      ) mustBe(
        "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"
      )
    }

    "Challenge 2: xor's two equal-length buffers" in {

      val a = hexStr2Bytes(
        "1c0111001f010100061a024b53535009181c"
      )
      val b = hexStr2Bytes(
        "686974207468652062756c6c277320657965"
      )

      (a xor b).hex mustBe
        "746865206b696420646f6e277420706c6179"
    }

    "Challenge 3: single-byte xor cipher" in {
      XorDecrypt.findBestSingleByteKey(
        hexStr2Bytes(
          "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"
        )
      ) mustBe 88.toByte
    }

    "Challenge 4: detecting single-byte xor" - {
      "Decrypts and reports the line of the single-byte xor" in {
        Challenge4.run("./data/4.txt") mustBe
          (("Now that the party is jumping\n", 170))
      }
    }

    "Challenge 5: repeating-key xor" in {
      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

    }

    "Challenge 8: Detect ECB" in {

      Challenge8.run mustBe 133

    }
  }

}