enigmapython 2.0.2__tar.gz → 3.0.1__tar.gz

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 (94) hide show
  1. {enigmapython-2.0.2 → enigmapython-3.0.1}/PKG-INFO +66 -15
  2. enigmapython-3.0.1/enigmapython/DynamicTurnoverRotor.py +39 -0
  3. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Enigma.py +2 -3
  4. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaB_A133RotorI.py +2 -2
  5. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaB_A133RotorII.py +2 -2
  6. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaB_A133RotorIII.py +2 -2
  7. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaDRotorI.py +6 -4
  8. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaDRotorII.py +6 -5
  9. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaDRotorIII.py +6 -5
  10. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaINorwayRotorI.py +2 -2
  11. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaINorwayRotorII.py +2 -2
  12. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaINorwayRotorIII.py +2 -2
  13. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaINorwayRotorIV.py +2 -2
  14. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaINorwayRotorV.py +2 -2
  15. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaIRotorI.py +2 -2
  16. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaIRotorII.py +2 -2
  17. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaIRotorIII.py +2 -2
  18. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaIRotorIV.py +2 -2
  19. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaIRotorV.py +2 -2
  20. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaISonderRotorI.py +2 -2
  21. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaISonderRotorII.py +2 -2
  22. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaISonderRotorIII.py +2 -2
  23. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaKRotorI.py +2 -2
  24. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaKRotorII.py +2 -2
  25. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaKRotorIII.py +2 -2
  26. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorI.py +2 -2
  27. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorII.py +2 -2
  28. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorIII.py +2 -2
  29. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorIV.py +2 -2
  30. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorV.py +2 -2
  31. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorVI.py +2 -2
  32. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorVII.py +2 -2
  33. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3RotorVIII.py +2 -2
  34. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorBeta.py +2 -2
  35. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorGamma.py +2 -2
  36. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorI.py +2 -2
  37. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorII.py +2 -2
  38. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorIII.py +2 -2
  39. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorIV.py +2 -2
  40. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorV.py +2 -2
  41. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorVI.py +2 -2
  42. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorVII.py +2 -2
  43. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4RotorVIII.py +2 -2
  44. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaZRotorI.py +2 -2
  45. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaZRotorII.py +2 -2
  46. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaZRotorIII.py +2 -2
  47. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKW_EnigmaZ.py +2 -2
  48. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Rotor.py +8 -9
  49. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Settable.py +23 -7
  50. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython.egg-info/PKG-INFO +66 -15
  51. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython.egg-info/SOURCES.txt +1 -0
  52. {enigmapython-2.0.2 → enigmapython-3.0.1}/setup.py +1 -1
  53. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Alphabets.py +0 -0
  54. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Clonable.py +0 -0
  55. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaB_A133.py +0 -0
  56. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaB_A133Etw.py +0 -0
  57. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaD.py +0 -0
  58. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaI.py +0 -0
  59. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaINorway.py +0 -0
  60. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaISonder.py +0 -0
  61. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaK.py +0 -0
  62. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM3.py +0 -0
  63. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaM4.py +0 -0
  64. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaZ.py +0 -0
  65. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EnigmaZEtw.py +0 -0
  66. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Etw.py +0 -0
  67. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EtwPassthrough.py +0 -0
  68. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/EtwQWERTZ.py +0 -0
  69. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Journaled.py +0 -0
  70. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Observable.py +0 -0
  71. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Observer.py +0 -0
  72. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Plugboard.py +0 -0
  73. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/PlugboardPassthrough.py +0 -0
  74. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Reflector.py +0 -0
  75. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKWA.py +0 -0
  76. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKWB.py +0 -0
  77. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKWBThin.py +0 -0
  78. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKWC.py +0 -0
  79. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKWCThin.py +0 -0
  80. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKW_EnigmaB_A133.py +0 -0
  81. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKW_EnigmaCommercial.py +0 -0
  82. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKW_EnigmaINorway.py +0 -0
  83. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/ReflectorUKW_EnigmaISonder.py +0 -0
  84. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/RotatingReflector.py +0 -0
  85. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Scrambler.py +0 -0
  86. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/SettableReflector.py +0 -0
  87. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Swappable.py +0 -0
  88. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/SwappablePlugboard.py +0 -0
  89. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/Utils.py +0 -0
  90. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/XRay.py +0 -0
  91. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython/__init__.py +0 -0
  92. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython.egg-info/dependency_links.txt +0 -0
  93. {enigmapython-2.0.2 → enigmapython-3.0.1}/enigmapython.egg-info/top_level.txt +0 -0
  94. {enigmapython-2.0.2 → enigmapython-3.0.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: enigmapython
3
- Version: 2.0.2
3
+ Version: 3.0.1
4
4
  Summary: A simple yet faithful library to emulate different Enigma machines models using Python
5
5
  Home-page: https://github.com/denismaggior8/enigma-python
6
6
  Author: Denis Maggiorotto
@@ -67,6 +67,10 @@ This project is listed on [Wikipedia](https://en.wikipedia.org/wiki/List_of_Enig
67
67
  - **Flexible Configuration**: **enigmapython** allows customization of the Enigma machine configuration, enabling users to experiment with different rotor settings, reflectors, and ring positions.
68
68
  - **Easy Extension**: **enigmapython** is designed to be easily extensible, allowing developers to add new features or enhance the existing implementation.
69
69
  - **Simple yet faithful**: don't be fooled by its simplicity; **enigmapython** implements 100% the algorithms of many Enigma machine models, allowing to decode a message that has been encoded by a real Enigma machine and also the contrary.
70
+
71
+ ## Enigma mechanics
72
+
73
+ For a detailed description of the rotor movement and stepping logic, including pseudocode, please refer to the [Enigma Mechanics](./docs/mechanics.md) documentation.
70
74
 
71
75
  ## Historical Accuracy & Verification
72
76
 
@@ -82,7 +86,7 @@ The following Enigma machine models (along with their rotors, reflectors and plu
82
86
 
83
87
  ### Enigma B (Sweden, s/n: A-133)*
84
88
 
85
- | Scrambler | Wiring | Notch | Implemented |
89
+ | Scrambler | Wiring | Turnover | Implemented |
86
90
  |------- |---------------------------- |------- |------------- |
87
91
  | ETW (passthrough) | abcdefghijklmnopqrstuvxyzåäö | N/A | ✅ |
88
92
  | Rotor I | psbgöxqjdhoäucfrtezvåinlymka | ä | ✅ |
@@ -94,7 +98,7 @@ The following Enigma machine models (along with their rotors, reflectors and plu
94
98
 
95
99
  ### Enigma K (Commercial Enigma)
96
100
 
97
- | Scrambler | Wiring | Notch | Implemented |
101
+ | Scrambler | Wiring | Turnover | Implemented |
98
102
  |------- |---------------------------- |------- |------------- |
99
103
  | ETW "QWERTZ" | qwertzuioasdfghjkpyxcvbnml | N/A | ✅ |
100
104
  | Rotor I | lpgszmhaeoqkvxrfybutnicjdw | y | ✅ |
@@ -102,21 +106,21 @@ The following Enigma machine models (along with their rotors, reflectors and plu
102
106
  | Rotor III | cjgdpshkturawzxfmynqobvlie | n | ✅ |
103
107
  | Reflector UKW | imetcgfraysqbzxwlhkdvupojn | N/A | ✅ |
104
108
 
109
+ ### Enigma D (Commercial Enigma)
105
110
 
106
- ### Enigma D
107
-
108
- | Scrambler | Wiring | Notch | Implemented |
111
+ | Scrambler | Wiring | Turnover | Implemented |
109
112
  |------- |---------------------------- |------- |------------- |
110
113
  | ETW "QWERTZ" | qwertzuioasdfghjkpyxcvbnml | N/A | ✅ |
111
- | Rotor I | lpgszmhaeoqkvxrfybutnicjdw | y | ✅ |
112
- | Rotor II | slvgbtfxjqohewirzyamkpcndu | e | ✅ |
113
- | Rotor III | bdfhjlcprtxvznyeiwgakmusqo | n | ✅ |
114
+ | Rotor I | lpgszmhaeoqkvxrfybutnicjdw | z* | ✅ |
115
+ | Rotor II | slvgbtfxjqohewirzyamkpcndu | z* | ✅ |
116
+ | Rotor III | cjgdpshkturawzxfmynqobvlie | z* | ✅ |
114
117
  | Reflector UKW | imetcgfraysqbzxwlhkdvupojn | N/A | ✅ |
115
118
 
119
+ *Enigma D rotor turnover happens at Z when ringstellung is 0 (A), otherwise turnover position is calculated using the formula `turnover = (ringstellung + 1) % 26`.
116
120
 
117
121
  ### Enigma Z (Z30 Mark I)*
118
122
 
119
- | Scrambler | Wiring | Notch | Implemented |
123
+ | Scrambler | Wiring | Turnover | Implemented |
120
124
  |------- |----------------------------|-------|-------------|
121
125
  | ETW (passthrough) | 1234567890 | N/A | ✅ |
122
126
  | Rotor I | 6418270359 | 9 | ✅ |
@@ -128,7 +132,7 @@ The following Enigma machine models (along with their rotors, reflectors and plu
128
132
 
129
133
  ### Enigma I
130
134
 
131
- | Scrambler | Wiring | Notch | Implemented |
135
+ | Scrambler | Wiring | Turnover | Implemented |
132
136
  |------- |---------------------------- |------- |------------- |
133
137
  | Plugboard (passthrough+swappable) | N/A | N/A | ✅ |
134
138
  | ETW (passthrough) | abcdefghijklmnopqrstuvwxyz | N/A | ✅ |
@@ -141,7 +145,7 @@ The following Enigma machine models (along with their rotors, reflectors and plu
141
145
 
142
146
  ### Enigma I Norway (Norenigma)
143
147
 
144
- | Scrambler | Wiring | Notch | Implemented |
148
+ | Scrambler | Wiring | Turnover | Implemented |
145
149
  |------- |---------------------------- |------- |------------- |
146
150
  | Plugboard (passthrough+swappable) | N/A | N/A | ✅ |
147
151
  | ETW (passthrough) | abcdefghijklmnopqrstuvwxyz | N/A | ✅ |
@@ -154,7 +158,7 @@ The following Enigma machine models (along with their rotors, reflectors and plu
154
158
 
155
159
  ### Enigma I Sondermaschine (special machine)
156
160
 
157
- | Scrambler | Wiring | Notch | Implemented |
161
+ | Scrambler | Wiring | Turnover | Implemented |
158
162
  |------- |---------------------------- |------- |------------- |
159
163
  | Plugboard (passthrough+swappable) | N/A | N/A | ✅ |
160
164
  | ETW (passthrough) | abcdefghijklmnopqrstuvwxyz | N/A | ✅ |
@@ -166,7 +170,7 @@ The following Enigma machine models (along with their rotors, reflectors and plu
166
170
 
167
171
  ### Enigma M3
168
172
 
169
- | Scrambler | Wiring | Notch | Implemented |
173
+ | Scrambler | Wiring | Turnover | Implemented |
170
174
  |------- |---------------------------- |------- |------------- |
171
175
  | Plugboard (passthrough+swappable) | N/A | N/A | ✅ |
172
176
  | ETW (passthrough) | abcdefghijklmnopqrstuvwxyz | N/A | ✅ |
@@ -183,7 +187,7 @@ The following Enigma machine models (along with their rotors, reflectors and plu
183
187
 
184
188
  ### Enigma M4
185
189
 
186
- | Scrambler | Wiring | Notch | Implemented |
190
+ | Scrambler | Wiring | Turnover | Implemented |
187
191
  |------- |---------------------------- |------- |------------- |
188
192
  | Plugboard (passthrough+swappable) | N/A | N/A | ✅ |
189
193
  | ETW (passthrough) | abcdefghijklmnopqrstuvwxyz | N/A | ✅ |
@@ -200,6 +204,53 @@ The following Enigma machine models (along with their rotors, reflectors and plu
200
204
  | Reflector B Thin | enkqauywjicopblmdxzvfthrgs | N/A | ✅ |
201
205
  | Reflector C Thin | rdobjntkvehmlfcwzaxgyipsuq | N/A | ✅ |
202
206
 
207
+ ### Custom Machine
208
+
209
+ | Scrambler | Wiring | Turnover | Implemented |
210
+ |------- |---------------------------- |------- |------------- |
211
+ | Plugboard (passthrough+swappable) | N/A | N/A | ✅ |
212
+ | ETW (Entry Wheel) | Custom | N/A | ✅ |
213
+ | Rotor | Custom | Custom | ✅ |
214
+ | Reflector | Custom | N/A | ✅ |
215
+
216
+
217
+ You can create a fully customized Enigma machine by instantiating the base components manually. This allows you to define custom alphabets, wirings, and turnover positions.
218
+
219
+ ```python
220
+ from enigmapython.Enigma import Enigma
221
+ from enigmapython.Rotor import Rotor
222
+ from enigmapython.Reflector import Reflector
223
+ from enigmapython.SwappablePlugboard import SwappablePlugboard
224
+ from enigmapython.Etw import Etw
225
+ from enigmapython.Alphabets import Alphabets
226
+
227
+ # 1. Define alphabet
228
+ alphabet = Alphabets.lookup.get("latin_i18n_26chars_lowercase")
229
+
230
+ # 2. Create custom rotors
231
+ # Parameters: wiring, turnover_indexes, alphabet, initial_position, ring_setting
232
+ rotor1 = Rotor("ekmflgdqvzntowyhxuspaibrcj", [16], alphabet, 0, 0) # Turnover at 'q'
233
+ rotor2 = Rotor("ajdksiruxblhwtmcqgznpyfvoe", [4], alphabet, 0, 0) # Turnover at 'e'
234
+ rotor3 = Rotor("bdfhjlcprtxvznyeiwgakmusqo", [21], alphabet, 0, 0) # Turnover at 'v'
235
+
236
+ # 3. Create custom reflector
237
+ reflector = Reflector("yruhqsldpxngokmiebfzcwvjat", alphabet)
238
+
239
+ # 4. Create other components
240
+ # Swappable plugboard allows you to connect pairs of letters
241
+ plugboard = SwappablePlugboard(alphabet=alphabet)
242
+ plugboard.swap("a", "z") # Example: swap 'a' with 'z'
243
+
244
+ etw = Etw(alphabet, alphabet) # Passthrough ETW using alphabet as wiring
245
+
246
+ # 5. Assemble the Enigma machine
247
+ engine = Enigma(plugboard, [rotor1, rotor2, rotor3], reflector, etw, auto_increment_rotors=True, alphabet=alphabet)
248
+
249
+ # 6. Encrypt/Decrypt
250
+ cipher = engine.input_string("hello")
251
+ print(f"Ciphertext: {cipher}") # Outputs: mfnca
252
+ ```
253
+
203
254
  ## Prerequisites
204
255
 
205
256
  - Python 3.11
@@ -0,0 +1,39 @@
1
+ from .Rotor import Rotor
2
+
3
+ class DynamicTurnoverRotor(Rotor):
4
+ """
5
+ Rotor that updates its notch position based on the ring setting using the formula:
6
+ effective_notch = (notch + ringstellung) mod 26
7
+ """
8
+ original_turnover_indexes = None
9
+
10
+ def __init__(self, wiring, turnover_indexes, alphabet, position=0, ring=0, turnover_function=None):
11
+ # We must save the original notch indexes before calling super().__init__
12
+ # because super().__init__ calls set_ring (via Settable), which we override.
13
+ self.original_turnover_indexes = turnover_indexes
14
+
15
+ if turnover_function is None:
16
+ self.turnover_function = lambda notch, ring, length: (notch + ring) % length
17
+ else:
18
+ self.turnover_function = turnover_function
19
+
20
+ super().__init__(wiring, turnover_indexes, alphabet, position, ring)
21
+ # Rotor.__init__ sets self.turnover_indexes = turnover_indexes at the end,
22
+ # overwriting any changes made by our set_ring during init.
23
+ # So we must call set_ring again to ensure notches are calculated correctly.
24
+ self.set_ring(ring)
25
+
26
+ def reset_ring(self):
27
+ self.set_ring(0)
28
+
29
+ def set_ring(self, ring):
30
+ # First perform standard ring setting (wiring rotation)
31
+ super().set_ring(ring)
32
+
33
+ # Now adjust notch positions using the turnover function
34
+ if self.original_turnover_indexes is not None:
35
+ length = len(self.wiring)
36
+ self.turnover_indexes = []
37
+ for notch in self.original_turnover_indexes:
38
+ new_notch = self.turnover_function(notch, ring, length)
39
+ self.turnover_indexes.append(new_notch)
@@ -107,7 +107,6 @@ class Enigma(Observer,Journaled,Clonable):
107
107
  iteration -=1
108
108
  logging.debug("Scrambled letter from rotor{}: {}".format(str(iteration+1),scrambled_char))
109
109
 
110
- # Processing rotor 1 returning signal by ETW
111
110
  # Processing rotor 1 returning signal by ETW
112
111
  scrambled_char = self.etw.scramble_char(self.alphabet_list,(inverted_wiring.index(self.shift_letter(scrambled_char, (0 - self.rotors[iteration].position),self.alphabet_list))), 0)
113
112
  logging.debug("Scrambled letter from ETW: {}".format(scrambled_char))
@@ -123,14 +122,14 @@ class Enigma(Observer,Journaled,Clonable):
123
122
  self.rotors[self.rotors.index(observable)+1].increment_position()
124
123
  logging.debug("Rotor at index {} has been incremented by 1 position".format(self.rotors.index(observable)+1))
125
124
  # Engaging the enigma double step issue, only if the next rotor position is in its notch indexe/s
126
- if self.rotors[self.rotors.index(observable)+1].position in self.rotors[self.rotors.index(observable)+1].notch_indexes:
125
+ if self.rotors[self.rotors.index(observable)+1].position in self.rotors[self.rotors.index(observable)+1].turnover_indexes:
127
126
  self.rotors[self.rotors.index(observable)+1].double_step_triggered = True
128
127
  # If the rotor is the last one in the list, but the machine has a rotating reflector, increment its position by 1
129
128
  if observable in self.rotors and self.rotors.index(observable) == len(self.rotors)-1 and isinstance(self.reflector, RotatingReflector):
130
129
  self.reflector.increment_position()
131
130
  logging.debug("Reflector has been incremented by 1 position")
132
131
  # Engaging the enigma double step issue, only if the next rotor position is in its notch indexe/s
133
- if self.reflector.position in self.reflector.notch_indexes:
132
+ if self.reflector.position in self.reflector.turnover_indexes:
134
133
  self.reflector.double_step_triggered = True
135
134
 
136
135
  @staticmethod
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaB_A133RotorI(Rotor):
5
5
 
6
6
  wiring = 'psbgöxqjdhoäucfrtezvåinlymka'
7
- notch_indexes = [11]
7
+ turnover_indexes = [11]
8
8
  tag = "B_A133_I"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaB_A133RotorI(Rotor):
12
12
  wiring=self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get("enigma_b_a133_28chars_lowercase")
17
17
  )
18
18
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaB_A133RotorII(Rotor):
5
5
 
6
6
  wiring = 'chnsyöadmotrzxbäigåekqupflvj'
7
- notch_indexes = [15]
7
+ turnover_indexes = [15]
8
8
  tag = "B_A133_II"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaB_A133RotorII(Rotor):
12
12
  wiring=self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get("enigma_b_a133_28chars_lowercase")
17
17
  )
18
18
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaB_A133RotorIII(Rotor):
5
5
 
6
6
  wiring = 'åvqiaäxrjbözspcfyunthdomekgl'
7
- notch_indexes = [5]
7
+ turnover_indexes = [5]
8
8
  tag = "B_A133_III"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaB_A133RotorIII(Rotor):
12
12
  wiring=self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get("enigma_b_a133_28chars_lowercase")
17
17
  )
18
18
 
@@ -1,10 +1,11 @@
1
+ from .DynamicTurnoverRotor import DynamicTurnoverRotor
1
2
  from .Rotor import Rotor
2
3
  from .Alphabets import Alphabets
3
4
 
4
- class EnigmaDRotorI(Rotor):
5
+ class EnigmaDRotorI(DynamicTurnoverRotor):
5
6
 
6
7
  wiring = 'lpgszmhaeoqkvxrfybutnicjdw'
7
- notch_indexes = [24]
8
+ turnover_indexes = [25]
8
9
  tag = "D_I"
9
10
 
10
11
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +13,8 @@ class EnigmaDRotorI(Rotor):
12
13
  wiring=self.wiring,
13
14
  position=position,
14
15
  ring=ring,
15
- notch_indexes=self.notch_indexes,
16
- alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
16
+ turnover_indexes=self.turnover_indexes,
17
+ alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase'),
18
+ turnover_function=lambda n, r, l: (n + r) % l
17
19
  )
18
20
 
@@ -1,10 +1,10 @@
1
- from .Rotor import Rotor
1
+ from .DynamicTurnoverRotor import DynamicTurnoverRotor
2
2
  from .Alphabets import Alphabets
3
3
 
4
- class EnigmaDRotorII(Rotor):
4
+ class EnigmaDRotorII(DynamicTurnoverRotor):
5
5
 
6
6
  wiring = 'slvgbtfxjqohewirzyamkpcndu'
7
- notch_indexes = [4]
7
+ turnover_indexes = [25]
8
8
  tag = "D_II"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,8 @@ class EnigmaDRotorII(Rotor):
12
12
  wiring=self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
16
- alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
15
+ turnover_indexes=self.turnover_indexes,
16
+ alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase'),
17
+ turnover_function=lambda n, r, l: (n + r) % l
17
18
  )
18
19
 
@@ -1,10 +1,10 @@
1
- from .Rotor import Rotor
1
+ from .DynamicTurnoverRotor import DynamicTurnoverRotor
2
2
  from .Alphabets import Alphabets
3
3
 
4
- class EnigmaDRotorIII(Rotor):
4
+ class EnigmaDRotorIII(DynamicTurnoverRotor):
5
5
 
6
6
  wiring = 'cjgdpshkturawzxfmynqobvlie'
7
- notch_indexes = [13]
7
+ turnover_indexes = [25]
8
8
  tag = "D_III"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,8 @@ class EnigmaDRotorIII(Rotor):
12
12
  wiring=self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
16
- alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
15
+ turnover_indexes=self.turnover_indexes,
16
+ alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase'),
17
+ turnover_function=lambda n, r, l: (n + r) % l
17
18
  )
18
19
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaINorwayRotorI(Rotor):
5
5
 
6
6
  wiring = 'wtokasuyvrbxjhqcpzefmdinlg'
7
- notch_indexes = [16]
7
+ turnover_indexes = [16]
8
8
  tag = "IN_I"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaINorwayRotorI(Rotor):
12
12
  wiring=self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
17
17
  )
18
18
 
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaINorwayRotorII(Rotor):
6
6
 
7
7
  wiring = 'gjlpubswemctqvhxaofzdrkyni'
8
- notch_indexes = [4]
8
+ turnover_indexes = [4]
9
9
  tag = "IN_II"
10
10
 
11
11
  def __init__(self, position = 0, ring = 0):
@@ -13,6 +13,6 @@ class EnigmaINorwayRotorII(Rotor):
13
13
  wiring=self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
18
18
  )
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaINorwayRotorIII(Rotor):
6
6
 
7
7
  wiring = 'jwfmhnbpusdytixvzgrqlaoekc'
8
- notch_indexes = [21]
8
+ turnover_indexes = [21]
9
9
  tag = "IN_III"
10
10
 
11
11
  def __init__(self, position = 0, ring = 0):
@@ -13,7 +13,7 @@ class EnigmaINorwayRotorIII(Rotor):
13
13
  wiring=self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
18
18
  )
19
19
 
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaINorwayRotorIV(Rotor):
6
6
 
7
7
  wiring = 'fgzjmvxepbwshqtliudykcnrao'
8
- notch_indexes = [21]
8
+ turnover_indexes = [21]
9
9
  tag = "IN_IV"
10
10
 
11
11
  def __init__(self, position = 0, ring = 0):
@@ -13,7 +13,7 @@ class EnigmaINorwayRotorIV(Rotor):
13
13
  wiring=self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
18
18
  )
19
19
 
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaINorwayRotorV(Rotor):
6
6
 
7
7
  wiring = 'hejxqotzbvfdascilwpgynmurk'
8
- notch_indexes = [25]
8
+ turnover_indexes = [25]
9
9
  tag = "IN_V"
10
10
 
11
11
  def __init__(self, position = 0, ring = 0):
@@ -13,7 +13,7 @@ class EnigmaINorwayRotorV(Rotor):
13
13
  wiring=self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
18
18
  )
