Python Forum
Enigma Machine, I need help!
Thread Rating:
  • 3 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Enigma Machine, I need help!
#60
Still struggling with this code. The fact is, and I hate to admit it, my mind just doesn't work right anymore.
Ten years ago, I'd have done this in one evening. But it's slow now.
I'm going to post my latest attempt, so any help would be appreciated.
There are a lot of debugging printouts in this code that show exactly what's going on.
The code seems to work perfectly for the right rotor, but not for the middle or left.
The code should be pretty much the same for all three, except for the rotor advancement
before the first rotor encryption.

The setup for the test is (left to right):
Rings: 12, 4, 8
Roller Window: Q, U, O
PlugBoard: MZ, NS
Rotors: V, III, II
Reflector: B
Message: Enigma

-----------------------
The step by step operation should look like:
   
------------------------


import EnigmaPaths
import string
import collections
import json
import copy

class EncryptDammit:
    def __init__(self, plugboard_pairs, rotors, rings, rotor_window, reflector):
        self.rotors = rotors
        self.rings = rings
        self.rotor_window = rotor_window
        self.reflector = reflector
        self.epath = EnigmaPaths.EnigmaPaths()

        with self.epath.enigma_info.open() as f:
            self.init_data = json.load(f)

        # Set up ciphers for test, V, III, I (left to right)
        # Initial cipher shifted (ring setting - window letter index) =
        #  12 - abs((ord('O') - ord('A')))| =   for right rotor test
        self.rotor_info = {}
        self.set_up_rotor_info()
        self.window_incr = [0, 0, 0]

    def set_up_rotor_info(self):
        # Set up ciphers for test, V, III, I (left to right)
        # Initial cipher shifted by self.rotor_info[side]['current_offset']
        self.rotor_info['plugboard'] = {}
        self.rotor_info['plugboard']['cipher'] = collections.deque('ABCDEFGHIJKLZSOPQRNTUVWXYM')
        self.rotor_info['alpha'] = collections.deque(string.ascii_uppercase)
        self.rotor_info['reflector_cipher'] = collections.deque(self.init_data[f'reflector_{self.reflector}'])

        self.sides = {'left': 0, 'middle': 1, 'right': 2}

        # Keep three ciphers, one for ring offset, one for roller offset, one unmodified
        for side, side_idx in self.sides.items():
            self.rotor_info[side] = {}
            self.rotor_info[side]['rotor'] = self.rotors[side_idx]
            self.rotor_info[side]['ring_offset'] = self.rings[side_idx]
            self.rotor_info[side]['roller_window'] = copy.deepcopy(self.rotor_window[side_idx])
            self.rotor_info[side]['roller_window_offset'] = ord(self.rotor_info[side]['roller_window']) - ord('A')
            self.rotor_info[side]['alpha'] = collections.deque(string.ascii_uppercase)
            rotor_name = f"rotor{self.rotor_info[side]['rotor']}_info"
            self.rotor_info[side]['notch'] = self.init_data['rotor_info'][rotor_name]['notches'][0]
            self.rotor_info[side]['cipher'] = collections.deque(self.init_data['rotor_info'][rotor_name]['cipher'])
        # self.rotate_ring_cipher()

        # for side, side_idx in self.sides.items():
        #     self.rotate_roller_cipher(side, self.rotor_info[side]['roller_window_offset'])

    def rotate_ring_cipher(self):
        """
        Rotate ring cipher (call once only)
        :return: None
        """
        for side, side_idx in self.sides.items():
            self.rotor_info[side]['ring_cipher'].rotate(-self.rotor_info[side]['ring_offset'])

    def next_letter(self, letter):
        """
        Perpetual letter incrementor
        :param letter:
        :return: Next letter in alphabet, rotates to 'A' if input is 'Z'
        """
        return chr(((ord(letter) - ord('A') + 1) % 26) + ord('A'))

    def incr_roller(self, side):
        letter = self.rotor_info[side]['roller_window'] = self.next_letter(self.rotor_info[side]['roller_window'])
        self.rotor_info[side]['roller_window_offset'] = ord(self.rotor_info[side]['roller_window']) - ord('A')
        return letter

    def rotate_roller(self, side):
        letter = self.incr_roller(side)
        if letter == self.rotor_info[side]['notch']:
            if side == 'right':
                letter = self.incr_roller('middle')
                if letter == self.rotor_info['middle']['notch']:
                    letter = self.incr_roller('left')
            elif side == 'middle':
                letter = self.incr_roller('left')


    # def update_roller_windows(self, side):
    #     self.rotor_info[side]['roller_window'] = self.rotor_info[side]['roller_cipher'][0]
    #     self.rotor_info[side]['roller_window_offset'] = ord(self.rotor_info[side]['roller_cipher'][0]) - ord('A')

    def get_alpha_index(self, letter):
        return ord(letter) - ord('A')

    def show_current_settings(self):
        pass
        print(f"\nPlugBoard cipher:........ {self.rotor_info['plugboard']['cipher']}")

        for side in ('left', 'middle', 'right'):
            print(f"\n{side} rotor:................ {self.rotor_info[side]['rotor']}")
            print(f"{side} ring offset:.......... {self.rotor_info[side]['ring_offset']}")
            print(f"{side} roller window:........ {self.rotor_info[side]['roller_window']}")
            print(f"{side} roller window offset:. {self.rotor_info[side]['roller_window_offset']}")
            print(f"{side}_alpha:................ {self.rotor_info[side]['alpha']}")
            print(f"{side}_cipher.......:........ {self.rotor_info[side]['cipher']}")
            print(f"{side}_notch:................ {self.rotor_info[side]['notch']}")

        print(f"\nreflector_cipher:............ {self.rotor_info['reflector_cipher']}")
            # print(f"self.current_{side}_offset:.. {self.rotor_info[side]['current_offset']}")

    def plugboard_encrypt(self, letter):
        idx = self.get_alpha_index(letter)
        return self.rotor_info['plugboard']['cipher'][idx]

    def rotor_encrypt(self, side, inchar):
        # Values needed
        print(f'\nrotor_encrypt - side: {side} input character: {inchar}')
        ring_offset = self.rotor_info[side]['ring_offset']
        cipher = self.rotor_info[side]['cipher']
        alpha_index = (self.get_alpha_index(inchar) + ring_offset) % 26

        # Alpha_char serves no purpose except for test aid
        alpha_char = self.rotor_info[side]['alpha'][alpha_index]
        cipher_char = cipher[alpha_index]

        print(f'add rotor {self.sides[side]} offset: alpha_index: {alpha_index}, alpha_char: {alpha_char}')
        print(f'rotor {self.sides[side]} from right: cipher_char: {cipher_char}')

        cipher_char_idx = (self.get_alpha_index(cipher_char) - (ring_offset + 1)) % 26
        outchar = cipher[cipher_char_idx]
        print(f'subtract rotor {self.sides[side]} offset: cipher_char_idx: {cipher_char_idx}, outchar: {outchar}')

        print(f'{outchar} <-- {side} ring encrypt <-- {inchar}')
        return outchar

    def encrypt_forward(self, letter):
        # run through patchboard
        pbchar = self.plugboard_encrypt(letter)
        print(f'\nplugboard --> {letter}')

        self.rotate_roller('right')

        rightchar = self.rotor_encrypt('right', pbchar)
        middlechar = self.rotor_encrypt('middle', rightchar)
        leftchar = self.rotor_encrypt('left', middlechar)



        # iidx = self.rotor_info[side]['ring_offset'] + (self.get_alpha_index(tchar) % 26)
        # output_letter = self.rotor_info[side]['cipher'][iidx]  # O
        # print(f'right output_letter: {output_letter}')
        # out_ltr_index = self.get_alpha_index(output_letter)
        # print(f'out_ltr_index: {out_ltr_index}')
        # rightchar = self.rotor_info[side]['cipher'][self.get_alpha_index(output_letter) -
        #                                         (self.rotor_info[side]['ring_offset'] + 1)]

        # side = 'middle'
        # ochar = rightchar
        # iidx = self.rotor_info[side]['ring_offset'] + (self.get_alpha_index(rightchar) % 26)
        # output_letter = self.rotor_info[side]['cipher'][iidx]  # O
        # middlechar = self.rotor_info[side]['cipher'][((self.get_alpha_index(output_letter) -
        #                                                (self.rotor_info[side]['ring_offset'] + 1)) % 26)]
        # print(f'\n{middlechar} <-- middle ring encrypt <-- {ochar}')
        #
        # side = 'left'
        # ochar = middlechar
        # iidx = self.rotor_info[side]['ring_offset'] + (self.get_alpha_index(middlechar) % 26)
        # output_letter = self.rotor_info[side]['cipher'][iidx]  # O
        # idx1 = self.get_alpha_index(output_letter)
        # stepn = ((self.rotor_info[side]['ring_offset'] + 1) % 26)
        # leftchar = self.rotor_info[side]['cipher'][(idx1 - stepn) % 26]
        # print(f'iidx: {iidx}, output_letter: {output_letter}, idx1: {idx1}, stepn: {stepn}')

        # leftchar = self.rotor_info[side]['cipher'][((self.get_alpha_index(output_letter) -
        #                                                (self.rotor_info[side]['ring_offset'] + 1)) % 26)]

        # print(f'\n{leftchar} <-- middle ring encrypt <-- {ochar}')

        # Should have a T at this point
        #     UKW  W.3   W.2   W.1   ETW   STK
        # ┌- t <-- s <-- o <-- e <-- e <-- e (REIN)
        # └> m --> y --> q --> g --> g --> g (RAUS)

        return 'A'

    def encrypt_message(self, message):
        for letter in message:
            self.show_current_settings()
            outchar = self.encrypt_forward(letter)

