Affine letter enciphering working
[cipher-tools.git] / cipher.py
index b3ab488db74c3af8090aefcc2396c2d503725064..7acaf6c36d76a44e6fa6ca3db1dfc9c4a2fd2804 100644 (file)
--- a/cipher.py
+++ b/cipher.py
@@ -17,6 +17,21 @@ def letter_frequencies(message):
         frequencies[letter]+=1
     return frequencies
 
+def scale_freq(frequencies):
+    total= sum(frequencies.values())
+    scaled_frequencies = collections.defaultdict(int)
+    for letter in frequencies.keys():
+        scaled_frequencies[letter] = frequencies[letter] / total
+    return scaled_frequencies
+
+def value_diff(frequencies1, frequencies2):
+    total= 0
+    for letter in frequencies1.keys():
+        total += abs(frequencies1[letter]-frequencies2[letter])
+    return total
+        
+    
+
 def caesar_cipher_letter(letter, shift):
     if letter in string.ascii_letters:
         if letter in string.ascii_lowercase:
@@ -37,3 +52,36 @@ def caesar_cipher_message(message, shift):
 
 def caesar_decipher_message(message, shift):
     return caesar_cipher_message(message, -shift)
+
+def affine_cipher_letter(letter, multiplier, shift, one_based=True):
+    if letter in string.ascii_letters:
+        if letter in string.ascii_lowercase:
+            alphastart = ord('a')
+        else:
+            alphastart = ord('A')
+        letter_number = ord(letter) - alphastart
+        if one_based: letter_number += 1  
+        enciphered_letter_number = letter_number * multiplier + shift
+        if one_based: enciphered_letter_number -=1
+        enciphered_letter = chr(enciphered_letter_number % 26 + alphastart)
+        return enciphered_letter
+    else:
+        return letter
+         
+
+
+
+def caesar_break(message):
+    best_key = 0
+    best_fit = float("inf")
+    for shift in range(26):
+        plaintxt = caesar_decipher_message(message, shift)
+        lettertxt = letter_frequencies(plaintxt)
+        total1 = scale_freq(lettertxt)
+        total2 = scale_freq(english_counts)
+        fit = value_diff(total2, total1)
+        if fit < best_fit:
+            best_key = shift
+            best_fit = fit
+    return best_key
+