Cryptopals: 1-5 in python

Challenge 1-5 Implement repeating-key XOR

  • Link: Cryptopals 1-5
  • Resources: nothing new
  • Execution: python convert.py

Description

Here is the opening stanza of an important work of the English language:

1
2
Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal

Encrypt it, under the key “ICE”, using repeating-key XOR.

In repeating-key XOR, you’ll sequentially apply each byte of the key; the first byte of plaintext will be XOR’d against I, the next C, the next E, then I again for the 4th byte, and so on.

It should come out to:

1
2
0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272
a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f

Encrypt a bunch of stuff using your repeating-key XOR function. Encrypt your mail. Encrypt your password file. Your .sig file. Get a feel for it. I promise, we aren’t wasting your time with this.

Solution

Approach:

This isn’t a complicated one either. We already have all the pieces of code to do this in our library. There were some things that were tricky though. For example, the “expected result” had a newline in the middle of it splitting a hex char. That seemed sloppy to me. I’m fairly certain it was an accident that was not corrected since the result should not have a newline in it unless we are intentionally not XOR’ing control characters.

So the way I accomplished this one was to maintain a counter for the character position we are at in the key. A string can be an array of individual characters so we treat it this way. Another solution would be to use the modulo operator on the i counter to determine our position. Same thing to me.

At this point to weed out potential errors stemming from the arbitrarily placed “\n” in the expected output string, I added a check between the encoded hex and the expected hex. If they did not match, i would log the info so I could inspect it and see wtf was happening.

That’s essentially all there is to this one.

Full code:

 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
import sys
import heapq
import string

sys.path.append('lib')

from cryptopals import xor_string_with_key

original_string = """Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal"""
expected_string = """0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f"""

def main():
    key = "ICE"
    ascii_actual = ""
    print("original: {}").format(original_string)

    print("")
    str_len = len(original_string)
    key_len = len(key)
    k = 0
    for i in range(0, str_len, 1):
        e = i * 2
        hex_e = expected_string[e:e+2]
        ch_o = original_string[i]
        dec_o = ord(ch_o)
        hex_o = hex(dec_o)[2:]
        ch_k = key[k]
        dec_k = ord(ch_k)
        hex_k = hex(dec_k)[2:]
        hex_n = xor_string_with_key(hex_o, hex_k)
        ascii_actual += hex_n
        # print("{}: {} ^ {} {} = {}").format(i, ch_k, hex_o, hex_n, hex_e)
        k += 1
        if k == 3:
            k = 0

        if hex_n != hex_e:
            print("Mismatch xor!")
            print("character_original: {}").format(ch_o)
            print("hex_original: {}").format(hex_o)
            print("key: {}").format(ch_k)
            print("hex_new: {}").format(hex_n)
            print("hex_expected: {}").format(hex_e)

    print("actual == expected?")
    print("{}").format(ascii_actual)
    print("=")
    print("{}").format(expected_string)

    if ascii_actual == expected_string:
        print("SUCCESS")
    else:
        print("FAILURE")

if __name__ == "__main__":
    main()

Which yields the following output:

1
2
3
4
5
6
7
8
9
$ python convert.py
original: Burning 'em, if you ain't quick and nimble
I go crazy when I hear a cymbal

actual == expected?
0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f
=
0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f
SUCCESS
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy