X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=docs%2Fszyfrow%2Fhill.html;fp=docs%2Fszyfrow%2Fhill.html;h=54e3c0474aa28b940c050992abb9e4da1f697256;hb=b535d9d75e69cc395e8de28c99e38564655e5ac9;hp=0000000000000000000000000000000000000000;hpb=f19a021eabb3222709b9d513839a14c01cfdfd38;p=szyfrow.git diff --git a/docs/szyfrow/hill.html b/docs/szyfrow/hill.html new file mode 100644 index 0000000..54e3c04 --- /dev/null +++ b/docs/szyfrow/hill.html @@ -0,0 +1,290 @@ + + + + + + +szyfrow.hill API documentation + + + + + + + + + + + +
+
+
+

Module szyfrow.hill

+
+
+
+ +Expand source code + +
import multiprocessing
+import numpy as np
+from numpy import matrix
+from numpy import linalg
+from szyfrow.support.utilities import *
+from szyfrow.support.language_models import *
+from szyfrow.affine import modular_division_table
+
+
+def hill_encipher(matrix, message_letters, fillvalue='a'):
+    """Hill cipher
+
+    >>> hill_encipher(np.matrix([[7,8], [11,11]]), 'hellothere')
+    'drjiqzdrvx'
+    >>> hill_encipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
+        'hello there')
+    'tfjflpznvyac'
+    """
+    n = len(matrix)
+    sanitised_message = sanitise(message_letters)
+    if len(sanitised_message) % n != 0:
+        padding = fillvalue[0] * (n - len(sanitised_message) % n)
+    else:
+        padding = ''
+    message = [pos(c) for c in sanitised_message + padding]
+    message_chunks = [message[i:i+n] for i in range(0, len(message), n)]
+    # message_chunks = chunks(message, len(matrix), fillvalue=None)
+    enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0] 
+            for c in message_chunks]
+    return cat([unpos(round(l))
+            for l in sum(enciphered_chunks, [])])
+
+def hill_decipher(matrix, message, fillvalue='a'):
+    """Hill cipher
+
+    >>> hill_decipher(np.matrix([[7,8], [11,11]]), 'drjiqzdrvx')
+    'hellothere'
+    >>> hill_decipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
+        'tfjflpznvyac')
+    'hellothereaa'
+    """
+    adjoint = linalg.det(matrix)*linalg.inv(matrix)
+    inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) % 26, 1]
+    inverse_matrix = (inverse_determinant * adjoint) % 26
+    return hill_encipher(inverse_matrix, message, fillvalue)          
+
+def hill_break(message, matrix_size=2, fitness=Pletters, 
+    number_of_solutions=1, chunksize=500):
+
+    all_matrices = [np.matrix(list(m)) 
+        for m in itertools.product([list(r) 
+            for r in itertools.product(range(26), repeat=matrix_size)], 
+        repeat=matrix_size)]
+    valid_matrices = [m for m, d in 
+        zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))
+                  if d != 0
+                  if d % 2 != 0
+                  if d % 13 != 0 ]
+    with multiprocessing.Pool() as pool:
+        helper_args = [(message, matrix, fitness)
+                       for matrix in valid_matrices]
+        # Gotcha: the helper function here needs to be defined at the top level
+        #   (limitation of Pool.starmap)
+        breaks = pool.starmap(hill_break_worker, helper_args, chunksize)
+        if number_of_solutions == 1:
+            return max(breaks, key=lambda k: k[1])
+        else:
+            return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]
+
+def hill_break_worker(message, matrix, fitness):
+    plaintext = hill_decipher(matrix, message)
+    fit = fitness(plaintext)
+    return matrix, fit
+
+if __name__ == "__main__":
+    import doctest
+
+
+
+
+
+
+
+

Functions

+
+
+def cat(iterable, /) +
+
+

Concatenate any number of strings.

+

The string whose method is called is inserted in between each given string. +The result is returned as a new string.

+

Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'

