enigmapython 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. enigmapython/Enigma.py +86 -0
  2. enigmapython/EnigmaI.py +8 -0
  3. enigmapython/EnigmaINorway.py +8 -0
  4. enigmapython/EnigmaINorwayRotorI.py +11 -0
  5. enigmapython/EnigmaINorwayRotorII.py +11 -0
  6. enigmapython/EnigmaINorwayRotorIII.py +12 -0
  7. enigmapython/EnigmaINorwayRotorIV.py +12 -0
  8. enigmapython/EnigmaINorwayRotorV.py +12 -0
  9. enigmapython/EnigmaIRotorI.py +11 -0
  10. enigmapython/EnigmaIRotorII.py +11 -0
  11. enigmapython/EnigmaIRotorIII.py +11 -0
  12. enigmapython/EnigmaIRotorIV.py +12 -0
  13. enigmapython/EnigmaIRotorV.py +12 -0
  14. enigmapython/EnigmaISonder.py +8 -0
  15. enigmapython/EnigmaISonderRotorI.py +11 -0
  16. enigmapython/EnigmaISonderRotorII.py +12 -0
  17. enigmapython/EnigmaISonderRotorIII.py +12 -0
  18. enigmapython/EnigmaM3.py +8 -0
  19. enigmapython/EnigmaM3RotorI.py +10 -0
  20. enigmapython/EnigmaM3RotorII.py +10 -0
  21. enigmapython/EnigmaM3RotorIII.py +10 -0
  22. enigmapython/EnigmaM3RotorIV.py +10 -0
  23. enigmapython/EnigmaM3RotorV.py +10 -0
  24. enigmapython/EnigmaM3RotorVI.py +12 -0
  25. enigmapython/EnigmaM3RotorVII.py +12 -0
  26. enigmapython/EnigmaM3RotorVIII.py +12 -0
  27. enigmapython/EnigmaM4.py +8 -0
  28. enigmapython/EnigmaM4RotorBeta.py +12 -0
  29. enigmapython/EnigmaM4RotorGamma.py +12 -0
  30. enigmapython/EnigmaM4RotorI.py +10 -0
  31. enigmapython/EnigmaM4RotorII.py +10 -0
  32. enigmapython/EnigmaM4RotorIII.py +10 -0
  33. enigmapython/EnigmaM4RotorIV.py +9 -0
  34. enigmapython/EnigmaM4RotorV.py +9 -0
  35. enigmapython/EnigmaM4RotorVI.py +9 -0
  36. enigmapython/EnigmaM4RotorVII.py +9 -0
  37. enigmapython/EnigmaM4RotorVIII.py +10 -0
  38. enigmapython/Etw.py +14 -0
  39. enigmapython/EtwPassthrough.py +7 -0
  40. enigmapython/Observable.py +18 -0
  41. enigmapython/Observer.py +3 -0
  42. enigmapython/Plugboard.py +15 -0
  43. enigmapython/PlugboardPassthrough.py +7 -0
  44. enigmapython/Reflector.py +4 -0
  45. enigmapython/ReflectorNorwayUKW.py +9 -0
  46. enigmapython/ReflectorSonderUKW.py +9 -0
  47. enigmapython/ReflectorUKWA.py +9 -0
  48. enigmapython/ReflectorUKWB.py +9 -0
  49. enigmapython/ReflectorUKWBThin.py +9 -0
  50. enigmapython/ReflectorUKWC.py +10 -0
  51. enigmapython/ReflectorUKWCThin.py +10 -0
  52. enigmapython/Rotor.py +93 -0
  53. enigmapython/SwappablePlugboard.py +19 -0
  54. enigmapython/Utils.py +31 -0
  55. enigmapython/__init__.py +58 -0
  56. enigmapython-0.1.0.dist-info/METADATA +5 -0
  57. enigmapython-0.1.0.dist-info/RECORD +59 -0
  58. enigmapython-0.1.0.dist-info/WHEEL +5 -0
  59. enigmapython-0.1.0.dist-info/top_level.txt +1 -0
