I implemented the Enigma encryption machine that Jun Sakai introduced on Youtube. The reason for doing this coding this time is that I wanted to refer to the syntax of people in Silicon Valley and practiced objective implementation.
Sakai's Youtube is [here](https://www.google.com/url?sa=t&rct=j&q½esrc=s&source=web&cd=1cad=rja&uact=8&ved=2ahUKEwj45vTKnZPrAhVU_GEKHbb5C90QwqsBMAF6BAgKEAg&url=http .com% 2Fwatch% 3Fv% 3Dv1rUoMZRjoQ & usg = AOvVaw2IjXcPc1wjhqag1_kef6Ul). Also, it was interesting that Mr. Nakata of Oriental Radio explained about Enigma at Youtube University. = rja & uact = 8 & ved = 2ahUKEwiZs_uPnpPrAhVaPHAKHVqUCE0QwqsBMAB6BAgIEAQ & url = https% 3A% 2F% 2Fwww.youtube.com% 2Fwatch% 3Fv% 3D4zIXv1w3d80 & usg = Av0
The coding method was very helpful, and it was a lot of fun to do in my spare time. I actually made it this time, but it is not enough to post it on Github, and it was a waste not to post it, so I posted it as an article on Qiita. The code I implemented first by myself was a little dirty, so please refer to it if you like because I will put the code I implemented below while watching Mr. Sakai's video.
The file structure is as follows. Define the model objectively in enigma.py and build the model in main.py.
egnima
├── enigma.py
└── main.py
Enigma.py Create four classes: PlugBoard, Rotate, Reflector and Enigma. For details of each, I think you should refer to Mr. Sakai's Youtube or Wiki.
enigma.py
import string
ALPHABET = string.ascii_uppercase
class PlugBoard(object):
def __init__(self, map_alphabet):
self.alphabet = ALPHABET
self.forward_map = {}
self.backward_map = {}
self.mapping(map_alphabet)
def mapping(self, map_alphabet):
self.forward_map = dict(zip(self.alphabet, map_alphabet))
self.backward_map = {v: k for k , v in self.forward_map.items()}
def forward(self, index_num):
char = self.alphabet[index_num]
char = self.forward_map[char]
return self.alphabet.index(char)
def backward(self, index_num):
char = self.alphabet[index_num]
char = self.backward_map[char]
return self.alphabet.index(char)
class Rotor(PlugBoard):
def __init__(self, map_alphabet, offset=0):
super().__init__(map_alphabet)
self.offset = offset
self.rotations = 0
def rotate(self, offset=None):
if offset is None:
offset = self.offset
self.alphabet = self.alphabet[offset:] + self.alphabet[:offset]
self.rotations += offset
return self.rotations
def reset(self):
self.rotationations = 0
self.alphabet = ALPHABET
class Reflector(object):
def __init__(self, map_alphabet):
self.map = dict(zip(ALPHABET, map_alphabet))
for x, y in self.map.items():
if x != self.map[y]:
raise ValueError(x, y)
def reflect(self, index_num):
reflected_char = self.map[ALPHABET[index_num]]
return ALPHABET.index(reflected_char)
class Enigam(object):
def __init__(self, plug_board, rotors, reflector):
self.plug_board = plug_board
self.rotors = rotors
self.reflector = reflector
def encrypt(self, text):
return ''.join([self.go_through(c) for c in list(text)])
def decrypt(self, text):
for rotor in self.rotors:
rotor.reset()
return ''.join([self.go_through(c) for c in list(text)])
def go_through(self, char):
char = char.upper()
if char not in ALPHABET:
return char
index_num = ALPHABET.index(char)
index_num = self.plug_board.forward(index_num)
for rotor in self.rotors:
index_num = rotor.forward(index_num)
index_num = self.reflector.reflect(index_num)
for rotor in reversed(self.rotors):
index_num = rotor.backward(index_num)
index_num = self.plug_board.backward(index_num)
char = ALPHABET[index_num]
for rotor in reversed(self.rotors):
if rotor.rotate() % len(ALPHABET) != 0:
break
return char
main.py
main.py
import random
from enigma import PlugBoard, ALPHABET, Rotor, Reflector, Enigam
if __name__ == '__main__':
# outputs : XYGBWNSCMQFJLHEVRIZODAPUTK
get_random_alphabet = lambda : ''.join(
random.sample(ALPHABET, len(ALPHABET)))
p = PlugBoard(get_random_alphabet())
r1 = Rotor(get_random_alphabet(), 3)
r2 = Rotor(get_random_alphabet(), 2)
r3 = Rotor(get_random_alphabet(), 1)
# reflected alphabets list for the Rflection
r = list(ALPHABET)
indexes = [i for i in range(len(ALPHABET))]
for _ in range(int(len(indexes)/2)):
x = indexes.pop(random.randint(0, len(indexes)-1))
y = indexes.pop(random.randint(0, len(indexes)-1))
r[x], r[y] = r[y], r[x]
reflector = Reflector(''.join(r))
# Define Enigam
machine = Enigam(
p, [r1, r2, r3], reflector)
text = 'PYTHON'
encrypted = machine.encrypt(text)
decrypted = machine.decrypt(encrypted)
print(f' Text : {text}') # Text : PYTHON
print(f'Encrypted text : {encrypted}') # Encrypted text : TDZXZS
print(f'Decrypted text : {decrypted}') # Decrypted text : PYTH
'''
Recommended Posts