enigmapython 1.1.0__tar.gz → 1.2.0__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.
- {enigmapython-1.1.0 → enigmapython-1.2.0}/PKG-INFO +41 -9
- enigmapython-1.2.0/enigmapython/Alphabets.py +6 -0
- enigmapython-1.2.0/enigmapython/Clonable.py +9 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/Enigma.py +38 -16
- enigmapython-1.2.0/enigmapython/EnigmaB_A133.py +12 -0
- enigmapython-1.2.0/enigmapython/EnigmaB_A133Etw.py +7 -0
- enigmapython-1.2.0/enigmapython/EnigmaB_A133RotorI.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaB_A133RotorII.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaB_A133RotorIII.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaDRotorI.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaDRotorII.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaDRotorIII.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaINorwayRotorI.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaINorwayRotorII.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaINorwayRotorIII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaINorwayRotorIV.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaINorwayRotorV.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaIRotorI.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaIRotorII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaIRotorIII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaIRotorIV.py +20 -0
- enigmapython-1.2.0/enigmapython/EnigmaIRotorV.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaISonderRotorI.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaISonderRotorII.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaISonderRotorIII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorI.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorIII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorIV.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorV.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorVI.py +20 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorVII.py +20 -0
- enigmapython-1.2.0/enigmapython/EnigmaM3RotorVIII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorBeta.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorGamma.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorI.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorIII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorIV.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorV.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorVI.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorVII.py +19 -0
- enigmapython-1.2.0/enigmapython/EnigmaM4RotorVIII.py +20 -0
- enigmapython-1.2.0/enigmapython/EnigmaZ.py +12 -0
- enigmapython-1.2.0/enigmapython/EnigmaZEtw.py +7 -0
- enigmapython-1.2.0/enigmapython/EnigmaZRotorI.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaZRotorII.py +18 -0
- enigmapython-1.2.0/enigmapython/EnigmaZRotorIII.py +18 -0
- enigmapython-1.2.0/enigmapython/Etw.py +19 -0
- enigmapython-1.2.0/enigmapython/Journaled.py +12 -0
- enigmapython-1.2.0/enigmapython/Plugboard.py +20 -0
- enigmapython-1.2.0/enigmapython/PlugboardPassthrough.py +8 -0
- enigmapython-1.2.0/enigmapython/Reflector.py +4 -0
- enigmapython-1.2.0/enigmapython/ReflectorDUKW.py +13 -0
- enigmapython-1.2.0/enigmapython/ReflectorNorwayUKW.py +14 -0
- enigmapython-1.2.0/enigmapython/ReflectorSonderUKW.py +13 -0
- enigmapython-1.2.0/enigmapython/ReflectorUKWA.py +13 -0
- enigmapython-1.2.0/enigmapython/ReflectorUKWB.py +13 -0
- enigmapython-1.2.0/enigmapython/ReflectorUKWBThin.py +13 -0
- enigmapython-1.2.0/enigmapython/ReflectorUKWC.py +15 -0
- enigmapython-1.2.0/enigmapython/ReflectorUKWCThin.py +15 -0
- enigmapython-1.2.0/enigmapython/ReflectorUKW_EnigmaB_A133.py +15 -0
- enigmapython-1.2.0/enigmapython/ReflectorZUKW.py +19 -0
- enigmapython-1.2.0/enigmapython/RotatingReflector.py +4 -0
- enigmapython-1.2.0/enigmapython/Rotor.py +50 -0
- enigmapython-1.2.0/enigmapython/Scrambler.py +63 -0
- enigmapython-1.1.0/enigmapython/SwappablePlugboard.py → enigmapython-1.2.0/enigmapython/Swappable.py +3 -10
- enigmapython-1.2.0/enigmapython/SwappablePlugboard.py +12 -0
- enigmapython-1.2.0/enigmapython/Utils.py +118 -0
- enigmapython-1.2.0/enigmapython/__init__.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython.egg-info/PKG-INFO +41 -9
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython.egg-info/SOURCES.txt +18 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/setup.py +1 -1
- enigmapython-1.1.0/enigmapython/EnigmaDRotorI.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaDRotorII.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaDRotorIII.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaINorwayRotorI.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaINorwayRotorII.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaINorwayRotorIII.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaINorwayRotorIV.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaINorwayRotorV.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaIRotorI.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaIRotorII.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaIRotorIII.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaIRotorIV.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaIRotorV.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaISonderRotorI.py +0 -11
- enigmapython-1.1.0/enigmapython/EnigmaISonderRotorII.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaISonderRotorIII.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorI.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorII.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorIII.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorIV.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorV.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorVI.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorVII.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaM3RotorVIII.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorBeta.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorGamma.py +0 -12
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorI.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorII.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorIII.py +0 -10
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorIV.py +0 -9
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorV.py +0 -9
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorVI.py +0 -9
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorVII.py +0 -9
- enigmapython-1.1.0/enigmapython/EnigmaM4RotorVIII.py +0 -10
- enigmapython-1.1.0/enigmapython/Etw.py +0 -22
- enigmapython-1.1.0/enigmapython/Plugboard.py +0 -15
- enigmapython-1.1.0/enigmapython/PlugboardPassthrough.py +0 -7
- enigmapython-1.1.0/enigmapython/Reflector.py +0 -4
- enigmapython-1.1.0/enigmapython/ReflectorDUKW.py +0 -9
- enigmapython-1.1.0/enigmapython/ReflectorNorwayUKW.py +0 -9
- enigmapython-1.1.0/enigmapython/ReflectorSonderUKW.py +0 -9
- enigmapython-1.1.0/enigmapython/ReflectorUKWA.py +0 -9
- enigmapython-1.1.0/enigmapython/ReflectorUKWB.py +0 -9
- enigmapython-1.1.0/enigmapython/ReflectorUKWBThin.py +0 -9
- enigmapython-1.1.0/enigmapython/ReflectorUKWC.py +0 -10
- enigmapython-1.1.0/enigmapython/ReflectorUKWCThin.py +0 -10
- enigmapython-1.1.0/enigmapython/Rotor.py +0 -94
- enigmapython-1.1.0/enigmapython/Utils.py +0 -31
- enigmapython-1.1.0/enigmapython/__init__.py +0 -58
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaD.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaDEtw_JWULCM.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaDEtw_QWERTZ.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaI.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaINorway.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaISonder.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaM3.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EnigmaM4.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/EtwPassthrough.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/Observable.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython/Observer.py +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython.egg-info/dependency_links.txt +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/enigmapython.egg-info/top_level.txt +0 -0
- {enigmapython-1.1.0 → enigmapython-1.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: enigmapython
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
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
|
|
@@ -8,7 +8,9 @@ Description-Content-Type: text/markdown
|
|
|
8
8
|
|
|
9
9
|
# Enigma Python library
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
<div class="img-container" style="text-align: center;">
|
|
12
|
+
<img src="img/logo.jpg" alt="drawing" width="200" />
|
|
13
|
+
</div>
|
|
12
14
|
|
|
13
15
|
## About
|
|
14
16
|
|
|
@@ -24,6 +26,18 @@ Welcome to **enigmapython**, a Python package designed to emulate the legendary
|
|
|
24
26
|
|
|
25
27
|
The following Enigma machine models (along with their rotors, reflectors and plugboards) have been implemented:
|
|
26
28
|
|
|
29
|
+
### Enigma B (Sweden, s/n: A-133)*
|
|
30
|
+
|
|
31
|
+
| Scrambler | Wiring | Notch | Implemented |
|
|
32
|
+
|------- |---------------------------- |------- |------------- |
|
|
33
|
+
| ETW (passthrough) | abcdefghijklmnopqrstuvxyzåäö | N/A | ✅ |
|
|
34
|
+
| Rotor I | psbgöxqjdhoäucfrtezvåinlymka | ä | ✅ |
|
|
35
|
+
| Rotor II | chnsyöadmotrzxbäigåekqupflvj | ä | ✅ |
|
|
36
|
+
| Rotor III | åvqiaäxrjbözspcfyunthdomekgl | ä | ✅ |
|
|
37
|
+
| Reflector UKW | ldgbäncpskjavfzhxuiårmqöotey | N/A | ✅ |
|
|
38
|
+
|
|
39
|
+
*given the rarity of this model and the little documentation/simulators available, although I expect an encryption consistency on par with newer models, I was unable to test it as I would have liked
|
|
40
|
+
|
|
27
41
|
### Enigma D
|
|
28
42
|
|
|
29
43
|
| Scrambler | Wiring | Notch | Implemented |
|
|
@@ -35,6 +49,19 @@ The following Enigma machine models (along with their rotors, reflectors and plu
|
|
|
35
49
|
| Rotor III | bdfhjlcprtxvznyeiwgakmusqo | n | ✅ |
|
|
36
50
|
| Reflector UKW | imetcgfraysqbzxwlhkdvupojn | N/A | ✅ |
|
|
37
51
|
|
|
52
|
+
|
|
53
|
+
### Enigma Z (Z30 Mark I)*
|
|
54
|
+
|
|
55
|
+
| Scrambler | Wiring | Notch | Implemented |
|
|
56
|
+
|------- |----------------------------|-------|-------------|
|
|
57
|
+
| ETW (passthrough) | 1234567890 | N/A | ✅ |
|
|
58
|
+
| Rotor I | 6418270359 | 9 | ✅ |
|
|
59
|
+
| Rotor II | 5841097632 | 9 | ✅ |
|
|
60
|
+
| Rotor III | 3581620794 | 9 | ✅ |
|
|
61
|
+
| Reflector UKW | 5079183642 | N/A | ✅ |
|
|
62
|
+
|
|
63
|
+
*given the rarity of this model and the little documentation/simulators available, although I expect an encryption consistency on par with newer models, I was unable to test it as I would have liked
|
|
64
|
+
|
|
38
65
|
### Enigma I
|
|
39
66
|
|
|
40
67
|
| Scrambler | Wiring | Notch | Implemented |
|
|
@@ -126,16 +153,18 @@ An initial documentation draft can be found [here](./docs/README.md), but in mos
|
|
|
126
153
|
|
|
127
154
|
Here's a list containing all the known Enigma simulators that use the **enigmapython** API.
|
|
128
155
|
|
|
129
|
-
- [
|
|
156
|
+
- [Enigma TUI](https://github.com/denismaggior8/enigma-tui). **Enigma TUI** is a **T**erminal **U**ser **I**nterface for Enigma machines, allowing you to simulate different Enigma machine models from the terminal. It employs **enigmapython** as Enigma engine.
|
|
130
157
|
|
|
131
|
-
|
|
158
|
+
<div class="img-container" style="text-align: center;">
|
|
159
|
+
<img src="img/enigmatui.png" alt="drawing" width="400" align="center"/>
|
|
160
|
+
</div>
|
|
132
161
|
|
|
133
162
|
|
|
134
|
-
|
|
163
|
+
- [Retrocampus BBS Enigma simulator](https://retrocampus.com/bbs/). When connected to the BBS, type E to access an Enigma M3 cypher machine whose backend is based on **enigmapython**.
|
|
135
164
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
165
|
+
<div class="img-container" style="text-align: center;">
|
|
166
|
+
<img src="img/retrocampus_enigma.png" alt="drawing" width="400" align="center"/>
|
|
167
|
+
</div>
|
|
139
168
|
|
|
140
169
|
In the case you leveraged **enigmapython** API in a project, either public or not, drop me an email at __denis.maggiorotto[at]gmail.com__ and I'll be happy to list you here.
|
|
141
170
|
|
|
@@ -150,7 +179,10 @@ In the case you leveraged **enigmapython** API in a project, either public or no
|
|
|
150
179
|
- PyEnigma https://pypi.org/project/pyenigma/
|
|
151
180
|
- 101 computing https://www.101computing.net/enigma-machine-emulator/
|
|
152
181
|
- DenCode Enigma simulator https://dencode.com/cipher/enigma
|
|
153
|
-
|
|
182
|
+
- Enigma simulation in Javascript/HTML by Daniel Palloks https://people.physik.hu-berlin.de/~palloks/js/enigma/index_en.html
|
|
183
|
+
- Enigma B A133 simulation in Javascript/HTML by Daniel Palloks https://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-a133_v261_en.html
|
|
184
|
+
- Enigma Z simulation in Javascript/HTML by Daniel Palloks https://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-z_v262b_en.html
|
|
185
|
+
|
|
154
186
|
for having helped me testing the correctness of the generated ciphertexts
|
|
155
187
|
|
|
156
188
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
from .Observer import Observer
|
|
2
|
-
from
|
|
2
|
+
from .RotatingReflector import RotatingReflector
|
|
3
|
+
from .Alphabets import Alphabets
|
|
4
|
+
from .Journaled import Journaled
|
|
5
|
+
from .Clonable import Clonable
|
|
3
6
|
import logging
|
|
4
7
|
|
|
5
8
|
|
|
6
|
-
class Enigma(Observer):
|
|
9
|
+
class Enigma(Observer,Journaled,Clonable):
|
|
7
10
|
|
|
8
11
|
plugboard = None
|
|
9
12
|
rotors = None
|
|
@@ -13,7 +16,9 @@ class Enigma(Observer):
|
|
|
13
16
|
|
|
14
17
|
alphabet_list = None
|
|
15
18
|
|
|
16
|
-
def __init__(self, plugboard, rotors, reflector,etw,auto_increment_rotors=False, alphabet=
|
|
19
|
+
def __init__(self, plugboard, rotors, reflector,etw,auto_increment_rotors=False, alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")):
|
|
20
|
+
Journaled.__init__(self)
|
|
21
|
+
Clonable.__init__(self)
|
|
17
22
|
self.plugboard = plugboard
|
|
18
23
|
self.rotors = rotors
|
|
19
24
|
self.reflector = reflector
|
|
@@ -34,13 +39,20 @@ class Enigma(Observer):
|
|
|
34
39
|
logging.info("Input char: {}".format(char))
|
|
35
40
|
## Triggering rotors extra rotation due to double step issue
|
|
36
41
|
for rotor in self.rotors:
|
|
37
|
-
## Rotor extra rotation should be done only if
|
|
42
|
+
## Rotor extra rotation should be done only if it's not the last one in the list
|
|
38
43
|
if rotor.double_step_triggered == True and self.rotors.index(rotor) < len(self.rotors)-1:
|
|
39
44
|
rotor.increment_position()
|
|
40
45
|
rotor.double_step_triggered = False
|
|
46
|
+
if isinstance(self.reflector, RotatingReflector) and self.reflector.double_step_triggered == True:
|
|
47
|
+
self.reflector.increment_position()
|
|
48
|
+
self.reflector.double_step_triggered = False
|
|
41
49
|
if self.auto_increment_rotors == True:
|
|
42
50
|
self.rotors[0].increment_position()
|
|
43
51
|
scrambled_char = self.process_char(char)
|
|
52
|
+
super().append_to_journal({
|
|
53
|
+
'input_char': char,
|
|
54
|
+
'output_char': scrambled_char
|
|
55
|
+
})
|
|
44
56
|
return scrambled_char
|
|
45
57
|
|
|
46
58
|
"""
|
|
@@ -56,33 +68,33 @@ class Enigma(Observer):
|
|
|
56
68
|
--- --- --- --- --- ---
|
|
57
69
|
"""
|
|
58
70
|
def process_char(self, char):
|
|
59
|
-
scrambled_char = self.plugboard.
|
|
71
|
+
scrambled_char = self.plugboard.scramble_char(self.plugboard.wiring,self.plugboard.alphabet_list.index(char),0)
|
|
60
72
|
logging.debug("Scrambled letter from plugboard: {}".format(scrambled_char))
|
|
61
|
-
scrambled_char = self.etw.
|
|
73
|
+
scrambled_char = self.etw.scramble_char(self.etw.wiring,self.alphabet_list.index(scrambled_char), 0)
|
|
62
74
|
logging.debug("Scrambled letter from ETW: {}".format(scrambled_char))
|
|
63
75
|
iteration = 0
|
|
64
76
|
for rotor in self.rotors:
|
|
65
77
|
if iteration == 0:
|
|
66
|
-
scrambled_char = rotor.
|
|
78
|
+
scrambled_char = rotor.scramble_char(rotor.wiring,self.alphabet_list.index(scrambled_char), rotor.position)
|
|
67
79
|
else:
|
|
68
|
-
scrambled_char = rotor.
|
|
80
|
+
scrambled_char = rotor.scramble_char(rotor.wiring,self.alphabet_list.index(scrambled_char)-self.rotors[iteration-1].position, rotor.position)
|
|
69
81
|
iteration +=1
|
|
70
82
|
logging.debug("Scrambled letter from rotor{}: {}".format(str(iteration),scrambled_char))
|
|
71
|
-
scrambled_char = self.reflector.
|
|
83
|
+
scrambled_char = self.reflector.scramble_char(self.reflector.wiring,(self.alphabet_list.index(scrambled_char)-self.rotors[iteration-1].position), 0)
|
|
72
84
|
logging.debug("Scrambled letter from reflector: {}".format(scrambled_char))
|
|
73
85
|
for rotor in reversed(self.rotors):
|
|
74
86
|
if iteration == len(self.rotors):
|
|
75
|
-
scrambled_char = rotor.
|
|
87
|
+
scrambled_char = rotor.scramble_char(self.alphabet_list,(rotor.wiring.index(self.shift_letter(scrambled_char,rotor.position,self.alphabet_list))-rotor.position), rotor.position)
|
|
76
88
|
else:
|
|
77
|
-
scrambled_char = rotor.
|
|
89
|
+
scrambled_char = rotor.scramble_char(self.alphabet_list,(rotor.wiring.index(self.shift_letter(scrambled_char, (rotor.position - self.rotors[iteration].position),self.alphabet_list)) - rotor.position), rotor.position)
|
|
78
90
|
iteration -=1
|
|
79
91
|
logging.debug("Scrambled letter from rotor{}: {}".format(str(iteration+1),scrambled_char))
|
|
80
92
|
|
|
81
93
|
# Processing rotor 1 returning signal by ETW
|
|
82
|
-
scrambled_char = self.etw.
|
|
94
|
+
scrambled_char = self.etw.scramble_char(self.alphabet_list,(self.etw.wiring.index(self.shift_letter(scrambled_char, (0 - self.rotors[iteration].position),self.alphabet_list))), 0)
|
|
83
95
|
logging.debug("Scrambled letter from ETW: {}".format(scrambled_char))
|
|
84
96
|
|
|
85
|
-
scrambled_char = self.plugboard.
|
|
97
|
+
scrambled_char = self.plugboard.scramble_char(self.plugboard.wiring,self.plugboard.alphabet_list.index(scrambled_char),0)
|
|
86
98
|
logging.debug("Scrambled letter from plugboard: {}".format(scrambled_char))
|
|
87
99
|
logging.info("Scrambled letter to lamp: {}".format(scrambled_char))
|
|
88
100
|
return scrambled_char
|
|
@@ -91,14 +103,24 @@ class Enigma(Observer):
|
|
|
91
103
|
# If there is rotor N+1, increment its position by 1
|
|
92
104
|
if observable in self.rotors and self.rotors.index(observable) < len(self.rotors)-1:
|
|
93
105
|
self.rotors[self.rotors.index(observable)+1].increment_position()
|
|
106
|
+
logging.debug("Rotor at index {} has been incremented by 1 position".format(self.rotors.index(observable)+1))
|
|
94
107
|
# Engaging the enigma double step issue, only if the next rotor position is in its notch indexe/s
|
|
95
108
|
if self.rotors[self.rotors.index(observable)+1].position in self.rotors[self.rotors.index(observable)+1].notch_indexes:
|
|
96
109
|
self.rotors[self.rotors.index(observable)+1].double_step_triggered = True
|
|
110
|
+
# If the rotor is the last one in the list, but the machine has a rotating reflector, increment it position by 1
|
|
111
|
+
if observable in self.rotors and self.rotors.index(observable) == len(self.rotors)-1 and isinstance(self.reflector, RotatingReflector):
|
|
112
|
+
self.reflector.increment_position()
|
|
113
|
+
logging.debug("Reflector has been incremented by 1 position")
|
|
114
|
+
# Engaging the enigma double step issue, only if the next rotor position is in its notch indexe/s
|
|
115
|
+
if self.reflector.position in self.reflector.notch_indexes:
|
|
116
|
+
self.reflector.double_step_triggered = True
|
|
97
117
|
|
|
98
118
|
@staticmethod
|
|
99
119
|
def shift_letter(letter,shift,alphabet_list):
|
|
100
120
|
return alphabet_list[(alphabet_list.index(letter)+shift) % len(alphabet_list)]
|
|
101
121
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
122
|
+
def clone(self):
|
|
123
|
+
new_enigma = super().clone()
|
|
124
|
+
for rotor in new_enigma.rotors:
|
|
125
|
+
rotor.add_observer(new_enigma)
|
|
126
|
+
return new_enigma
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from .Enigma import Enigma
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
from .PlugboardPassthrough import PlugboardPassthrough
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class EnigmaB_A133(Enigma):
|
|
7
|
+
|
|
8
|
+
alphabet=Alphabets.lookup.get("enigma_b_a133_28chars_lowercase")
|
|
9
|
+
|
|
10
|
+
def __init__(self,rotor1, rotor2, rotor3,reflector,etw,auto_increment_rotors=False):
|
|
11
|
+
rotors = [rotor1, rotor2, rotor3]
|
|
12
|
+
super().__init__(PlugboardPassthrough(alphabet=self.alphabet),rotors,reflector,etw,auto_increment_rotors, alphabet=self.alphabet)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaB_A133RotorI(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'psbgöxqjdhoäucfrtezvåinlymka'
|
|
7
|
+
notch_indexes = [11]
|
|
8
|
+
tag = "B_A133_I"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring=self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get("enigma_b_a133_28chars_lowercase")
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaB_A133RotorII(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'chnsyöadmotrzxbäigåekqupflvj'
|
|
7
|
+
notch_indexes = [15]
|
|
8
|
+
tag = "B_A133_II"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring=self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get("enigma_b_a133_28chars_lowercase")
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaB_A133RotorIII(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'åvqiaäxrjbözspcfyunthdomekgl'
|
|
7
|
+
notch_indexes = [5]
|
|
8
|
+
tag = "B_A133_III"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring=self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get("enigma_b_a133_28chars_lowercase")
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaDRotorI(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'lpgszmhaeoqkvxrfybutnicjdw'
|
|
7
|
+
notch_indexes = [24]
|
|
8
|
+
tag = "D_I"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring=self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaDRotorII(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'slvgbtfxjqohewirzyamkpcndu'
|
|
7
|
+
notch_indexes = [4]
|
|
8
|
+
tag = "D_II"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring=self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaDRotorIII(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'cjgdpshkturawzxfmynqobvlie'
|
|
7
|
+
notch_indexes = [13]
|
|
8
|
+
tag = "D_III"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring=self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaINorwayRotorI(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'wtokasuyvrbxjhqcpzefmdinlg'
|
|
7
|
+
notch_indexes = [16]
|
|
8
|
+
tag = "IN_I"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring=self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaINorwayRotorII(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'gjlpubswemctqvhxaofzdrkyni'
|
|
8
|
+
notch_indexes = [4]
|
|
9
|
+
tag = "IN_II"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring=self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
18
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaINorwayRotorIII(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'jwfmhnbpusdytixvzgrqlaoekc'
|
|
8
|
+
notch_indexes = [21]
|
|
9
|
+
tag = "IN_III"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring=self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
18
|
+
)
|
|
19
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaINorwayRotorIV(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'fgzjmvxepbwshqtliudykcnrao'
|
|
8
|
+
notch_indexes = [21]
|
|
9
|
+
tag = "IN_IV"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring=self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
18
|
+
)
|
|
19
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaINorwayRotorV(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'hejxqotzbvfdascilwpgynmurk'
|
|
8
|
+
notch_indexes = [25]
|
|
9
|
+
tag = "IN_V"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring=self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get('latin_i18n_26chars_lowercase')
|
|
18
|
+
)
|
|
19
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaIRotorI(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'ekmflgdqvzntowyhxuspaibrcj'
|
|
7
|
+
notch_indexes = [16]
|
|
8
|
+
tag = "I_I"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring = self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaIRotorII(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'ajdksiruxblhwtmcqgznpyfvoe'
|
|
7
|
+
notch_indexes = [4]
|
|
8
|
+
|
|
9
|
+
tag = "I_II"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring = self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
18
|
+
)
|
|
19
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaIRotorIII(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'bdfhjlcprtxvznyeiwgakmusqo'
|
|
7
|
+
notch_indexes = [21]
|
|
8
|
+
|
|
9
|
+
tag = "I_III"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring = self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
18
|
+
)
|
|
19
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaIRotorIV(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'esovpzjayquirhxlnftgkdcmwb'
|
|
8
|
+
notch_indexes = [9]
|
|
9
|
+
|
|
10
|
+
tag = "I_IV"
|
|
11
|
+
|
|
12
|
+
def __init__(self, position = 0, ring = 0):
|
|
13
|
+
super().__init__(
|
|
14
|
+
wiring = self.wiring,
|
|
15
|
+
position=position,
|
|
16
|
+
ring=ring,
|
|
17
|
+
notch_indexes=self.notch_indexes,
|
|
18
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
19
|
+
)
|
|
20
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaIRotorV(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'vzbrgityupsdnhlxawmjqofeck'
|
|
8
|
+
notch_indexes = [25]
|
|
9
|
+
tag = "I_V"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring = self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
18
|
+
)
|
|
19
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaISonderRotorI(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'veosirzujdqckgwypnxaflthmb'
|
|
7
|
+
notch_indexes = [16]
|
|
8
|
+
tag = "IS_I"
|
|
9
|
+
|
|
10
|
+
def __init__(self, position = 0, ring = 0):
|
|
11
|
+
super().__init__(
|
|
12
|
+
wiring = self.wiring,
|
|
13
|
+
position=position,
|
|
14
|
+
ring=ring,
|
|
15
|
+
notch_indexes=self.notch_indexes,
|
|
16
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
17
|
+
)
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaISonderRotorII(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'uemoatqlshpkcyfwjzbgvxidnr'
|
|
8
|
+
notch_indexes = [4]
|
|
9
|
+
tag = "IS_II"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring = self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
18
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EnigmaISonderRotorIII(Rotor):
|
|
6
|
+
|
|
7
|
+
wiring = 'tzhxmbsipnurjfdkeqvcwglaoy'
|
|
8
|
+
notch_indexes = [21]
|
|
9
|
+
tag = "IS_III"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring = self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
18
|
+
)
|
|
19
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .Rotor import Rotor
|
|
2
|
+
from .Alphabets import Alphabets
|
|
3
|
+
|
|
4
|
+
class EnigmaM3RotorI(Rotor):
|
|
5
|
+
|
|
6
|
+
wiring = 'ekmflgdqvzntowyhxuspaibrcj'
|
|
7
|
+
notch_indexes = [16]
|
|
8
|
+
|
|
9
|
+
tag = "M3_I"
|
|
10
|
+
|
|
11
|
+
def __init__(self, position = 0, ring = 0):
|
|
12
|
+
super().__init__(
|
|
13
|
+
wiring = self.wiring,
|
|
14
|
+
position=position,
|
|
15
|
+
ring=ring,
|
|
16
|
+
notch_indexes=self.notch_indexes,
|
|
17
|
+
alphabet=Alphabets.lookup.get("latin_i18n_26chars_lowercase")
|
|
18
|
+
)
|
|
19
|
+
|