19
19
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaIRotorI(Rotor):
5
5
 
6
6
  wiring = 'ekmflgdqvzntowyhxuspaibrcj'
7
- notch_indexes = [16]
7
+ turnover_indexes = [16]
8
8
  tag = "I_I"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaIRotorI(Rotor):
12
12
  wiring = self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
17
17
  )
18
18
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaIRotorII(Rotor):
5
5
 
6
6
  wiring = 'ajdksiruxblhwtmcqgznpyfvoe'
7
- notch_indexes = [4]
7
+ turnover_indexes = [4]
8
8
 
9
9
  tag = "I_II"
10
10
 
@@ -13,7 +13,7 @@ class EnigmaIRotorII(Rotor):
13
13
  wiring = self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
18
18
  )
19
19
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaIRotorIII(Rotor):
5
5
 
6
6
  wiring = 'bdfhjlcprtxvznyeiwgakmusqo'
7
- notch_indexes = [21]
7
+ turnover_indexes = [21]
8
8
 
9
9
  tag = "I_III"
10
10
 
@@ -13,7 +13,7 @@ class EnigmaIRotorIII(Rotor):
13
13
  wiring = self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
18
18
  )
19
19
 
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaIRotorIV(Rotor):
6
6
 
7
7
  wiring = 'esovpzjayquirhxlnftgkdcmwb'
