-2

So I have been given an assignment to recover an encryption key through the method of brute force. I know the keyspace is 2^16. I have the ciphertext, and I have the encryption/decryption algorithms. My problem is I have no clue how one would begin any sort of brute force attack. I don't require any cryptoanalysis from anyone, just maybe some tips and tricks, or a good resource anyone may know of that might help me realize my goal. This is my first time attempting anything like this. I'd really appreciate it guys. If it would helpful in determining what advice I'd need: The assignment code is given at https://engineering.purdue.edu/kak/compsec/ under lecture notes 2. "With BLOCKSIZE set to 16, the script EncryptForFun.py produces the following ciphertext output for a plaintext message that is a quote by Mark Twain: 20352a7e36703a6930767f7276397e376528632d6b6665656f6f6424623c2d\ 30272f3c2d3d2172396933742c7e233f687d2e32083c11385a03460d440c25 Recover the encryption key and decode the message"

  • 2
    The course of action for that brute force attack should be: make sure that you can successfully use the provided code/algorithm to encrypt some text of your choice to something in the format you have for the given ciphertext (but different values), and decrypt it back, for any 16-bit key of your choice. Then, for each possible $2^{16}$ key, apply that tested deciphering code to the given ciphertext, and find the (probably single) result that makes sense; that search could be by merely looking at the results, or comparing letter or bigram frequency to that of English. – fgrieu Feb 16 '17 at 07:43
  • Ok that bigram frequency part helps a lot. I wasn't sure how I'd implement code that could run through every key and know when to stop. I do have one more question though.. when I'm considering keys in the space 2^16, does that mean I'm merely checking every key between 0 and 2^16? Thanks a lot. @fgrieu – Krishneel Sahdeo Feb 16 '17 at 07:49
  • yes, to test the $2^{16}$ keys, you can make a loop over integer range $[0\dots2^{16}[$; but you might need to convert the index variable to whatever format the key use (like, from integer to array of 2 bytes). Note: the method of choice to detect the right plaintext may depend on the encryption algorithm; I have not examined this particular one. – fgrieu Feb 16 '17 at 08:30

1 Answers1

1

I solved it. I won't tell you the solution so that you can find it by yourself.

You only need to modify the file DecryptionForFun.py from the link you provide, to solve it. First, set the variable BLOCKSIZE to 16. Next, fix the ciphertext to be the string you have (instead of reading from file). In the part where it asks for a key, remove that and make a loop where you vary the key in the range(2**16). You need to define key_bv properly, basically it has to take a different value in each iteration. It should be something like key_bv = BitVector([0,0,0,0,...,0]) in the first iteration and everything 1 in the last iteration. Define key_bv depending on the integer from your key loop. ('bin' function from python may help)

Now you only need to know when to stop searching. I tried something very naive but it worked. I searched for the word "Mark" in the decrypted-text. Something like:

if "Mark" in outputtext: print outputtext; break

Run it and eventually it will stop!

Good luck, you can solve it!

Ambrona
  • 26
  • 3
  • Good thinking on the crib. – zaph Feb 17 '17 at 20:33
  • You are amazing! Thank you so much, I will take my next attempt at this tonight!! @Ambrona – Krishneel Sahdeo Feb 17 '17 at 23:38
  • @Ambrona So when I change key_bv to the bin representation of key, I get an error about strings not having size. I've also ran the program as is , changing only the key from 0-2**16, program finished with no successful decryption. Not sure where I'm going wrong here. – Krishneel Sahdeo Feb 18 '17 at 06:23
  • @Krishneel Sahdeo I only gave you a sketch on how to do it. I would say, the most important hint is that "Mark" appears in the plaintext, so that you know what to search for. You need to play with the python data-types. Don't give up after the first obstacle. I didn't know about the BitVector structure, but I realized you can initialite it by doing something like BitVector( bitlist = [0,0,1,0,1,0]). What I want to say is that you cannot use the "bin" function directly. You need to adapt the output. "bin(17)" returns the string "0b10001", so you probably want to remove the first two chars. – Ambrona Feb 18 '17 at 13:36
  • @Krishneel Sahdeo You could do something like:

    for key in range(65536):

    then you convert the key integer into string by

    key_str = bin(key)[2:]

    Note that you want this to have zeros on the left if the length is not 16, for example:

    key_str = '0'*(16-len(key_str)) + key_str

    – Ambrona Feb 18 '17 at 13:41
  • @Krishneel Sahdeo and now you can define the BitVector like: key_bv = BitVector( bitlist = [int(b) for b in key_str])

    It is just an example, there are several ways (probably more efficient/elegant).

    Btw, brute-forzing all the 65536 keys takes a while so I recommend you to print the key to know where it goes.

    – Ambrona Feb 18 '17 at 13:49
  • @Ambrona Hi! I managed to make it work thanks to you, long after the due date unfortunately. However, I fail to understand why the algorithm requires such an alteration? Why is it not enough the run the existing code as is, only modifying so that it cycles through every key? Sorry for all the questions, just genuinely confused. – Krishneel Sahdeo Feb 23 '17 at 09:02
  • I am glad you made it! Did you get the right sentence? I am not sure I understand your question. The single task was to try all keys. We did that, we modified the code so that it cycles through every key. The problem is that the 'key' object had the structure of a BitVector, that I think is not iterable (maybe it is), so we adapted the code to consider all possible values. – Ambrona Feb 24 '17 at 13:18