def __init__(self): """ sets the initial machine with reflector, default rotors and default plugboard. """ self.__reflector = Reflector() self.plugboard = Plugboard() self.rotors = Rotors()
def setUp(self): self.enigma = Enigma(Plugboard('VZBRGITYUPSDNHLXAWMJQOFECK'), Reflector('JPGVOUMFYQBENHZRDKASXLICTW'), Settings("ABC")) self.enigma2 = Enigma(Plugboard('VZBRGITYUPSDNHLXAWMJQOFECK'), Reflector('JPGVOUMFYQBENHZRDKASXLICTW'), Settings("WGF"))
class Tests_Plugboard(unittest.TestCase): def setUp(self): self.alph = Plugboard("ABCDEF") def test_init(self): self.assertEqual(self.alph.alphabet, ["A", "B", "C", "D", "E", "F"]) def test_plugboard_encode(self): self.assertEqual(self.alph.plugboard_encode("A"), [1]) def test_plugboard_decode(self): self.assertEqual(self.alph.plugboard_decode([1]), ["A"])
class EnigmaMachine(Encoder): def __init__(self, *configs): self.plugboard = Plugboard(configs[-1]) self.rotors = [] # initially no rotors for rotor_path in configs[:-1]: self.rotors.append(Rotor(rotor_path)) self.reflector = Reflector(13) def encode(self, input): input = ord(input) - ord('A') # A -> 0, ..., Z -> 25 output = self.plugboard.encode(input) output = self.pass_rotors('encode', output) output = self.reflector.encode(output) output = self.pass_rotors('decode', output) output = self.plugboard.decode(output) if len(self.rotors) > 0: # check for rotors self.rotate_rotors(0) # rotate necessary rotors return chr(output + ord('A')) def encode_message(self, message): encoded_message = '' for letter in message: if letter == ' ': encoded_message += ' ' else: encoded_message += self.encode(letter) return encoded_message def decode(self, output): return self.encode(output) # reciprocal cipher def rotate_rotors(self, rotor_i): if self.rotors[rotor_i].rotate(): rotor_i += 1 if rotor_i < len(self.rotors): self.rotate_rotors(rotor_i) def pass_rotors(self, transformer, input): direc = -1 if transformer == 'decode' else 1 for rotor_num, rotor in enumerate(self.rotors[::direc]): # get output of current rotor if transformer == 'encode': input = rotor.encode(input) else: # decode input = rotor.decode(input) return input
def from_key_sheet(cls, rotors='I II III', ring_settings=None, reflector='B', plugboard_settings=None): """Convenience function to build an EnigmaMachine from the data as you might find it on a key sheet: rotors: either a list of strings naming the rotors from left to right or a single string: e.g. ["I", "III", "IV"] or "I III IV" ring_settings: either a list/tuple of integers, a string, or None to represent the ring settings to be applied to the rotors in the rotors list. The acceptable values are: - A list/tuple of integers with values between 0-25 - A string; either space separated letters or numbers, e.g. 'B U L' or '2 21 12'. If numbers are used, they are 1-based to match historical key sheet data. - None means all ring settings are 0. reflector: a string that names the reflector to use plugboard_settings: a string of plugboard settings as you might find on a key sheet; e.g. 'PO ML IU KJ NH YT GB VF RE DC' or '18/26 17/4 21/6 3/16 19/14 22/7 8/1 12/25 5/9 10/15' A value of None means no plugboard connections are made. """ # validate inputs if isinstance(rotors, str): rotors = rotors.split() num_rotors = len(rotors) if num_rotors not in (3, 4): raise EnigmaError("invalid rotors list size") if ring_settings is None: ring_settings = [0] * num_rotors elif isinstance(ring_settings, str): strings = ring_settings.split() ring_settings = [] for s in strings: if s.isalpha(): ring_settings.append(ord(s.upper()) - ord('A')) elif s.isdigit(): ring_settings.append(int(s) - 1) else: raise EnigmaError('invalid ring setting: %s' % s) if num_rotors != len(ring_settings): raise EnigmaError("# of rotors doesn't match # of ring settings") # assemble the machine rotor_list = [create_rotor(r[0], r[1]) for r in zip(rotors, ring_settings)] return cls(rotor_list, create_reflector(reflector), Plugboard.from_key_sheet(plugboard_settings))
def __init__(self, *configs): self.plugboard = Plugboard(configs[-1]) self.rotors = [] # initially no rotors for rotor_path in configs[:-1]: self.rotors.append(Rotor(rotor_path)) self.reflector = Reflector(13)
class testPlugboard(unittest.TestCase): def setUp(self): self.plugboard = Plugboard() def test_changeString(self): testString = "WAMTRSQVYEcdz" self.assertEqual("ZBOFXGUINLCDZ",self.plugboard.changeString(testString))
class Enigma(object): '''Object to handle Enigma encryption. Based on Enigma Machine''' def __init__(self, offset1, offset2, offset3): self.rot1 = Rotor(offset1, rotor_num=1) self.rot2 = Rotor(offset2, rotor_num=2) self.rot3 = Rotor(offset3, rotor_num=3) self.reflector = Reflector(ALPHABET) self.plugboard = Plugboard(ALPHABET, PLUGBOARD_LIST) #TODO: Do this better def set_rotors(self, offset1, offset2, offset3): '''Set the values of the rotors''' self.rot1.offset = offset1 self.rot2.offset = offset2 self.rot3.offset = offset3 #TODO: Implement this correctly def increment_rotors(self): '''Increment the rotors according to the Enigma algorithm''' self.rot1.increment() if self.rot1.offset == 3: self.rot2.increment() if self.rot2.offset == 2: self.rot3.increment() def encipher(self, msg): '''Encipher the message according to the Enigma algorithm''' output = '' for val in msg: val = self.plugboard.encipher(val) self.increment_rotors() val = self.rot1.encipher(val) val = self.rot2.encipher(val) val = self.rot3.encipher(val) val = self.reflector.encipher(val) val = self.rot3.decipher(val) val = self.rot2.decipher(val) val = self.rot1.decipher(val) val = self.plugboard.encipher(val) output = output + val return output
def __init__(self, rotor_selection, rotor_settings, plugs, ring_positions, reflector): """ Rotor_selection: Which rotors are in use and which order. List would look like this: [4, 2, 5] rotor_settings: list of starting positions for left, middle, and right rotor. i.e index 0 is for left rotor, 1 for middle, and 2 for right rotor. List would look like this: [1, 6, 16] plugs: List of enabled plugboard settings. List would look like this: [ "QH", "EN", "RM", "TL", "YS", "UI", "OK", "PC", "DV", "FG" ] """ # Wiring for rotors I to V self.rotor_settings_strings = [ "EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO", "ESOVPZJAYQUIRHXLNFTGKDCMWB", "VZBRGITYUPSDNHLXAWMJQOFECK" ] self.rotor_settings = rotor_settings self.rotor_selection = rotor_selection self.ring_positions = ring_positions self.rotor_list = self.setup_rotors(self.rotor_selection, self.rotor_settings) self.plugboard = Plugboard(plugs) self.reflector = reflector
def create_machinery(self): """ Adds in turn each part of the machine as specified in the user settings. """ # Add plugboard with respective pluglead pairs self.board = Plugboard(self.settings) # Add housing self.add("Housing") # Add rotors. Rotors are 'inserted' in reverse order from right to left for i in range(len(self.settings['rotors'].split(' ')) - 1, -1, -1): rotor_name = self.settings['rotors'].split(' ')[i] ring_setting = self.settings['ring_settings'].split(' ')[i] initial_position = self.settings['initial_positions'].split(' ')[i] self.add(rotor_name, ring_setting, initial_position) # Add reflector self.add(self.settings['reflector'])
def __init__(self, nmrRotors, initCharRotors, cables): self.list_of_rotors = [] reflector_indexes = "IXUHFEZDAOMTKQJWNSRLCYPBVG" #rotors_orders = ["EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO"] rotors_orders = [ "EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO", "RMSLNIXCYPTZAHJOUFDBQGWKVE", "ZIHFQEMASYPOWDBKVXCNLRTUGJ" ] # "RMSLNIXCYPTZAHJOUFDBQGWKVE", "ZIHFQEMASYPOWDBKVXCNLRTUGJ" # imaginemos nmrRotor = [2,1] y charRotor = ['C','G'] for index, (nmrRotor, charRotor) in enumerate(zip(nmrRotors, initCharRotors)): self.list_of_rotors.append( Rotor(charRotor, rotors_orders[nmrRotor - 1])) self.plugboard = Plugboard(cables) self.reflector = Rotor('A', reflector_indexes)
def __init__(self, rotors='I II III', ring_settings=None, reflector='B', plugboard_settings=None): if isinstance(rotors, str): rotors = rotors.split() num_rotors = len(rotors) if num_rotors not in (3, 4): raise EnigmaError("invalid rotors list size") if ring_settings is None: ring_settings = [0] * num_rotors elif isinstance(ring_settings, str): strings = ring_settings.split() ring_settings = [] for s in strings: if s.isalpha(): ring_settings.append(ord(s.upper()) - ord('A')) elif s.isdigit(): ring_settings.append(int(s) - 1) else: raise EnigmaError('invalid ring setting: %s' % s) if num_rotors != len(ring_settings): raise EnigmaError("# of rotors doesn't match # of ring settings") rotor_list = [ create_rotor(r[0], r[1]) for r in zip(rotors, ring_settings) ] self.rotors = rotor_list self.rotor_count = len(rotors) self.reflector = create_reflector(reflector) self.plugboard = Plugboard(plugboard_settings)
def setUp(self): self.plugboard = Plugboard()
def __init__(self, offset1, offset2, offset3): self.rot1 = Rotor(offset1, rotor_num=1) self.rot2 = Rotor(offset2, rotor_num=2) self.rot3 = Rotor(offset3, rotor_num=3) self.reflector = Reflector(ALPHABET) self.plugboard = Plugboard(ALPHABET, PLUGBOARD_LIST)
class Enigma: """ this class is the main class of the enigma machine simulator. it will encrypt and decrypt messages. """ def __init__(self): """ sets the initial machine with reflector, default rotors and default plugboard. """ self.__reflector = Reflector() self.plugboard = Plugboard() self.rotors = Rotors() def decrypt_encrypt_text(self, text): """ encrypts or decrypts a whole text :param text: :return: """ text_after_enigma = "" for i in text: letter_after_enigma, encryption_str = self.encrypt_letter(i) text_after_enigma += letter_after_enigma return text_after_enigma def encrypt_letter(self, letter): """ encrypts a given letter :param letter: :return: encrypted letter and encryption string which explains the stages of the encryption. used in the simulator when showing the encryption stages. """ encryption_str = "the letter to encrypt: " + letter + "\n" letter = letter.upper() encryption_str += "letters on rotors: " + str( self.rotors.letter_on_rotors()) + "\n" encryption_str += "letter before plugboard = " + letter + "\n" letter_after_plugboard = self.plugboard.return_encrypted_letter(letter) encryption_str += "letter after plugboard = " + letter_after_plugboard + "\n" letter_before_reflector, cipher_txt = self.rotors.\ cipher_letter_plugboard_to_reflector(letter_after_plugboard) encryption_str += cipher_txt encryption_str += "letter before reflector = " + letter_before_reflector + "\n" letter_after_reflector = self.__reflector.get_encrypted_letter( letter_before_reflector) encryption_str += "letter after reflector = " + letter_after_reflector + "\n" letter_before_plugboard, decipher_txt = self.rotors.cipher_letter_reflector_to_plugboard( letter_after_reflector) encryption_str += decipher_txt encryption_str += "letter before plugboard = " + letter_before_plugboard + "\n" letter_encrypted = self.plugboard.return_encrypted_letter( letter_before_plugboard) encryption_str += "letter encrypted = " + letter_encrypted self.rotors.move_rotors_after_cipher() return letter_encrypted, encryption_str def set_random_settings(self): """ this function sets the enigma to a random settings. :return: """ # setting random rotors rotors_numbers = random.sample([1, 2, 3, 4, 5], 3) rotors_letters = random.sample([chr(i) for i in range(65, 91)], 3) self.rotors.set_rotors(rotors_numbers[0], rotors_numbers[1], rotors_numbers[2], rotors_letters[0], rotors_letters[1], rotors_letters[2]) # setting random plugboard num_pairs = random.randint(0, 10) plugboard_letters = random.sample([chr(i) for i in range(65, 91)], num_pairs * 2) for i in plugboard_letters: self.plugboard.add_letter(i)
class EnigmaMachine: def __init__(self, rotors='I II III', ring_settings=None, reflector='B', plugboard_settings=None): if isinstance(rotors, str): rotors = rotors.split() num_rotors = len(rotors) if num_rotors not in (3, 4): raise EnigmaError("invalid rotors list size") if ring_settings is None: ring_settings = [0] * num_rotors elif isinstance(ring_settings, str): strings = ring_settings.split() ring_settings = [] for s in strings: if s.isalpha(): ring_settings.append(ord(s.upper()) - ord('A')) elif s.isdigit(): ring_settings.append(int(s) - 1) else: raise EnigmaError('invalid ring setting: %s' % s) if num_rotors != len(ring_settings): raise EnigmaError("# of rotors doesn't match # of ring settings") rotor_list = [ create_rotor(r[0], r[1]) for r in zip(rotors, ring_settings) ] self.rotors = rotor_list self.rotor_count = len(rotors) self.reflector = create_reflector(reflector) self.plugboard = Plugboard(plugboard_settings) def set_display(self, val): if len(val) != self.rotor_count: raise EnigmaError("Incorrect length for display value") for i, rotor in enumerate(reversed(self.rotors)): rotor.set_display(val[-1 - i]) def key_press(self, key): if key not in KEYBOARD_SET: raise EnigmaError('illegal key press %s' % key) self._step_rotors() signal_num = ord(key) - ord('A') lamp_num = self._electric_signal(signal_num) return KEYBOARD_CHARS[lamp_num] def _step_rotors(self): rotor1 = self.rotors[-1] rotor2 = self.rotors[-2] rotor3 = self.rotors[-3] rotate2 = rotor1.notch_over_pawl() or rotor2.notch_over_pawl() rotate3 = rotor2.notch_over_pawl() rotor1.rotate() if rotate2: rotor2.rotate() if rotate3: rotor3.rotate() def _electric_signal(self, signal_num): pos = self.plugboard.signal(signal_num) for rotor in reversed(self.rotors): pos = rotor.signal_in(pos) pos = self.reflector.signal_in(pos) for rotor in self.rotors: pos = rotor.signal_out(pos) return self.plugboard.signal(pos) def process_text(self, text): result = [] for key in text: c = key.upper() if c not in KEYBOARD_SET: if c == '=' or c in string.digits: result.append(c) continue else: raise EnigmaError('illegal symbol') result.append(self.key_press(c)) return ''.join(result)
settings = Settings(ask_for_key()) user = User(ask_for_text()) print("Do you want set Enigma yourself? [yes/no]") a = input() while a.upper() not in ["YES", "NO"]: print("You have to answer yes or no!") a = input() if a.upper() == "YES": print( "Be careful! If you make a mistake, you will have to start from the beginning!" ) print("Provide your Plugboard set.") connect = input() Plugboard(connect).check_len_alphabet() Plugboard(connect).repeat_alphabet() print("Provide your first Rotor set.") characteristic1 = input() Rotor(characteristic1).check_len_alphabet() Rotor(characteristic1).repeat_alphabet() print("Provide your secound Rotor set.") characteristic2 = input() Rotor(characteristic2).check_len_alphabet() Rotor(characteristic2).repeat_alphabet() print("Provide your third Rotor set.") characteristic3 = input() Rotor(characteristic3).check_len_alphabet() Rotor(characteristic3).repeat_alphabet() print("Provide your Reflector set.") reflect = input()
class Enigma: """ This class simulates the Enigma machine As models M3 and M4 of the Enigma machine, it supports 3 or 4 rotors configuration. The order of reflector and rotors definition respect the physical order (left-to-right). :param reflector: The reflector associated to the Enigma machine :type reflector: Reflector :param *rotors: The rotors associated to the Enigma machine :type *rotors: Variable length rotor list :raises: :class:`TypeError, ValueError`: If one of the provided parameter is invalid Example:: enigma = Enigma(ReflectorB(), RotorI(), RotorII(), RotorIII("V")) enigma.encode("HELLOWORLDHELLOWORLDHELLOWORLD") enigma = Enigma(ReflectorA(), RotorIV("E", 18), RotorV("Z", 24), RotorBeta("G", 3), RotorI("P", 5)) enigma.plugboard.set("PC XZ FM QA ST NB HY OR EV IU") enigma.encode("BUPXWJCDPFASXBDHLBBIBSRNWCSZXQOLBNXYAXVHOGCUUIBCVMPUZYUUKHI") """ def __init__(self, reflector, *rotors): self._rotor_chain = RotorChain(reflector, *rotors) self.plugboard = Plugboard() self.__alpha_string_validator = Validator( TypeValidator(str), LengthValidator(1, lambda x, y: x >= y), AlphaValidator()) def encode(self, string): """ Perform the whole encoding of a string on the Enigma machine Each character of the string is first encoded by the plug board then the character is encoded through the rotor chain and finally the character is encoded by the plug board again. :param char: The string to encode :type char: str :return: The encoded string :rtype: str """ self.__alpha_string_validator.validate(string) encoded_string = "" for letter in string: encoded_string += self.plugboard.encode( self._rotor_chain.encode(self.plugboard.encode(letter))) return encoded_string def reset(self): """ Reset all rotors of the machine to position to "A" and the ring setting to 1 """ self._rotor_chain.reset() @property def plugboard(self): """ The plug board associated to the Enigma machine :getter: Returns the plug board :setter: Sets the plug board :type: Plugboard """ return self.__plugboard @plugboard.setter def plugboard(self, plugboard): self.__plugboard = plugboard @property def reflector(self): """ The reflector associated to the Enigma machine :getter: Returns the reflector :setter: Sets the reflector :type: Reflector """ return self._rotor_chain.reflector @reflector.setter def reflector(self, reflector): self._rotor_chain.reflector = reflector @property def rotors(self): """ The rotors associated to the Enigma machine :getter: Returns the list of rotors :setter: Sets the list of rotors :type: Rotors list """ return self._rotor_chain.rotors @rotors.setter def rotors(self, rotors): self._rotor_chain.rotors = rotors
def setUp(self): self.alph = Plugboard("ABCDEF")
class EnigmaMachine(): """ A programmatic implementation of the infamous Enigma encryption algorithm. To be honest, I made this because I was bored and this felt like a challenge. Wikipedia Description: The Enigma machine is an encryption device developed and used in the early to mid-20th century to protect commercial, diplomatic and military communication. It was employed extensively by Nazi Germany during World War II, in all branches of the German military. Read more about it here: https://en.wikipedia.org/wiki/Enigma_machine Brad Fitzgerald December 2020 """ def __init__(self, rotor_selection, rotor_settings, plugs, ring_positions, reflector): """ Rotor_selection: Which rotors are in use and which order. List would look like this: [4, 2, 5] rotor_settings: list of starting positions for left, middle, and right rotor. i.e index 0 is for left rotor, 1 for middle, and 2 for right rotor. List would look like this: [1, 6, 16] plugs: List of enabled plugboard settings. List would look like this: [ "QH", "EN", "RM", "TL", "YS", "UI", "OK", "PC", "DV", "FG" ] """ # Wiring for rotors I to V self.rotor_settings_strings = [ "EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO", "ESOVPZJAYQUIRHXLNFTGKDCMWB", "VZBRGITYUPSDNHLXAWMJQOFECK" ] self.rotor_settings = rotor_settings self.rotor_selection = rotor_selection self.ring_positions = ring_positions self.rotor_list = self.setup_rotors(self.rotor_selection, self.rotor_settings) self.plugboard = Plugboard(plugs) self.reflector = reflector def setup_rotors(self, rotor_selection, rotor_settings): """[summary] Args: rotor_selection ([type]): [description] rotor_settings ([type]): [description] Returns: [type]: [description] """ # Setup rotor strings rotor_str = [] for index, obj in enumerate(self.rotor_selection): selection_index = rotor_selection[index] - 1 rotor_wiring = self.rotor_settings_strings[selection_index] rotor_str.append(rotor_wiring) # Setup ring settings ring_pos = [] for index, obj in enumerate(self.ring_positions): ring_pos.append(self.ring_positions[index]) rotor_list = [] # Configure rotors and rotor attributes for index, obj in enumerate(rotor_selection): rotor_list.append( Rotor(rotor_str[index], rotor_settings[index], rotor_selection[index], ring_pos[index])) return rotor_list def encode_message(self, message): """Takes a string and encodes each char of the string printing the final result Args: message (string): message to transform """ character_list = self.convert_message_to_numbers(message) encoded_message = [] for index, value in enumerate(character_list): encoded_char = self.encode_letter(value) encoded_message.append(encoded_char) print('') print(f"Ciphertext:") print(self.convert_numbers_to_letters(encoded_message)) def encode_letter(self, char_index): """Translates inputted chars into scrambled char based on current rotor/plugbard setting Args: char_index (int): index of char within alphabit list (i.e 0 = A, 1 = B, etc) Returns: int: index of transformed char """ # Move rotor position by one and check if others need to be moved self.move_rotors() # Pass char through plugboard and get index plugboard_out = self.plugboard.swap(char_index) rotor_input_left = plugboard_out # Move letter through rotors from left to right for rotor in reversed(self.rotor_list): rotor_input_left = rotor.use_rotor(rotor_input_left, "left") # Run letter through reflector reflector_output = self.calculate_reflection(rotor_input_left, self.reflector) rotor_input_right = reflector_output # Move letter through rotors from right to left for rotor in self.rotor_list: rotor_input_right = rotor.use_rotor(rotor_input_right, "right") # Apply plug board logic plugboard_out = self.plugboard.swap(rotor_input_right) return plugboard_out def move_rotors(self): """Logic to move rotors. If the turnover position is hit on one rotor, the next rotor to the left turns over """ # Always move the right most rotor one postion self.rotor_list[2].update_position() # Check if middle rotor should rotate if (self.rotor_list[2].position == self.rotor_list[2].turnover): self.rotor_list[1].update_position() # Check if middle rotor is on turnover and preform a double step elif (self.rotor_list[1].position == self.rotor_list[1].turnover - 1): self.rotor_list[1].update_position() self.rotor_list[0].update_position() def calculate_reflection(self, input_val, reflector): """Run input character through reflector Args: input_val (int): index of character in alphabit reflector (str): reflector character string Returns: [int]: index of reflected character """ char_to_reflect = reflector[input_val] return self.get_char_to_index(char_to_reflect) def convert_numbers_to_letters(self, number_list): """converts index of character to character itself and store resulting message in list Args: number_list (list): list of index values for characters Returns: string: message resulting from enigma encryption """ message = '' for x in number_list: message = message + self.get_char_from_index(x) return message def get_char_to_index(self, char): """Converts a letter to its index value as part of a list Args: char (str): actual letter as a char Returns: int: position of char in list of alphabit """ a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' for index, letter in enumerate(a): if (letter is char): return index def get_char_from_index(self, index): """Returns the char matching the index of the alphabit list Args: index (int): [description] Returns: [type]: [description] """ a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' return a[index] def convert_message_to_numbers(self, message): """converts character to index position within alphabit and store resulting integers in a list Args: message (string): message to be encrypted Returns: list: list of index values for each char of the message """ a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' message_as_char_index = [] for char in message.upper(): if char not in a: continue for index, letter in enumerate(a): if (char is letter): message_as_char_index.append(index) return message_as_char_index def print_settings(self): """Prints a welcome message to the user and shows the current configuration """ print(" _____________________________________________________") print("| |") print("| Enigma model M3 |") print("|_____________________________________________________|") print('') print(" Configuration:") print('') print(f"Reflector Config: {self.reflector}") print('') print("Rotor Order:") for selection in self.rotor_selection: print(selection, sep=',', end=' ', flush=True) print('') print("Starting Position:") for pos in self.rotor_settings: print(pos, sep=',', end=' ', flush=True) print('') print("Ring Setting:") for ring in self.ring_positions: print(ring, sep=',', end=' ', flush=True) print('') print(f"Plugboard connections:") for plug in self.plugboard.get_plugs(): print(plug, sep=',', end=' ', flush=True) print('') print("******************************************************")
def test_nothingMapped(): plugboard = Plugboard() for element in Alphabet.set: assert plugboard[element] == element
class Enigma: """ The core class for the Enigma machine. Takes in a settings dictionary as provided by the user, and constructs the required machine from the settings blueprints. The structure of the machine is as follows: 1. Plugboard with required plugleads 2. Housing - a simple list from A-Z, never rotates 3. Rotors - 3 or 4 with respective pins and contacts, these rotate with each 'key press' 4. 1 Reflector - which will map the final rotor output to a different letter before passing the signal rightwards. """ def __init__(self, settings: dict): self.settings = settings self.root = None self.rotor_box = { "Housing": { 'contacts': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'notch': None }, "Beta": { 'contacts': 'LEYJVCNIXWPBQMDRTAKZGFUHOS', 'notch': None }, "Gamma": { 'contacts': 'FSOKANUERHMBTIYCWLQPZXVGJD', 'notch': None }, "I": { 'contacts': 'EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'notch': 'Q' }, "II": { 'contacts': 'AJDKSIRUXBLHWTMCQGZNPYFVOE', 'notch': 'E' }, "III": { 'contacts': 'BDFHJLCPRTXVZNYEIWGAKMUSQO', 'notch': 'V' }, "IV": { 'contacts': 'ESOVPZJAYQUIRHXLNFTGKDCMWB', 'notch': 'J' }, "V": { 'contacts': 'VZBRGITYUPSDNHLXAWMJQOFECK', 'notch': 'Z' }, "A": { 'contacts': 'EJMZALYXVBWFCRQUONTSPIKHGD', 'notch': None }, "B": { 'contacts': 'YRUHQSLDPXNGOKMIEBFZCWVJAT', 'notch': None }, "C": { 'contacts': 'FVPJIAOYEDRZXWGCTKUQSBNMHL', 'notch': None }, } def create_machinery(self): """ Adds in turn each part of the machine as specified in the user settings. """ # Add plugboard with respective pluglead pairs self.board = Plugboard(self.settings) # Add housing self.add("Housing") # Add rotors. Rotors are 'inserted' in reverse order from right to left for i in range(len(self.settings['rotors'].split(' ')) - 1, -1, -1): rotor_name = self.settings['rotors'].split(' ')[i] ring_setting = self.settings['ring_settings'].split(' ')[i] initial_position = self.settings['initial_positions'].split(' ')[i] self.add(rotor_name, ring_setting, initial_position) # Add reflector self.add(self.settings['reflector']) @abstractmethod def add(self, name: str, ring_setting: int = 1, initial_position: str = 'A'): """ Adds a named mechanical part to the machine from right to left, and then adjusts the default part setting to reflect the desired ring setting and initial position :param name: Name of the part being added (see self.rotor_box in the __init__ method for details) :param ring_setting: An integer from 1-26 determining the pin-to-contact mapping for the rotor :param initial_position: The starting position for the rotor """ if self.root is None: self.root = Rotor(name, self.rotor_box, ring_setting, initial_position) self.root.adjust_ring_setting() self.root.adjust_starting_positions() else: ptr = self.root while True: if ptr.left is None: ptr.left = Rotor(name, self.rotor_box, ring_setting, initial_position, right=ptr) ptr.left.adjust_ring_setting() ptr.left.adjust_starting_positions() break else: ptr = ptr.left def encode(self, message: str) -> str: """ Takes the users input message and runs each character through the enigma machine from right to left, and back again, to produce an encoded character. Encoded characters are combined into a single list and returned/printed as one encoded/decoded message. :param message: The message to be decoded/encoded :return: decoded/encoded message string """ i = 0 encoded_phrase = [] # For each character in the message while i < len(message): character = message[i] # Run the character through the plugboard character = self.board.encode(character) ptr = self.root # Rotate all rotors as necessary ptr.left.key_press() # Assign the Housing (first "ptr.contacts") index of the character to input_index inside the first rotor object ptr.left.input_index = ptr.contacts.index(character.upper()) ptr = ptr.left while True: # If there is another rotor to the left if ptr.left is not None: # If Housing is to the right of the current rotor... if ptr.right.name == 'Housing': # ..pass the Housing/input index to the first rotor pins, to get the associated contact/output index ptr.rotor_encode_left(ptr.input_index) else: # Else if it is a rotor to the right, grab that rotors encoded/output character ptr.rotor_encode_left(ptr.right.output_index) # Set pointer to the next part to the left and repeat ptr = ptr.left else: # No more rotors, now run signal through the reflector ptr.rotor_encode_left(ptr.right.output_index) break # Pass signal from reflector back through to the plugboard ptr = ptr.right while True: if ptr.right: # If there is another machine element to the right position, encode as normal ptr.rotor_encode_right(ptr.left.output_index) ptr = ptr.right else: # If there are no more parts to pass the signal through, encode, run through the plugboard if it # exists, then append the output to the output phrase list ptr.rotor_encode_right(ptr.left.output_index) if self.board: ptr.output_char = self.board.encode(ptr.output_char) encoded_phrase.append(ptr.output_char) break # Increase i by one to then loop back and start again for the next character i += 1 print(f"Input Phrase: {message}") print(f"Encoded Phrase: {''.join(encoded_phrase)}") if len(self.settings['rotors'].split(' ')) == 3: print(f'Final Rotor Positions:{self.root.left.left.left.position}' f'{self.root.left.left.position}' f'{self.root.left.position}') else: print( f'Final Rotor Positions:{self.root.left.left.left.left.position}' f'{self.root.left.left.left.position}' f'{self.root.left.left.position}' f'{self.root.left.position}') return ''.join(encoded_phrase)
* * * ENIGMA MACHINE * * * -**********************- AUTHORS: | ID: -------- | ----- MATAN DAVIDIAN | 205509219 TOM DAMRI | 205770068 Tomer Leon | 312203003 Alex Kreinis | 312623218 DATE : 15.11.19 """ e = Enigma() p = Plugboard() p.initials() fast_configure = int( input("FOR FAST CONFIGURE PRESS 0 FOR COSTUME CONFIGURE PRESS 1: ")) if fast_configure == 1: configure = int( input( "Enter 1 to configure plug board, 0 to use the default plug board: " )) if configure: count = 0 match = input( "Enter pairs - less than 10 pairs (for example: AB CD FK): " ).split() for m in match: if count > 10:
class Maquina: list_of_rotors: list reflector: Rotor plugboard: Plugboard def __init__(self, nmrRotors, initCharRotors, cables): self.list_of_rotors = [] reflector_indexes = "IXUHFEZDAOMTKQJWNSRLCYPBVG" #rotors_orders = ["EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO"] rotors_orders = [ "EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO", "RMSLNIXCYPTZAHJOUFDBQGWKVE", "ZIHFQEMASYPOWDBKVXCNLRTUGJ" ] # "RMSLNIXCYPTZAHJOUFDBQGWKVE", "ZIHFQEMASYPOWDBKVXCNLRTUGJ" # imaginemos nmrRotor = [2,1] y charRotor = ['C','G'] for index, (nmrRotor, charRotor) in enumerate(zip(nmrRotors, initCharRotors)): self.list_of_rotors.append( Rotor(charRotor, rotors_orders[nmrRotor - 1])) self.plugboard = Plugboard(cables) self.reflector = Rotor('A', reflector_indexes) def cifrar(self, char): char_processed = char char_processed = self.plugboard.procesar_caracter(char_processed) for rotor in self.list_of_rotors: char_processed = rotor.push(char_processed) char_processed = self.reflector.push(char_processed) for rotor in self.list_of_rotors[::-1]: char_processed = rotor.antipush(char_processed) char_processed = self.plugboard.procesar_caracter(char_processed) self.moveListOfRotors() """ for rotor in self.list_of_rotors: print(f"Rotor: {rotor.dest_go} count: {rotor.count}") """ return char_processed def moveListOfRotors(self): for index, rotor in enumerate(self.list_of_rotors): if index == 0: rotor.move() rotor.count += 1 else: if self.list_of_rotors[index - 1].count == 26: self.list_of_rotors[index - 1].count = 0 rotor.move() rotor.count += 1
e = self.left_rotor.convert_backward(e) e = self.middle_rotor.convert_backward(e) e = self.right_rotor.convert_backward(e) e = self.plugboard.convert(e) self.right_rotor.increment_position() encrypted += e return encrypted if __name__ == "__main__": r_right = Rotor(3, 0) r_middle = Rotor(2, 0) r_left = Rotor(1, 0) reflector = Reflector("A") plugboard = Plugboard("AZ BP CH DN EM FS GW JY KT LQ") input_text = "HELLOWORLD" print "Input:", input_text e = Enigma(reflector, r_left, r_middle, r_right, plugboard) encrypted = e.encrypt(input_text) print "Encrypted:", encrypted r_left.set_position(0) r_middle.set_position(0) r_right.set_position(0) decrypted = e.encrypt(encrypted) print "Decrypted:", decrypted
def __init__(self, reflector, *rotors): self._rotor_chain = RotorChain(reflector, *rotors) self.plugboard = Plugboard() self.__alpha_string_validator = Validator( TypeValidator(str), LengthValidator(1, lambda x, y: x >= y), AlphaValidator())
r3 = Rotor('my rotor1', 'CEADFB', ring_setting=0) #, stepping='A') r2 = Rotor('my rotor2', 'CADFEB', ring_setting=0) #, stepping='A') r1 = Rotor('my rotor3', 'ADFBCE', ring_setting=0) #, stepping='A') # zweite Version / rotiert # 1 3 2 <- chaotisch # 2 3 1 <- weniger chaotisch r1 = Rotor('my rotor1', 'CEADFB', ring_setting=0) #, stepping='A') r3 = Rotor('my rotor2', 'CADFEB', ring_setting=0) #, stepping='A') r2 = Rotor('my rotor3', 'ADFBCE', ring_setting=0) #, stepping='A') #reflector = Rotor('my reflector', 'FVPJIAOYEDRZXWGCTKUQSBNMHL') reflector = Rotor('my reflector', 'CFAEDB') #pb = Plugboard.from_key_sheet('AF CD EB') pb = Plugboard() machine = EnigmaMachine([r1, r2, r3], reflector, pb) #machine = EnigmaMachine([r1], reflector, pb) def mapper(text): mapping = 'ENIGMA' new_text = "" for s in text: new_text += mapping[ord(s) - ord('A')] + " " return new_text def test_female(msg): female = []
def test_a_mapped_to_b(given, expected): plugboard = Plugboard() plugboard["A"] = "B"
from enigma import Enigma from plugboard import Plugboard from reflector import Reflector from rotor import Rotor e1 = Enigma(rotors=[ Rotor(position=24, type="II"), Rotor(position=13, type="I"), Rotor(position=22, type="III") ], plugboard=Plugboard([ ('A', 'M'), ('F', 'I'), ('N', 'V'), ('P', 'S'), ('T', 'U'), ('W', 'Z'), ]), reflector=Reflector("A") ) e2 = Enigma(rotors=[ Rotor(position=24, type="II"), Rotor(position=13, type="I"), Rotor(position=22, type="III") ], plugboard=Plugboard([ ('A', 'M'), ('F', 'I'), ('N', 'V'), ('P', 'S'),