8
- notch_indexes = [9]
8
+ turnover_indexes = [9]
9
9
 
10
10
  tag = "I_IV"
11
11
 
@@ -14,7 +14,7 @@ class EnigmaIRotorIV(Rotor):
14
14
  wiring = self.wiring,
15
15
  position=position,
16
16
  ring=ring,
17
- notch_indexes=self.notch_indexes,
17
+ turnover_indexes=self.turnover_indexes,
18
18
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
19
19
  )
20
20
 
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaIRotorV(Rotor):
6
6
 
7
7
  wiring = 'vzbrgityupsdnhlxawmjqofeck'
8
- notch_indexes = [25]
8
+ turnover_indexes = [25]
9
9
  tag = "I_V"
10
10
 
11
11
  def __init__(self, position = 0, ring = 0):
@@ -13,7 +13,7 @@ class EnigmaIRotorV(Rotor):
13
13
  wiring = self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
18
18
  )
19
19
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaISonderRotorI(Rotor):
5
5
 
6
6
  wiring = 'veosirzujdqckgwypnxaflthmb'
7
- notch_indexes = [16]
7
+ turnover_indexes = [16]
8
8
  tag = "IS_I"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaISonderRotorI(Rotor):
12
12
  wiring = self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
17
17
  )
18
18
 
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaISonderRotorII(Rotor):
6
6
 
