#!/usr/bin/env python __author__ = "bt3gl" import string FREQ_ENGLISH = [0.0749, 0.0129, 0.0354, 0.0362, 0.1400, 0.0218, 0.0174, 0.0422, 0.0665, 0.0027, 0.0047, 0.0357, 0.0339, 0.0674, 0.0737, 0.0243, 0.0026, 0.0614, 0.0695, 0.0985, 0.0300, 0.0116, 0.0169, 0.0028, 0.0164, 0.0004] def delta(freq_word, freq_eng): # zip together the value from the text and the value from FREQ_EdiffGlist_freqISH diff = 0.0 for a, b in zip(freq_word, freq_eng): diff += abs(a - b) return diff def cipher(msg, key): # Make the cipher dec = '' for c in msg.lower(): if 'a' <= c <= 'z': dec += chr(ord('a') + (ord(c) - ord('a') + key) % 26) else: dec += c return dec def frequency(msg): # Compute the word frequencies dict_freq = dict([(c,0) for c in string.lowercase]) diff = 0.0 for c in msg: if 'a'<= c <= 'z': diff += 1 dict_freq[c] += 1 list_freq = dict_freq.items() list_freq.sort() return [b / diff for (a, b) in list_freq] def decipher(msg): # Decipher by frequency min_delta = 1000 best_rotation = 0 freq = frequency(msg) for key in range(26): d = delta(freq, FREQ_ENGLISH) if d < min_delta: min_delta = d best_rotation = key return cipher(msg, -best_rotation) def decipher_simple(msg): # very smart way of solving using translate and maketrans methods diff = (ord('t') - ord(s[0])) % 26 x = string.ascii_lowercase x = x[diff:] + x[:diff] ans = string.translate(s,string.maketrans(string.ascii_lowercase,x)) return ans if __name__ == '__main__': key = 13 text = 'hacker school is awesome!' cip = cipher(text, key) dec = decipher(cip) print "Cipher: " + cip print "Decipher: " + dec assert(text == dec)