Last active
June 23, 2016 10:15
-
-
Save jvarho/d73ca813d7685668f949b92f3ecdaa60 to your computer and use it in GitHub Desktop.
Enigma machine emulator, written in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' | |
class Rotor(): | |
perms = [] | |
turnover_position = '' | |
position = 'A' | |
def __init__(self, perms, turnover_position, ring_setting): | |
i = alphabet.index(ring_setting) | |
perms = perms[i:] + perms[:i] | |
self.perms = [c for c in perms] | |
self.turnover_position = turnover_position | |
def set_position(self, position): | |
position_change = alphabet.index(position) - alphabet.index(self.position) | |
self.position = position | |
self.perms = self.perms[position_change:] + self.perms[:position_change] | |
def turnover(self): | |
return True if self.turnover_position == self.position else False | |
def step(self): | |
turnover = self.turnover() | |
self.perms = self.perms[1:] + self.perms[:1] | |
self.position = alphabet[(alphabet.index(self.position) + 1) % 26] | |
if turnover: | |
return True | |
else: | |
return False | |
def encrypt_forward(self, c): | |
return self.perms[alphabet.index(c)] | |
def encrypt_backward(self, c): | |
return alphabet[self.perms.index(c)] | |
class Reflector(): | |
def __init__(self, pairs): | |
self.pairs = {} | |
for i, c in enumerate(alphabet): | |
self.pairs[c] = pairs[i] | |
def reflect(self, c): | |
return self.pairs[c] | |
class Machine(): | |
rotors = [] | |
reflector = None | |
plug_board = {} | |
double_step = False | |
def __init__(self, rotors, reflector, plug_board): | |
self.rotors = [Rotor(rotor[0], rotor[1], rotor[2]) for rotor in rotors] | |
self.reflector = Reflector(reflector) | |
for pair in plug_board: | |
self.plug_board[pair[0]], self.plug_board[pair[1]] = pair[1], pair[0] | |
def set_rotors(self, positions): | |
if len(positions) != len(self.rotors): | |
print('Error: rotor settings do not match with number of rotors') | |
else: | |
[rotor.set_position(positions[i]) for i, rotor in enumerate(self.rotors)] | |
return | |
def encrypt_char(self, c): | |
c = self.plug_board[c] if c in self.plug_board else c | |
for i, rotor in enumerate(self.rotors[::-1]): | |
if i is 0: | |
c = rotor.encrypt_forward(c) | |
else: | |
difference = (alphabet.index(self.rotors[::-1][i-1].position) - alphabet.index(self.rotors[::-1][i].position)) % 26 | |
c = rotor.encrypt_forward(alphabet[alphabet.index(c) - difference]) | |
print(c) | |
difference = alphabet.index(self.rotors[0].position) | |
c = self.reflector.reflect(c) | |
print('\n') | |
print(c) | |
print('\n') | |
for i, rotor in enumerate(self.rotors): | |
if i is 0: | |
c = rotor.encrypt_backward(c) | |
else: | |
difference = (alphabet.index(self.rotors[i-1].position) - alphabet.index(self.rotors[i].position)) % 26 | |
print(difference) | |
c = rotor.encrypt_backward(alphabet[alphabet.index(c) - difference]) | |
print(c) | |
c = self.plug_board[c] if c in self.plug_board else c | |
return c | |
def status(self): | |
return self.rotors[0].position + self.rotors[1].position + self.rotors[2].position | |
def step(self): | |
if self.double_step: | |
self.rotors[1].step() | |
self.rotors[0].step() | |
self.double_step = False | |
if self.rotors[2].step(): | |
self.rotors[1].step() | |
if self.rotors[1].turnover(): | |
self.double_step = True | |
def encrypt(self, s): | |
out = '' | |
for c in s: | |
self.step() | |
out += self.encrypt_char(c) | |
return out | |
def test(): | |
rotors=[('ESOVPZJAYQUIRHXLNFTGKDCMWB', 'J', 'G'), | |
('AJDKSIRUXBLHWTMCQGZNPYFVOE', 'E', 'M'), | |
('VZBRGITYUPSDNHLXAWMJQOFECK', 'Z', 'Y')] | |
reflector = 'YRUHQSLDPXNGOKMIEBFZCWVJAT' | |
plug_board = [('D', 'N'), ('G', 'R'), ('I', 'S'), ('K', 'C'), ('Q', 'X'), ('T', 'M'), ('P', 'V'), ('H', 'Y'), ('F', 'W'), ('B', 'J')] | |
machine = Machine(rotors, reflector, plug_board) | |
return machine |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment