Lab 4 - Classical Ciphers and Frequency Analysis (Feb 7 - Feb 14, 2014)

So that you do not have to code everything yourself, I have written some helper code in this file codes.py. You can either cut and paste the necessary code into your program window, or load the whole module with the command import codes (after saving the file in your working directory). If you do import my code, functions can be called by codes.functionname(inputs). For example, if you want to use the slice function, the usage would be codes.slice('abcdefg', 3). (Alternatively, if you type from codes import slice you can call the function without the codes. prefix. Here is a summary of the functions you may want to use in this lab:

Task 1: Write a function weave(l), where l is a list of strings. This should be the inverse function of slice. Namely, if you write each string vertically as a column, weave should return the string you get from reading through the rows. Test this to make sure this gives you the inverse of the slice function, e.g., weave(slice('abcdefgh', 3)) should result in 'abcdefgh'.

Task 2: Write a function vigenere(s,key, decode=False) that performs a Vigenere encryption (or decryption if decode is set to True) on the string s with key key. (Here key should also be a string, e.g., 'vigenere'.) Test out encoding and decoding.

Task 3: Write a function test_shifts(s) that takes in a string s, computes the frequency distribution, and calculates the dot products of all cyclic shifts of the frequency distribution with the standard English frequency distribution (stored in the variable EF). Print out the amount of each possible shift, the corresponding letter, and the dot product. The highest dot product is the most likely shift. (Note: depending which way you shift, left or right, you might get the encryption shift key or decryption shift key.)

Task 4: Determine the key and plaintext for ciphertext C0a, which was encoded using a Vigenere cipher. You can use the vig_keylength function and either direct frequency counts (aug_freq may be useful here) or the test_shifts function. Personally I think the test_shifts function is a more accurate way to find the amount to shift by.

Task 5: Using the functions for frequency counts, digrams, trigrams and testsub functions, decode the ciphertext C0b, which was encodes using a substitution cipher (with the randsub function).

Lab 4 Homework (due with Homework 3)

  1. Turn in your code for the vigenere function. Test encryption on the plaintext 'aaabbbzzzy' with the key 'abc'. Test decryption on the resulting ciphertext.
  2. Turn in your code for the test_shifts function. Test it on the string 'a'.
  3. For the ciphertext C1 in the codes.py file, guess the method of encryption, determine the key and original plaintext using the above functions in Python. You should not print out your whole decryption session, but rather explain in words what you did and how you got the answer, possibly including a couple of key snippets from your Python decryption session.
  4. Do the same as the previous exercise for C2.


Labs Page
Course Home