enigmapython/Enigma.py ADDED
@@ -0,0 +1,86 @@
1
+ from .Observer import Observer
2
+ from string import ascii_lowercase
3
+ import logging
4
+
5
+
6
+ class Enigma(Observer):
7
+
8
+ plugboard = None
9
+ rotors = None
10
+ reflector = None
11
+ etw = None
12
+ auto_increment_rotors = False
13
+
14
+ alphabet = list(ascii_lowercase)
15
+
16
+ def __init__(self, plugboard, rotors, reflector,etw,auto_increment_rotors=False):
17
+ self.plugboard = plugboard
18
+ self.rotors = rotors
19
+ self.reflector = reflector
20
+ self.etw = etw
21
+ self.auto_increment_rotors = auto_increment_rotors
22
+ if auto_increment_rotors == True:
23
+ for rotor in rotors:
24
+ rotor.add_observer(self)
25
+
26
+ def input_string(self,str):
27
+ output_string = ""
28
+ for char in str:
29
+ output_string += self.input_char(char)
30
+ return output_string
31
+
32
+ def input_char(self,char):
33
+ logging.info("Input char: {}".format(char))
34
+ ## Triggering rotors extra rotation due to double step issue
35
+ for rotor in self.rotors:
36
+ ## Rotor extra rotation should be done only if the rotor is not the last one in the list
37
+ if rotor.double_step_triggered == True and self.rotors.index(rotor) < len(self.rotors)-1:
38
+ rotor.increment_position()
39
+ rotor.double_step_triggered = False
40
+ if self.auto_increment_rotors == True:
41
+ self.rotors[0].increment_position()
42
+ scrambled_char = self.process_char(char)
43
+ return scrambled_char
44
+
45
+ def process_char(self, char):
46
+ scrambled_char = self.plugboard.switch_char(char)
47
+ logging.debug("Scrambled letter from plugboard: {}".format(scrambled_char))
48
+ iteration = 0
49
+ for rotor in self.rotors:
50
+ if iteration == 0:
51
+ scrambled_char = rotor.scramble_letter_index(rotor.wiring,Enigma.alphabet.index(scrambled_char))
52
+ else:
53
+ scrambled_char = rotor.scramble_letter_index(rotor.wiring,Enigma.alphabet.index(scrambled_char)-self.rotors[iteration-1].position)
54
+ iteration +=1
55
+ logging.debug("Scrambled letter from rotor{}: {}".format(str(iteration),scrambled_char))
56
+ scrambled_char = self.reflector.scramble_letter_index(self.reflector.wiring,(Enigma.alphabet.index(scrambled_char)-self.rotors[iteration-1].position))
57
+ logging.debug("Scrambled letter from reflector: {}".format(scrambled_char))
58
+ for rotor in reversed(self.rotors):
59
+ if iteration == len(self.rotors):
60
+ scrambled_char = rotor.scramble_letter_index(Enigma.alphabet,(rotor.wiring.index(Enigma.shift_letter(scrambled_char,rotor.position))-rotor.position))
61
+ else:
62
+ scrambled_char = rotor.scramble_letter_index(Enigma.alphabet,(rotor.wiring.index(Enigma.shift_letter(scrambled_char, (rotor.position - self.rotors[iteration].position))) - rotor.position))
63
+ iteration -=1
64
+ logging.debug("Scrambled letter from rotor{}: {}".format(str(iteration+1),scrambled_char))
65
+ scrambled_char = self.etw.switch_char(scrambled_char,-self.rotors[iteration].position)
66
+ logging.debug("Scrambled letter from ETW: {}".format(scrambled_char))
67
+ scrambled_char = self.plugboard.switch_char(scrambled_char)
68
+ logging.debug("Scrambled letter from plugboard: {}".format(scrambled_char))
69
+ logging.info("Scrambled letter to lamp: {}".format(scrambled_char))
70
+ return scrambled_char
71
+
72
+ def update(self, observable, *args, **kwargs):
73
+ # If there is rotor N+1, increment its position by 1
74
+ if observable in self.rotors and self.rotors.index(observable) < len(self.rotors)-1:
75
+ self.rotors[self.rotors.index(observable)+1].increment_position()
76
+ # Engaging the enigma double step issue, only if the next rotor position is in its notch indexe/s
77
+ if self.rotors[self.rotors.index(observable)+1].position in self.rotors[self.rotors.index(observable)+1].notch_indexes:
78
+ self.rotors[self.rotors.index(observable)+1].double_step_triggered = True
79
+
80
+ @staticmethod
81
+ def shift_letter(letter,shift):
82
+ return Enigma.alphabet[(Enigma.alphabet.index(letter)+shift) % len(Enigma.alphabet)]
83
+
84
+
85
+
86
+
@@ -0,0 +1,8 @@
1
+ from .Enigma import Enigma
2
+
3
+
4
+ class EnigmaI(Enigma):
5
+
6
+ def __init__(self,plugboard,rotor1, rotor2, rotor3,reflector,etw,auto_increment_rotors=False):
7
+ rotors = [rotor1, rotor2, rotor3]
8
+ super().__init__(plugboard,rotors,reflector,etw,auto_increment_rotors)
@@ -0,0 +1,8 @@
1
+ from .Enigma import Enigma
2
+
3
+
4
+ class EnigmaINorway(Enigma):
5
+
6
+ def __init__(self,plugboard,rotor1, rotor2, rotor3,reflector,etw,auto_increment_rotors=False):
7
+ rotors = [rotor1, rotor2, rotor3]
8
+ super().__init__(plugboard,rotors,reflector,etw,auto_increment_rotors)
@@ -0,0 +1,11 @@
1
+ from .Rotor import Rotor
2
+
3
+ class EnigmaINorwayRotorI(Rotor):
4
+
5
+ wiring = 'wtokasuyvrbxjhqcpzefmdinlg'
6
+ notch_indexes = [16]
7
+ tag = "IN_I"
8
+
9
+ def __init__(self, position = 0, ring = 0):
10
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
11
+
@@ -0,0 +1,11 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaINorwayRotorII(Rotor):
5
+
6
+ wiring = 'gjlpubswemctqvhxaofzdrkyni'
7
+ notch_indexes = [4]
8
+ tag = "IN_II"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaINorwayRotorIII(Rotor):
5
+
6
+ wiring = 'jwfmhnbpusdytixvzgrqlaoekc'
7
+ notch_indexes = [21]
8
+ tag = "IN_III"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaINorwayRotorIV(Rotor):
5
+
6
+ wiring = 'fgzjmvxepbwshqtliudykcnrao'
7
+ notch_indexes = [21]
8
+ tag = "IN_IV"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaINorwayRotorV(Rotor):
5
+
6
+ wiring = 'hejxqotzbvfdascilwpgynmurk'
7
+ notch_indexes = [25]
8
+ tag = "IN_V"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,11 @@
1
+ from .Rotor import Rotor
2
+
3
+ class EnigmaIRotorI(Rotor):
4
+
5
+ wiring = 'ekmflgdqvzntowyhxuspaibrcj'
6
+ notch_indexes = [16]
7
+ tag = "I_I"
8
+
9
+ def __init__(self, position = 0, ring = 0):
10
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
11
+
@@ -0,0 +1,11 @@
1
+ from .Rotor import Rotor
2
+
3
+ class EnigmaIRotorII(Rotor):
4
+
5
+ wiring = 'ajdksiruxblhwtmcqgznpyfvoe'
6
+ notch_indexes = [4]
7
+ tag = "I_II"
8
+
9
+ def __init__(self, position = 0, ring = 0):
10
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
11
+
@@ -0,0 +1,11 @@
1
+ from .Rotor import Rotor
2
+
3
+ class EnigmaIRotorIII(Rotor):
4
+
5
+ wiring = 'bdfhjlcprtxvznyeiwgakmusqo'
6
+ notch_indexes = [21]
7
+ tag = "I_III"
8
+
9
+ def __init__(self, position = 0, ring = 0):
10
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
11
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaIRotorIV(Rotor):
5
+
6
+ wiring = 'esovpzjayquirhxlnftgkdcmwb'
7
+ notch_indexes = [9]
8
+ tag = "I_IV"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaIRotorV(Rotor):
5
+
6
+ wiring = 'vzbrgityupsdnhlxawmjqofeck'
7
+ notch_indexes = [25]
8
+ tag = "I_V"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,8 @@
1
+ from .Enigma import Enigma
2
+
3
+
4
+ class EnigmaISonder(Enigma):
5
+
6
+ def __init__(self,plugboard,rotor1, rotor2, rotor3,reflector,etw,auto_increment_rotors=False):
7
+ rotors = [rotor1, rotor2, rotor3]
8
+ super().__init__(plugboard,rotors,reflector,etw,auto_increment_rotors)
@@ -0,0 +1,11 @@
1
+ from .Rotor import Rotor
2
+
3
+ class EnigmaISonderRotorI(Rotor):
4
+
5
+ wiring = 'veosirzujdqckgwypnxaflthmb'
6
+ notch_indexes = [16]
7
+ tag = "IS_I"
8
+
9
+ def __init__(self, position = 0, ring = 0):
10
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
11
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaISonderRotorII(Rotor):
5
+
6
+ #wiring = 'uemoatqlshpkcyfwjzbgvxindr'
7
+ wiring = 'uemoatqlshpkcyfwjzbgvxidnr'
8
+ notch_indexes = [4]
9
+ tag = "IS_II"
10
+
11
+ def __init__(self, position = 0, ring = 0):
12
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaISonderRotorIII(Rotor):
5
+
6
+ wiring = 'tzhxmbsipnurjfdkeqvcwglaoy'
7
+ notch_indexes = [21]
8
+ tag = "IS_III"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,8 @@
1
+ from .Enigma import Enigma
2
+
3
+
4
+ class EnigmaM3(Enigma):
5
+
6
+ def __init__(self,plugboard,rotor1, rotor2, rotor3,reflector,etw,auto_increment_rotors=False):
7
+ rotors = [rotor1, rotor2, rotor3]
8
+ super().__init__(plugboard,rotors,reflector,etw,auto_increment_rotors)
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaIRotorI import EnigmaIRotorI
3
+
4
+ class EnigmaM3RotorI(EnigmaIRotorI):
5
+
6
+ tag = "M3_I"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaIRotorII import EnigmaIRotorII
3
+
4
+ class EnigmaM3RotorII(EnigmaIRotorII):
5
+
6
+ tag = "M3_II"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaIRotorIII import EnigmaIRotorIII
3
+
4
+ class EnigmaM3RotorIII(EnigmaIRotorIII):
5
+
6
+ tag = "M3_III"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaIRotorIV import EnigmaIRotorIV
3
+
4
+ class EnigmaM3RotorIV(EnigmaIRotorIV):
5
+
6
+ tag = "M3_IV"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaIRotorV import EnigmaIRotorV
3
+
4
+ class EnigmaM3RotorV(EnigmaIRotorV):
5
+
6
+ tag = "M3_V"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaM3RotorVI(Rotor):
5
+
6
+ wiring = 'jpgvoumfyqbenhzrdkasxlictw'
7
+ notch_indexes = [12,25]
8
+ tag = "M3_VI"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaM3RotorVII(Rotor):
5
+
6
+ wiring = 'nzjhgrcxmyswboufaivlpekqdt'
7
+ notch_indexes = [12,25]
8
+ tag = "M3_VII"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaM3RotorVIII(Rotor):
5
+
6
+ wiring = 'fkqhtlxocbjspdzramewniuygv'
7
+ notch_indexes = [12,25]
8
+ tag = "M3_VIII"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,8 @@
1
+ from .Enigma import Enigma
2
+
3
+
4
+ class EnigmaM4(Enigma):
5
+
6
+ def __init__(self, plugboard, rotor1, rotor2, rotor3, rotor4, reflector, etw, auto_increment_rotors=False):
7
+ rotors = [rotor1, rotor2, rotor3, rotor4]
8
+ super().__init__(plugboard,rotors,reflector,etw,auto_increment_rotors)
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaM4RotorBeta(Rotor):
5
+
6
+ wiring = 'leyjvcnixwpbqmdrtakzgfuhos'
7
+ notch_indexes = []
8
+ tag = "M4_Beta"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,12 @@
1
+ from .Rotor import Rotor
2
+
3
+
4
+ class EnigmaM4RotorGamma(Rotor):
5
+
6
+ wiring = 'fsokanuerhmbtiycwlqpzxvgjd'
7
+ notch_indexes = []
8
+ tag = "M4_Gamma"
9
+
10
+ def __init__(self, position = 0, ring = 0):
11
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
12
+
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaM3RotorI import EnigmaM3RotorI
3
+
4
+ class EnigmaM4RotorI(EnigmaM3RotorI):
5
+
6
+ tag = "M4_I"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaM3RotorII import EnigmaM3RotorII
3
+
4
+ class EnigmaM4RotorII(EnigmaM3RotorII):
5
+
6
+ tag = "M4_II"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .EnigmaM3RotorIII import EnigmaM3RotorIII
3
+
4
+ class EnigmaM4RotorIII(EnigmaM3RotorIII):
5
+
6
+ tag = "M4_III"
7
+
8
+ def __init__(self, position = 0, ring = 0):
9
+ super().__init__(position, ring)
10
+
@@ -0,0 +1,9 @@
1
+ from .EnigmaM3RotorIV import EnigmaM3RotorIV
2
+
3
+ class EnigmaM4RotorIV(EnigmaM3RotorIV):
4
+
5
+ tag = "M4_IV"
6
+
7
+ def __init__(self, position = 0, ring = 0):
8
+ super().__init__(position, ring)
9
+
@@ -0,0 +1,9 @@
1
+ from .EnigmaM3RotorV import EnigmaM3RotorV
2
+
3
+ class EnigmaM4RotorV(EnigmaM3RotorV):
4
+
5
+ tag = "M4_V"
6
+
7
+ def __init__(self, position = 0, ring = 0):
8
+ super().__init__(position, ring)
9
+
@@ -0,0 +1,9 @@
1
+ from .EnigmaM3RotorVI import EnigmaM3RotorVI
2
+
3
+ class EnigmaM4RotorVI(EnigmaM3RotorVI):
4
+
5
+ tag = "M4_VI"
6
+
7
+ def __init__(self, position = 0, ring = 0):
8
+ super().__init__(position, ring)
9
+
@@ -0,0 +1,9 @@
1
+ from .EnigmaM3RotorVII import EnigmaM3RotorVII
2
+
3
+ class EnigmaM4RotorVII(EnigmaM3RotorVII):
4
+
5
+ tag = "M4_VII"
6
+
7
+ def __init__(self, position = 0, ring = 0):
8
+ super().__init__(position, ring)
9
+
@@ -0,0 +1,10 @@
1
+ from .EnigmaM3RotorVIII import EnigmaM3RotorVIII
2
+
3
+ class EnigmaM4RotorVIII(EnigmaM3RotorVIII):
4
+
5
+ tag = "M4_VIII"
6
+
7
+ def __init__(self, position = 0, ring = 0):
8
+ super().__init__(position, ring)
9
+
10
+
enigmapython/Etw.py ADDED
@@ -0,0 +1,14 @@
1
+
2
+ from string import ascii_lowercase
3
+
4
+ class Etw:
5
+ wiring = None
6
+
7
+ def switch_char(self,char,shift):
8
+ return self.wiring[self.wiring.index(char)+shift]
9
+
10
+ def __init__(self, wiring):
11
+ self.wiring = wiring
12
+
13
+ def __str__(self):
14
+ return self.wiring
@@ -0,0 +1,7 @@
1
+ from .Etw import Etw
2
+
3
+ class EtwPassthrough(Etw):
4
+ wiring = "abcdefghijklmnopqrstuvwxyz"
5
+
6
+ def __init__(self):
7
+ super().__init__(self.wiring)
@@ -0,0 +1,18 @@
1
+ class Observable:
2
+
3
+ observers = []
4
+
5
+ def __init__(self):
6
+ self.observers = []
7
+
8
+ def add_observer(self, observer):
9
+ if observer not in self.observers:
10
+ self.observers.append(observer)
11
+
12
+ def remove_observer(self, observer):
13
+ if observer in self.observers:
14
+ self.observers.remove(observer)
15
+
16
+ def notify_observers(self, *args, **kwargs):
17
+ for observer in self.observers:
18
+ observer.update(self, *args, **kwargs)
@@ -0,0 +1,3 @@
1
+ class Observer:
2
+ def update(self, observable, *args, **kwargs):
3
+ pass
@@ -0,0 +1,15 @@
1
+
2
+ from string import ascii_lowercase
3
+
4
+ class Plugboard:
5
+ wiring = None
6
+
7
+ def switch_char(self,char):
8
+ alphabet = list(ascii_lowercase)
9
+ return self.wiring[alphabet.index(char)]
10
+
11
+ def __init__(self, wiring):
12
+ self.wiring = wiring
13
+
14
+ def __str__(self):
15
+ return self.wiring
@@ -0,0 +1,7 @@
1
+ from .Plugboard import Plugboard
2
+
3
+ class PlugboardPassthrough(Plugboard):
4
+ wiring = "abcdefghijklmnopqrstuvwxyz"
5
+
6
+ def __init__(self):
7
+ super().__init__(self.wiring)
@@ -0,0 +1,4 @@
1
+ from .Rotor import Rotor
2
+
3
+ class Reflector(Rotor):
4
+ tag = None
@@ -0,0 +1,9 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+ class ReflectorNorwayUKW(Reflector):
4
+
5
+ wiring = 'mowjypuxndsraibfvlkzgqchet'
6
+ tag = "IN_UKW"
7
+
8
+ def __init__(self):
9
+ super().__init__(self.wiring,0)
@@ -0,0 +1,9 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+ class ReflectorSonderUKW(Reflector):
4
+
5
+ wiring = 'ciagsndrbytpzfulvhekoqxwjm'
6
+ tag = "IS_UKW"
7
+
8
+ def __init__(self):
9
+ super().__init__(self.wiring,0)
@@ -0,0 +1,9 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+ class ReflectorUKWA(Reflector):
4
+
5
+ wiring = 'ejmzalyxvbwfcrquontspikhgd'
6
+ tag = "UKW-A"
7
+
8
+ def __init__(self):
9
+ super().__init__(self.wiring,0)
@@ -0,0 +1,9 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+ class ReflectorUKWB(Reflector):
4
+
5
+ wiring = 'yruhqsldpxngokmiebfzcwvjat'
6
+ tag = "UKW-B"
7
+
8
+ def __init__(self):
9
+ super().__init__(self.wiring,0)
@@ -0,0 +1,9 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+ class ReflectorUKWBThin(Reflector):
4
+
5
+ wiring = 'enkqauywjicopblmdxzvfthrgs'
6
+ tag = "UKW-BT"
7
+
8
+ def __init__(self):
9
+ super().__init__(self.wiring,0)
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+
4
+ class ReflectorUKWC(Reflector):
5
+
6
+ wiring = 'fvpjiaoyedrzxwgctkuqsbnmhl'
7
+ tag = "UKW-C"
8
+
9
+ def __init__(self):
10
+ super().__init__(self.wiring,0)
@@ -0,0 +1,10 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+
4
+ class ReflectorUKWCThin(Reflector):
5
+
6
+ wiring = 'rdobjntkvehmlfcwzaxgyipsuq'
7
+ tag = "UKW-CT"
8
+
9
+ def __init__(self):
10
+ super().__init__(self.wiring,0)
enigmapython/Rotor.py ADDED
@@ -0,0 +1,93 @@
1
+ from .Observable import Observable
2
+ from .Utils import Utils
3
+ from string import ascii_lowercase
4
+ import logging
5
+
6
+ class Rotor(Observable):
7
+ original_wiring = None
8
+ wiring = None
9
+ position = None
10
+ rotations_counter = None
11
+ notch_indexes = None
12
+ double_step_triggered = None
13
+ ring = None
14
+ dot_position = None
15
+ lookup = {}
16
+
17
+ @staticmethod
18
+ def register(tag, class_name):
19
+ Rotor.lookup[tag] = class_name
20
+
21
+ def reset_position(self):
22
+ self.position = 0
23
+
24
+ def increment_position(self):
25
+ self.position = ((self.position + 1) % len(self.wiring))
26
+ self.rotations_counter = self.rotations_counter + 1
27
+ for notch_index in self.notch_indexes:
28
+ logging.debug("Evaluating notch_index {} against position {}".format(notch_index+1,self.position))
29
+ if (self.position == ((notch_index+1) % len(self.wiring))):
30
+ logging.debug("Found that rotor position {} is equals to notch {}, notifying observers".format(self.position, ((notch_index+1) % len(self.wiring))))
31
+ self.notify_observers(None,None)
32
+
33
+ def set_position(self,position):
34
+ self.position = position % len(self.wiring)
35
+ self.rotations_counter = 0
36
+
37
+ def scramble_letter_index(self, dictionary, letter_index):
38
+ scrambled_letter_index_from_rotor = dictionary.index(dictionary[(self.position + letter_index) % len(dictionary)])
39
+ return dictionary[scrambled_letter_index_from_rotor]
40
+
41
+ def __init__(self, wiring, position = 0, ring = 0, notch_indexes=[]):
42
+ self.wiring = wiring
43
+ self.position = position % len(wiring)
44
+ self.notch_indexes = notch_indexes
45
+ self.double_step_triggered = False
46
+ self.rotations_counter = 0
47
+ self.original_wiring = self.wiring
48
+ self.ring = ring
49
+ self.set_rotor_ring(ring)
50
+
51
+ def __str__(self):
52
+ pointer = ' ' * self.position + '^'
53
+ return self.wiring + '\n' + pointer
54
+
55
+ def __eq__(self, __value: object) -> bool:
56
+ return id(self) == id(object)
57
+
58
+ def set_rotor_ring(self, ring):
59
+ self.wiring = self.original_wiring
60
+ self.dot_position = list(self.wiring).index("a")
61
+ logging.debug("Dot position: " + str(self.dot_position))
62
+ alphabet = list(ascii_lowercase)
63
+ for i in range(0, ring):
64
+ # Set temporary wiring variable
65
+ temp_wiring = self.wiring
66
+ # Set actual wiring to empty string
67
+ wiring = ""
68
+ # Loop over chars in temporary wiring
69
+ for char in temp_wiring:
70
+ # Shift the char by one and add that shifted char to wiring variable
71
+ wiring += Rotor.shift(char, 1, alphabet)
72
+ # Add one to dot position, make sure we don't exceed the lenght of the alphabet
73
+ self.wiring = wiring
74
+ self.dot_position = (self.dot_position + 1) % len(alphabet)
75
+ logging.debug("Wiring shifted up the alphabet: " + wiring)
76
+ logging.debug("New dot position: " + str(self.dot_position))
77
+ i = 0
78
+ # While the letter at the dot position doesn't match with the ringstellung
79
+ while not self.wiring[self.dot_position] == alphabet[ring % len(self.wiring)]:
80
+ i += 1
81
+ # Rotate the wiring
82
+ self.wiring = self.wiring[-1:] + self.wiring[:-1]
83
+ logging.debug("Rotation " + str(i).zfill(2) + "; Wiring: " + self.wiring)
84
+
85
+ @staticmethod
86
+ def shift(letter, shift, alphabet):
87
+ for i in range(0, len(alphabet)):
88
+ if alphabet[i] == letter:
89
+ return alphabet[(i + shift) % len(alphabet)]
90
+
91
+ @staticmethod
92
+ def get_instance_from_tag(tag: str):
93
+ return Utils.get_class_instance(Rotor.lookup[tag].__module__+"."+Rotor.lookup[tag].__name__)()
@@ -0,0 +1,19 @@
1
+ from .Plugboard import Plugboard
2
+ from .Utils import Utils
3
+ from .PlugboardPassthrough import PlugboardPassthrough
4
+
5
+ class SwappablePlugboard(PlugboardPassthrough):
6
+
7
+ def __init__(self, chars=None):
8
+ super().__init__()
9
+ self.bulk_swap(chars)
10
+
11
+ def bulk_swap(self,chars):
12
+ if chars != None and isinstance(chars, dict):
13
+ for key, value in chars.items():
14
+ self.swap(key,value)
15
+
16
+ def swap(self, c1, c2):
17
+ if c1 != None and self.wiring.__contains__(c1) and c2 != None and self.wiring.__contains__(c2):
18
+ self.wiring = Utils.swap_chars(self.wiring, c1, c2)
19
+
enigmapython/Utils.py ADDED
@@ -0,0 +1,31 @@
1
+ from importlib import import_module
2
+
3
+ class Utils:
4
+
5
+ @staticmethod
6
+ def find_all_subclasses(cls):
7
+ return set(cls.__subclasses__()).union(
8
+ [s for c in cls.__subclasses__() for s in Utils.find_all_subclasses(c)])
9
+
10
+ @staticmethod
11
+ def get_class_instance(cls):
12
+ try:
13
+ module_path, class_name = cls.rsplit('.', 1)
14
+ module = import_module(module_path)
15
+ return getattr(module, class_name)
16
+ except (ImportError, AttributeError) as e:
17
+ raise ImportError(cls)
18
+
19
+ @staticmethod
20
+ def swap_chars(string, ch1, ch2):
21
+ if ch1 == ch2: return string
22
+ str_list = []
23
+ for char in string:
24
+ if char == ch1:
25
+ str_list.append(ch2)
26
+ elif char == ch2:
27
+ str_list.append(ch1)
28
+ else:
29
+ str_list.append(char)
30
+ return ''.join(str_list)
31
+
@@ -0,0 +1,58 @@
1
+ __all__ = [
2
+ 'EnigmaIRotorI',
3
+ 'EnigmaIRotorII',
4
+ 'EnigmaIRotorIII',
5
+ 'EnigmaIRotorIV',
6
+ 'EnigmaIRotorV',
7
+ 'EnigmaINorwayRotorI',
8
+ 'EnigmaINorwayRotorII',
9
+ 'EnigmaINorwayRotorIII',
10
+ 'EnigmaINorwayRotorIV',
11
+ 'EnigmaINorwayRotorV',
12
+ 'EnigmaISonderRotorI',
13
+ 'EnigmaISonderRotorII',
14
+ 'EnigmaISonderRotorIII',
15
+ 'EnigmaM3RotorI',
16
+ 'EnigmaM3RotorII',
17
+ 'EnigmaM3RotorIII',
18
+ 'EnigmaM3RotorIV',
19
+ 'EnigmaM3RotorV',
20
+ 'EnigmaM3RotorVI',
21
+ 'EnigmaM3RotorVII',
22
+ 'EnigmaM3RotorVIII',
23
+ 'EnigmaM4RotorI',
24
+ 'EnigmaM4RotorII',
25
+ 'EnigmaM4RotorIII',
26
+ 'EnigmaM4RotorIV',
27
+ 'EnigmaM4RotorV',
28
+ 'EnigmaM4RotorVI',
29
+ 'EnigmaM4RotorVII',
30
+ 'EnigmaM4RotorVIII',
31
+ 'EnigmaM4RotorBeta',
32
+ 'EnigmaM4RotorGamma',
33
+ 'Utils',
34
+ 'Rotor',
35
+ 'Plugboard',
36
+ 'PlugboardPassthrough',
37
+ 'Etw',
38
+ 'EtwPassthrough',
39
+ 'Reflector',
40
+ 'ReflectorNorwayUKW',
41
+ 'ReflectorSonderUKW',
42
+ 'ReflectorUKWA',
43
+ 'ReflectorUKWB',
44
+ 'ReflectorUKWBThin',
45
+ 'ReflectorUKWC',
46
+ 'ReflectorUKWCThin',
47
+ 'EnigmaI',
48
+ 'EnigmaINorway',
49
+ 'EnigmaISonder',
50
+ 'EnigmaM3',
51
+ 'EnigmaM4',
52
+ ]
53
+ from .Rotor import Rotor
54
+ from .Utils import Utils
55
+ from . import *
56
+
57
+ for sub in Utils.find_all_subclasses(Rotor):
58
+ Rotor.register(sub.tag,sub)
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.1
2
+ Name: enigmapython
3
+ Version: 0.1.0
4
+ Description-Content-Type: text/markdown
5
+
@@ -0,0 +1,59 @@
1
+ enigmapython/Enigma.py,sha256=ZoWGcAuJBI6LxXSmizimR9VMLhV18lQwFEsKr2kdYmI,4230
2
+ enigmapython/EnigmaI.py,sha256=hpttzjWTqpaW8vLljn1TRTmg4KECHUgPtwBQAi5snXc,278
3
+ enigmapython/EnigmaINorway.py,sha256=E6jkja7xNvC7xoBuwe3qrKlcPBFLSEeZcFxCT2-6fsg,284
4
+ enigmapython/EnigmaINorwayRotorI.py,sha256=xWMWIYq5rzoCl8kYhmffHUiZmp1muPWly7DD5BCs-3o,281
5
+ enigmapython/EnigmaINorwayRotorII.py,sha256=eBpmVpDc40iYohuyPhkxPuKBl5tk4kaL0eaGhR6VPvo,277
6
+ enigmapython/EnigmaINorwayRotorIII.py,sha256=WnbY6UqKI2aYGrqYjU53wnMJg4mJHVGtNFqVvQThzbw,278
7
+ enigmapython/EnigmaINorwayRotorIV.py,sha256=TeZfWpwcvrLG6bwoQ0VnQZtt4YFTxdqMiR8M-YYmwFI,276
8
+ enigmapython/EnigmaINorwayRotorV.py,sha256=5czOZqiM0XIVBcZASCAe8wMcnJxeDZsv-AdyMgaB1qE,274
9
+ enigmapython/EnigmaIRotorI.py,sha256=WSyssFcYLjYI2yrZKlxcvZ1Qcfllua3MOHzDQg9ZiZU,274
10
+ enigmapython/EnigmaIRotorII.py,sha256=OHOsJNdZukUi4Po1YqV_n8d7eiMGj-weE5MRgur4PEQ,275
11
+ enigmapython/EnigmaIRotorIII.py,sha256=LDeRBwOY0bqkVJn0Sd6asaswi72Gb7keG6mDa1pr1gw,278
12
+ enigmapython/EnigmaIRotorIV.py,sha256=KlFIozCjg98YZQ4oAW3KOLumDkJ9NovA3AgG1166q54,268
13
+ enigmapython/EnigmaIRotorV.py,sha256=PPNh0CWYO6kbctdRaoV251eTQKCym_acT_4HmTJM9OU,267
14
+ enigmapython/EnigmaISonder.py,sha256=EdS90URItG-q4qzdcItRvb_rf8W6cJlq9NrCM2cgcCM,284
15
+ enigmapython/EnigmaISonderRotorI.py,sha256=h2KtjKPPYUu3ZWxuXwUyClBjbcvx_gJEkM9KzyLcGRo,281
16
+ enigmapython/EnigmaISonderRotorII.py,sha256=kjUoSSY68ndS5V76npDhVtvBtQaiuEub5siZ_YEUIyM,320
17
+ enigmapython/EnigmaISonderRotorIII.py,sha256=Kg3SKbJtRriQG63dEwKLs8IzYxHAD0yGYJRy1yzQi0U,278
18
+ enigmapython/EnigmaM3.py,sha256=vQEE0RBblXLODs-T-4k621XB4Urm1U8x0DViSSDmmRM,279
19
+ enigmapython/EnigmaM3RotorI.py,sha256=RkWfcp97UEcxBI6BZTBdGE1MzsGdbDdqNCbPb3Z2nrA,217
20
+ enigmapython/EnigmaM3RotorII.py,sha256=kzqHIke1urNjJfQ5n08OPrVeTaj8DtvGiq_rSs6Tqc8,222
21
+ enigmapython/EnigmaM3RotorIII.py,sha256=DAHxFwj9GlYZ5DbJUyvS1ENwAPc7YwJgQQwqemYdIzg,227
22
+ enigmapython/EnigmaM3RotorIV.py,sha256=WALWJYS9XDRnoNaQ3x3NXI7nuOEB31kzwZhA4h4M9pA,222
23
+ enigmapython/EnigmaM3RotorV.py,sha256=2jHZNc51Ho4RLP1yownx9gxO-IMuUzjx9Ff7zzZ2Q9Q,217
24
+ enigmapython/EnigmaM3RotorVI.py,sha256=5vtNAz7MTj2rYa387WsOAp9C8b7Tl8AISLsEQbStTIM,274
25
+ enigmapython/EnigmaM3RotorVII.py,sha256=p628P-ud50LmJPl0QV3rnBjUaX37QzKrDpS2eljuGk8,276
26
+ enigmapython/EnigmaM3RotorVIII.py,sha256=KYOS4tOGljpHY2TtvBqR3KiwgQOxoWNydSKkPh2piKk,278
27
+ enigmapython/EnigmaM4.py,sha256=h_DGwJF9BUo-km4BLL6OFTVHUZbE48rCPxORA5jBE70,300
28
+ enigmapython/EnigmaM4RotorBeta.py,sha256=wBygpofb4m7t9KL80RQ5H2ifwHxFRb6c4FNeP0ucKNA,273
29
+ enigmapython/EnigmaM4RotorGamma.py,sha256=rO2uY7Fw3aS5JPOZX0zVIduSvXmCObWh-DeT9rS2lj0,275
30
+ enigmapython/EnigmaM4RotorI.py,sha256=px_MXfYFX_mN--bpqTu5IO_9aqveSeAEkQUn2jeHBZo,220
31
+ enigmapython/EnigmaM4RotorII.py,sha256=Gma6TZUhwU83sTgiwZYZVEeJUenOdN3--dmP3zbkH2c,225
32
+ enigmapython/EnigmaM4RotorIII.py,sha256=HrZsP-jrwRcssrtB9-2RAYJZIrL5mbGoUCvodCySjak,230
33
+ enigmapython/EnigmaM4RotorIV.py,sha256=IxQv4x9h7zSpK4XcYR3ImgpKWyZrxUilwz8nFUAWZAg,200
34
+ enigmapython/EnigmaM4RotorV.py,sha256=73UWfrM2iETZDHIQhKGPuwi2yD78CBJbISliBgDrdSo,195
35
+ enigmapython/EnigmaM4RotorVI.py,sha256=tjiFDQE0BZkn3DwRU3ItdDXLIH6BPiDHFAhPlZVKW1Q,196
36
+ enigmapython/EnigmaM4RotorVII.py,sha256=pX8k-Ow2WqHuHZdNDKaFy7t2qRhGDZPTLmV26ZzBq4g,201
37
+ enigmapython/EnigmaM4RotorVIII.py,sha256=xIpFDFHw8C5E-rYKASGR6uRuQQcOUt90MNSmYsY1tkY,207
38
+ enigmapython/Etw.py,sha256=PI1EwG0IgEAwOrZbkZ_MhWAqcSsM84Cj-PuII1I-6hM,275
39
+ enigmapython/EtwPassthrough.py,sha256=FEk7aIF0CAKebBZzz0CAFCevTMxwE2deCy9tSLJU3Zo,154
40
+ enigmapython/Observable.py,sha256=9zFynI_gQuZDIR-1NZVq1T9lykaInCwtPa53_f3l3oM,482
41
+ enigmapython/Observer.py,sha256=0KBmvK4g00ag0w0CX1Ly9HAWSE2Dsn9fGKua2LUQQ-o,79
42
+ enigmapython/Plugboard.py,sha256=hjnabPPGhMW2XAHVEhua9dfFWiRCBGa-Q2JamJn1Z9A,307
43
+ enigmapython/PlugboardPassthrough.py,sha256=k6VUayOgqYL6-9XnK-F8PUwubyzRZF4xxVTmmmtOS1s,179
44
+ enigmapython/Reflector.py,sha256=T2iUu-4YIXhrH6-os7GW0tmnDlmJMWkw_yTI7pLfwqU,64
45
+ enigmapython/ReflectorNorwayUKW.py,sha256=dbUXVbdD5P_9FrTICdqKkRIgP7VBNh7-yW-9bb27rvk,229
46
+ enigmapython/ReflectorSonderUKW.py,sha256=WMOaSdQiwuWlCzAV6dKrjYwhut4vLiyaP50f1eBd98k,229
47
+ enigmapython/ReflectorUKWA.py,sha256=sRGIjXnULBZKPXKD5ZXE5LGZVwk8m7QD7UEUBdLAieA,223
48
+ enigmapython/ReflectorUKWB.py,sha256=ZMgwvnP-kOjXoGWdJ86946AllgTwRsMvtvaY-9WejAo,223
49
+ enigmapython/ReflectorUKWBThin.py,sha256=GVySP8f0tnoKa0mhFcCdTGRezIlQgcgVgh6eZcNCaLs,228
50
+ enigmapython/ReflectorUKWC.py,sha256=hCbE79kd21MC9gX6mM0N-Hnkx9crRc88PPL0pKPyHOc,224
51
+ enigmapython/ReflectorUKWCThin.py,sha256=50wyVP-CdqXMDkM48LbBy0A73JVXNbynFOu0d6j-084,229
52
+ enigmapython/Rotor.py,sha256=Oe-r2Km3Cc2rTuLzhcwRlVSS5uOAzJyfxTtPeEjaQ_c,3822
53
+ enigmapython/SwappablePlugboard.py,sha256=xsDuzTWk6qACBwi3VoKLLHvtkL4H_qMUQ1gqziC3S5M,630
54
+ enigmapython/Utils.py,sha256=oYobnAsvrbxwWJmkJn18p8ib1mk31_6GjZThDa50AsQ,912
55
+ enigmapython/__init__.py,sha256=UTB1GdVmwL6OKkUOK0bzWxlBh4VDAtukVfHxDi_ttaA,1495
56
+ enigmapython-0.1.0.dist-info/METADATA,sha256=-dCGRzCyIqVjttL4m3FmsMB5JBSyWqwHTFR2JVw_H38,97
57
+ enigmapython-0.1.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
58
+ enigmapython-0.1.0.dist-info/top_level.txt,sha256=9lDElg8HslLQqbh6IYiY2UPRwC0EdCY4AdZKm3sl0Po,13
59
+ enigmapython-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.43.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ enigmapython