7
7
  wiring = 'uemoatqlshpkcyfwjzbgvxidnr'
8
- notch_indexes = [4]
8
+ turnover_indexes = [4]
9
9
  tag = "IS_II"
10
10
 
11
11
  def __init__(self, position = 0, ring = 0):
@@ -13,6 +13,6 @@ class EnigmaISonderRotorII(Rotor):
13
13
  wiring = self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
18
18
  )
@@ -5,7 +5,7 @@ from .Alphabets import Alphabets
5
5
  class EnigmaISonderRotorIII(Rotor):
6
6
 
7
7
  wiring = 'tzhxmbsipnurjfdkeqvcwglaoy'
8
- notch_indexes = [21]
8
+ turnover_indexes = [21]
9
9
  tag = "IS_III"
10
10
 
11
11
  def __init__(self, position = 0, ring = 0):
@@ -13,7 +13,7 @@ class EnigmaISonderRotorIII(Rotor):
13
13
  wiring = self.wiring,
14
14
  position=position,
15
15
  ring=ring,
16
- notch_indexes=self.notch_indexes,
16
+ turnover_indexes=self.turnover_indexes,
17
17
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
18
18
  )
19
19
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaKRotorI(Rotor):
5
5
 
6
6
  wiring = 'lpgszmhaeoqkvxrfybutnicjdw'
7
- notch_indexes = [24] # Y (notch position)
7
+ turnover_indexes = [24] # Y (notch position)
8
8
  tag = "K_I"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaKRotorI(Rotor):
12
12
  wiring = self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
17
17
  )
18
18
 
@@ -4,7 +4,7 @@ from .Alphabets import Alphabets
4
4
  class EnigmaKRotorII(Rotor):
5
5
 
6
6
  wiring = 'slvgbtfxjqohewirzyamkpcndu'
7
- notch_indexes = [4] # E (notch position)
7
+ turnover_indexes = [4] # E (notch position)
8
8
  tag = "K_II"
9
9
 
10
10
  def __init__(self, position = 0, ring = 0):
@@ -12,7 +12,7 @@ class EnigmaKRotorII(Rotor):
12
12
  wiring = self.wiring,
13
13
  position=position,
14
14
  ring=ring,
15
- notch_indexes=self.notch_indexes,
15
+ turnover_indexes=self.turnover_indexes,
16
16
  alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
17
17
  )
18
18