Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
66
Task/ADFGVX-cipher/Python/adfgvx-cipher.py
Normal file
66
Task/ADFGVX-cipher/Python/adfgvx-cipher.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"""
|
||||
The ADFGVX cipher implemented as a Python class
|
||||
See also eg. https://www.nku.edu/~christensen/092hnr304%20ADFGVX.pdf
|
||||
"""
|
||||
|
||||
from random import shuffle, choice
|
||||
from itertools import product, accumulate
|
||||
from numpy import floor, sqrt
|
||||
|
||||
class ADFGVX:
|
||||
""" The WWI German ADFGVX cipher. """
|
||||
def __init__(self, spoly, k, alph='ADFGVX'):
|
||||
self.polybius = list(spoly.upper())
|
||||
self.pdim = int(floor(sqrt(len(self.polybius))))
|
||||
self.key = list(k.upper())
|
||||
self.keylen = len(self.key)
|
||||
self.alphabet = list(alph)
|
||||
pairs = [p[0] + p[1] for p in product(self.alphabet, self.alphabet)]
|
||||
self.encode = dict(zip(self.polybius, pairs))
|
||||
self.decode = dict((v, k) for (k, v) in self.encode.items())
|
||||
|
||||
def encrypt(self, msg):
|
||||
""" Encrypt with the ADFGVX cipher. """
|
||||
chars = list(''.join([self.encode[c] for c in msg.upper() if c in self.polybius]))
|
||||
colvecs = [(lett, chars[i:len(chars):self.keylen]) \
|
||||
for (i, lett) in enumerate(self.key)]
|
||||
colvecs.sort(key=lambda x: x[0])
|
||||
return ''.join([''.join(a[1]) for a in colvecs])
|
||||
|
||||
def decrypt(self, cod):
|
||||
""" Decrypt with the ADFGVX cipher. Does not depend on spacing of encoded text """
|
||||
chars = [c for c in cod if c in self.alphabet]
|
||||
sortedkey = sorted(self.key)
|
||||
order = [self.key.index(ch) for ch in sortedkey]
|
||||
originalorder = [sortedkey.index(ch) for ch in self.key]
|
||||
base, extra = divmod(len(chars), self.keylen)
|
||||
strides = [base + (1 if extra > i else 0) for i in order] # shuffled column lengths
|
||||
starts = list(accumulate(strides[:-1], lambda x, y: x + y)) # shuffled starts of columns
|
||||
starts = [0] + starts # starting index
|
||||
ends = [starts[i] + strides[i] for i in range(self.keylen)] # shuffled ends of columns
|
||||
cols = [chars[starts[i]:ends[i]] for i in originalorder] # get reordered columns
|
||||
pairs = [] # recover the rows
|
||||
for i in range((len(chars) - 1) // self.keylen + 1):
|
||||
for j in range(self.keylen):
|
||||
if i * self.keylen + j < len(chars):
|
||||
pairs.append(cols[j][i])
|
||||
|
||||
return ''.join([self.decode[pairs[i] + pairs[i + 1]] for i in range(0, len(pairs), 2)])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
PCHARS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
|
||||
shuffle(PCHARS)
|
||||
POLYBIUS = ''.join(PCHARS)
|
||||
with open('unixdict.txt') as fh:
|
||||
WORDS = [w for w in (fh.read()).split() \
|
||||
if len(w) == 9 and len(w) == len(set(list(w)))]
|
||||
KEY = choice(WORDS)
|
||||
|
||||
SECRET, MESSAGE = ADFGVX(POLYBIUS, KEY), 'ATTACKAT1200AM'
|
||||
print(f'Polybius: {POLYBIUS}, key: {KEY}')
|
||||
print('Message: ', MESSAGE)
|
||||
ENCODED = SECRET.encrypt(MESSAGE)
|
||||
DECODED = SECRET.decrypt(ENCODED)
|
||||
print('Encoded: ', ENCODED)
|
||||
print('Decoded: ', DECODED)
|
||||
Loading…
Add table
Add a link
Reference in a new issue