Moved cracking files into directories
[cipher-tools.git] / cipherbreak.py
index 8a4d7b14942f2e9873eeb73b6ca270ba7ac21af7..0ac8ae57f7ed11a443dfedc8366ddc51086eda8c 100644 (file)
@@ -199,23 +199,27 @@ def keyword_break_worker(message, keyword, wrap_alphabet, fitness):
     return (keyword, wrap_alphabet), fit
 
 def monoalphabetic_break_hillclimbing(message, max_iterations=10000000, 
-        fitness=Pletters):
+        alphabet=None, fitness=Pletters):
     ciphertext = unaccent(message).lower()
-    alphabet = list(string.ascii_lowercase)
-    random.shuffle(alphabet)
-    alphabet = ''.join(alphabet)
+    if not alphabet:
+        alphabet = list(string.ascii_lowercase)
+        random.shuffle(alphabet)
+        alphabet = ''.join(alphabet)
     return monoalphabetic_break_hillclimbing_worker(ciphertext, alphabet,
                                                     max_iterations, fitness)
 
 def monoalphabetic_break_hillclimbing_mp(message, workers=10, 
-        max_iterations = 10000000, fitness=Pletters, chunksize=1):
+        max_iterations = 10000000, alphabet=None, fitness=Pletters, chunksize=1):
     worker_args = []
     ciphertext = unaccent(message).lower()
     for i in range(workers):
-        alphabet = list(string.ascii_lowercase)
-        random.shuffle(alphabet)
-        alphabet = ''.join(alphabet)
-        worker_args.append((ciphertext, alphabet, max_iterations, fitness))
+        if alphabet:
+            this_alphabet = alphabet
+        else:
+            this_alphabet = list(string.ascii_lowercase)
+            random.shuffle(this_alphabet)
+            this_alphabet = ''.join(this_alphabet)
+        worker_args.append((ciphertext, this_alphabet, max_iterations, fitness))
     with Pool() as pool:
         breaks = pool.starmap(monoalphabetic_break_hillclimbing_worker,
                               worker_args, chunksize)
@@ -465,6 +469,9 @@ def railfence_break(message, max_key_length=20,
     return max(results, key=lambda k: k[1])
 
 def amsco_break(message, translist=transpositions, patterns = [(1, 2), (2, 1)],
+                                  fillstyles = [AmscoFillStyle.continuous, 
+                                                AmscoFillStyle.same_each_row, 
+                                                AmscoFillStyle.reverse_each_row],
                                   fitness=Pbigrams, 
                                   chunksize=500):
     """Breaks an AMSCO transposition cipher using a dictionary and
@@ -498,24 +505,26 @@ def amsco_break(message, translist=transpositions, patterns = [(1, 2), (2, 1)],
     (((2, 0, 5, 3, 1, 4, 6), (2, 1)), -997.0129085...)
     """
     with Pool() as pool:
-        helper_args = [(message, trans, pattern, fitness)
+        helper_args = [(message, trans, pattern, fillstyle, fitness)
                        for trans in translist.keys()
-                       for pattern in patterns]
+                       for pattern in patterns
+                       for fillstyle in fillstyles]
         # Gotcha: the helper function here needs to be defined at the top level
         #   (limitation of Pool.starmap)
         breaks = pool.starmap(amsco_break_worker, helper_args, chunksize) 
         return max(breaks, key=lambda k: k[1])
 
 def amsco_break_worker(message, transposition,
-        pattern, fitness):
+        pattern, fillstyle, fitness):
     plaintext = amsco_transposition_decipher(message, transposition,
-        fillpattern=pattern)
+        fillpattern=pattern, fillstyle=fillstyle)
     fit = fitness(sanitise(plaintext))
     logger.debug('AMSCO transposition break attempt using key {0} and pattern'
-                         '{1} gives fit of {2} and decrypt starting: {3}'.format(
-                             transposition, pattern, fit, 
+                         '{1} ({2}) gives fit of {3} and decrypt starting: '
+                         '{4}'.format(
+                             transposition, pattern, fillstyle, fit, 
                              sanitise(plaintext)[:50]))
-    return (transposition, pattern), fit
+    return (transposition, pattern, fillstyle), fit
 
 
 def hill_break(message, matrix_size=2, fitness=Pletters,