예제 #1
0
 def __init__(self):
     """
     sets the initial machine with reflector, default rotors and default plugboard.
     """
     self.__reflector = Reflector()
     self.plugboard = Plugboard()
     self.rotors = Rotors()
예제 #2
0
 def setUp(self):
     self.enigma = Enigma(Plugboard('VZBRGITYUPSDNHLXAWMJQOFECK'),
                          Reflector('JPGVOUMFYQBENHZRDKASXLICTW'),
                          Settings("ABC"))
     self.enigma2 = Enigma(Plugboard('VZBRGITYUPSDNHLXAWMJQOFECK'),
                           Reflector('JPGVOUMFYQBENHZRDKASXLICTW'),
                           Settings("WGF"))
예제 #3
0
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"])
예제 #4
0
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
예제 #5
0
    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))
예제 #6
0
    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)
예제 #7
0
class testPlugboard(unittest.TestCase):

	def setUp(self):
		self.plugboard = Plugboard()

	def test_changeString(self):
		testString = "WAMTRSQVYEcdz"
		self.assertEqual("ZBOFXGUINLCDZ",self.plugboard.changeString(testString))
예제 #8
0
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
예제 #9
0
    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
예제 #10
0
    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'])
예제 #11
0
    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)
예제 #12
0
    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)
예제 #13
0
	def setUp(self):
		self.plugboard = Plugboard()
예제 #14
0
 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)
예제 #15
0
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)
예제 #16
0
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)
예제 #17
0

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()
예제 #18
0
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
예제 #19
0
 def setUp(self):
     self.alph = Plugboard("ABCDEF")
예제 #20
0
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("******************************************************")
예제 #21
0
def test_nothingMapped():
    plugboard = Plugboard()
    for element in Alphabet.set:
        assert plugboard[element] == element
예제 #22
0
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)
예제 #23
0
			*					   *
			*	 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:
예제 #24
0
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
예제 #25
0
파일: enigma.py 프로젝트: dalemyers/Enigma
            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
예제 #26
0
 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())
예제 #27
0
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 = []
예제 #28
0
def test_a_mapped_to_b(given, expected):
    plugboard = Plugboard()
    plugboard["A"] = "B"
예제 #29
0
파일: main.py 프로젝트: maartenpeels/Enigma
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'),