+
+
+def hill_break(message, matrix_size=2, fitness=<function Pletters>, number_of_solutions=1, chunksize=500) +
+
+
+
+ +Expand source code + +
def hill_break(message, matrix_size=2, fitness=Pletters, 
+    number_of_solutions=1, chunksize=500):
+
+    all_matrices = [np.matrix(list(m)) 
+        for m in itertools.product([list(r) 
+            for r in itertools.product(range(26), repeat=matrix_size)], 
+        repeat=matrix_size)]
+    valid_matrices = [m for m, d in 
+        zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))
+                  if d != 0
+                  if d % 2 != 0
+                  if d % 13 != 0 ]
+    with multiprocessing.Pool() as pool:
+        helper_args = [(message, matrix, fitness)
+                       for matrix in valid_matrices]
+        # Gotcha: the helper function here needs to be defined at the top level
+        #   (limitation of Pool.starmap)
+        breaks = pool.starmap(hill_break_worker, helper_args, chunksize)
+        if number_of_solutions == 1:
+            return max(breaks, key=lambda k: k[1])
+        else:
+            return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]
+
+
+
+def hill_break_worker(message, matrix, fitness) +
+
+
+
+ +Expand source code + +
def hill_break_worker(message, matrix, fitness):
+    plaintext = hill_decipher(matrix, message)
+    fit = fitness(plaintext)
+    return matrix, fit
+
+
+
+def hill_decipher(matrix, message, fillvalue='a') +
+
+

Hill cipher

+
>>> hill_decipher(np.matrix([[7,8], [11,11]]), 'drjiqzdrvx')
+'hellothere'
+>>> hill_decipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]),         'tfjflpznvyac')
+'hellothereaa'
+
+
+ +Expand source code + +
def hill_decipher(matrix, message, fillvalue='a'):
+    """Hill cipher
+
+    >>> hill_decipher(np.matrix([[7,8], [11,11]]), 'drjiqzdrvx')
+    'hellothere'
+    >>> hill_decipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
+        'tfjflpznvyac')
+    'hellothereaa'
+    """
+    adjoint = linalg.det(matrix)*linalg.inv(matrix)
+    inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) % 26, 1]
+    inverse_matrix = (inverse_determinant * adjoint) % 26
+    return hill_encipher(inverse_matrix, message, fillvalue)          
+
+
+
+def hill_encipher(matrix, message_letters, fillvalue='a') +
+
+

Hill cipher

+
>>> hill_encipher(np.matrix([[7,8], [11,11]]), 'hellothere')
+'drjiqzdrvx'
+>>> hill_encipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]),         'hello there')
+'tfjflpznvyac'
+
+
+ +Expand source code + +
def hill_encipher(matrix, message_letters, fillvalue='a'):
+    """Hill cipher
+
+    >>> hill_encipher(np.matrix([[7,8], [11,11]]), 'hellothere')
+    'drjiqzdrvx'
+    >>> hill_encipher(np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]]), \
+        'hello there')
+    'tfjflpznvyac'
+    """
+    n = len(matrix)
+    sanitised_message = sanitise(message_letters)
+    if len(sanitised_message) % n != 0:
+        padding = fillvalue[0] * (n - len(sanitised_message) % n)
+    else:
+        padding = ''
+    message = [pos(c) for c in sanitised_message + padding]
+    message_chunks = [message[i:i+n] for i in range(0, len(message), n)]
+    # message_chunks = chunks(message, len(matrix), fillvalue=None)
+    enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0] 
+            for c in message_chunks]
+    return cat([unpos(round(l))
+            for l in sum(enciphered_chunks, [])])
+
+
+
+def lcat(iterable, /) +
+
+

Concatenate any number of strings.

+

The string whose method is called is inserted in between each given string. +The result is returned as a new string.

+

Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'

+
+
+def wcat(iterable, /) +
+
+

Concatenate any number of strings.

+

The string whose method is called is inserted in between each given string. +The result is returned as a new string.

+

Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'

+
+
+
+
+
+
+ +
+ + + \ No newline at end of file