if __name__ == '__main__':
    # message = 'ENIGMA'
    message = 'E'
    az = EncryptDammit(plugboard_pairs=[['M', 'Z'], ['N', 'S']], rotors=[5, 3, 1],
              rings=[12, 4, 8], rotor_window=['Q', 'U', 'O'], reflector='B')
    # az.show_current_settings()
    az.encrypt_message(message)
EnigmaPaths.py
from pathlib import Path

class EnigmaPaths:
    def __init__(self):
        self.homepath = Path('.')
        self.datapath = self.homepath / 'data'
        self.imagepath = self.homepath / 'image'
        self.enigma_info = self.datapath / 'enigma_info.json'
        self.color_info = self.datapath / 'color_info.json'
        self.patchboard_image = self.imagepath / 'patchboard.ppm'

Attached Files

.json   enigma_info.json (Size: 908 bytes / Downloads: 205)
Reply


Messages In This Thread
Enigma Machine, I need help! - by Kimkuq - Nov-12-2017, 07:15 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-12-2017, 10:37 PM
RE: Enigma Machine, I need help! - by AceScottie - Nov-13-2017, 05:00 AM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-13-2017, 06:29 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-13-2017, 06:36 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-13-2017, 06:42 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-13-2017, 06:45 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-13-2017, 08:22 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-13-2017, 09:27 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-13-2017, 10:09 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-14-2017, 05:38 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-14-2017, 05:47 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-14-2017, 06:25 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-15-2017, 12:54 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-15-2017, 02:26 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-16-2017, 06:08 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-16-2017, 02:02 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-16-2017, 09:56 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-17-2017, 04:23 AM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-17-2017, 10:08 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-18-2017, 01:48 AM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-18-2017, 10:09 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-19-2017, 01:40 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-19-2017, 10:06 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-20-2017, 05:45 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-20-2017, 08:28 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-21-2017, 01:53 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-21-2017, 02:21 AM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-21-2017, 11:50 AM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-21-2017, 10:36 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-22-2017, 09:18 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-21-2017, 11:52 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-22-2017, 11:00 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-22-2017, 02:20 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-22-2017, 04:24 PM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-22-2017, 05:12 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-22-2017, 08:32 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-22-2017, 09:03 PM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-22-2017, 08:48 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-22-2017, 08:51 PM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-22-2017, 09:01 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-22-2017, 09:06 PM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-22-2017, 09:28 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-22-2017, 10:41 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-24-2017, 09:18 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-24-2017, 11:48 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-25-2017, 05:09 AM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-26-2017, 11:31 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Nov-26-2017, 01:56 PM
RE: Enigma Machine, I need help! - by Kimkuq - Nov-26-2017, 09:53 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-27-2017, 03:03 AM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-28-2017, 08:29 PM
RE: Enigma Machine, I need help! - by Larz60+ - Nov-29-2017, 01:42 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Dec-02-2017, 02:20 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-02-2017, 02:50 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-04-2017, 01:49 AM
RE: Enigma Machine, I need help! - by Kimkuq - Dec-06-2017, 09:58 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-06-2017, 11:04 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-07-2017, 02:08 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-08-2017, 11:35 AM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-16-2017, 02:08 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-18-2017, 05:53 AM
RE: Enigma Machine, I need help! - by Kimkuq - Dec-18-2017, 09:06 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-19-2017, 03:26 AM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-23-2017, 02:22 AM
RE: Enigma Machine, I need help! - by sparkz_alot - Dec-23-2017, 02:19 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-27-2017, 08:26 PM
RE: Enigma Machine, I need help! - by sparkz_alot - Dec-27-2017, 09:27 PM
RE: Enigma Machine, I need help! - by Larz60+ - Dec-28-2017, 01:49 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Numeric Enigma Machine idev 9 715 Mar-29-2024, 06:15 PM
Last Post: idev
  Enigma Decoding Problem krisarmstrong 4 835 Dec-14-2023, 10:42 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020