enigmapython 1.0.0__tar.gz → 1.1.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.
Files changed (70) hide show
  1. {enigmapython-1.0.0 → enigmapython-1.1.0}/PKG-INFO +33 -3
  2. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/Enigma.py +28 -10
  3. enigmapython-1.1.0/enigmapython/EnigmaD.py +9 -0
  4. enigmapython-1.1.0/enigmapython/EnigmaDEtw_JWULCM.py +6 -0
  5. enigmapython-1.1.0/enigmapython/EnigmaDEtw_QWERTZ.py +6 -0
  6. enigmapython-1.1.0/enigmapython/EnigmaDRotorI.py +11 -0
  7. enigmapython-1.1.0/enigmapython/EnigmaDRotorII.py +11 -0
  8. enigmapython-1.1.0/enigmapython/EnigmaDRotorIII.py +11 -0
  9. enigmapython-1.1.0/enigmapython/Etw.py +22 -0
  10. enigmapython-1.1.0/enigmapython/ReflectorDUKW.py +9 -0
  11. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/Rotor.py +10 -9
  12. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython.egg-info/PKG-INFO +33 -3
  13. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython.egg-info/SOURCES.txt +7 -0
  14. {enigmapython-1.0.0 → enigmapython-1.1.0}/setup.py +1 -1
  15. enigmapython-1.0.0/enigmapython/Etw.py +0 -14
  16. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaI.py +0 -0
  17. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaINorway.py +0 -0
  18. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaINorwayRotorI.py +0 -0
  19. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaINorwayRotorII.py +0 -0
  20. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaINorwayRotorIII.py +0 -0
  21. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaINorwayRotorIV.py +0 -0
  22. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaINorwayRotorV.py +0 -0
  23. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaIRotorI.py +0 -0
  24. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaIRotorII.py +0 -0
  25. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaIRotorIII.py +0 -0
  26. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaIRotorIV.py +0 -0
  27. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaIRotorV.py +0 -0
  28. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaISonder.py +0 -0
  29. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaISonderRotorI.py +0 -0
  30. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaISonderRotorII.py +0 -0
  31. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaISonderRotorIII.py +0 -0
  32. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3.py +0 -0
  33. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorI.py +0 -0
  34. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorII.py +0 -0
  35. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorIII.py +0 -0
  36. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorIV.py +0 -0
  37. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorV.py +0 -0
  38. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorVI.py +0 -0
  39. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorVII.py +0 -0
  40. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM3RotorVIII.py +0 -0
  41. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4.py +0 -0
  42. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorBeta.py +0 -0
  43. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorGamma.py +0 -0
  44. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorI.py +0 -0
  45. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorII.py +0 -0
  46. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorIII.py +0 -0
  47. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorIV.py +0 -0
  48. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorV.py +0 -0
  49. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorVI.py +0 -0
  50. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorVII.py +0 -0
  51. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EnigmaM4RotorVIII.py +0 -0
  52. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/EtwPassthrough.py +0 -0
  53. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/Observable.py +0 -0
  54. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/Observer.py +0 -0
  55. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/Plugboard.py +0 -0
  56. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/PlugboardPassthrough.py +0 -0
  57. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/Reflector.py +0 -0
  58. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/ReflectorNorwayUKW.py +0 -0
  59. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/ReflectorSonderUKW.py +0 -0
  60. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/ReflectorUKWA.py +0 -0
  61. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/ReflectorUKWB.py +0 -0
  62. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/ReflectorUKWBThin.py +0 -0
  63. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/ReflectorUKWC.py +0 -0
  64. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/ReflectorUKWCThin.py +0 -0
  65. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/SwappablePlugboard.py +0 -0
  66. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/Utils.py +0 -0
  67. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython/__init__.py +0 -0
  68. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython.egg-info/dependency_links.txt +0 -0
  69. {enigmapython-1.0.0 → enigmapython-1.1.0}/enigmapython.egg-info/top_level.txt +0 -0
  70. {enigmapython-1.0.0 → enigmapython-1.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: enigmapython
3
- Version: 1.0.0
3
+ Version: 1.1.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
@@ -24,6 +24,17 @@ Welcome to **enigmapython**, a Python package designed to emulate the legendary
24
24
 
25
25
  The following Enigma machine models (along with their rotors, reflectors and plugboards) have been implemented:
26
26
 
27
+ ### Enigma D
28
+
29
+ | Scrambler | Wiring | Notch | Implemented |
30
+ |------- |---------------------------- |------- |------------- |
31
+ | ETW "QWERTZ" | qwertzuioasdfghjkpyxcvbnml | N/A | ✅ |
32
+ | ETW "JWULCM" | jwulcmnohpqzyxiradkegvbtsf | N/A | ✅ |
33
+ | Rotor I | lpgszmhaeoqkvxrfybutnicjdw | y | ✅ |
34
+ | Rotor II | slvgbtfxjqohewirzyamkpcndu | e | ✅ |
35
+ | Rotor III | bdfhjlcprtxvznyeiwgakmusqo | n | ✅ |
36
+ | Reflector UKW | imetcgfraysqbzxwlhkdvupojn | N/A | ✅ |
37
+
27
38
  ### Enigma I
28
39
 
29
40
  | Scrambler | Wiring | Notch | Implemented |
@@ -109,17 +120,36 @@ Please have a look of the [examples](https://github.com/denismaggior8/enigma-pyt
109
120
 
110
121
  ## Documentation
111
122
 
112
- TBD, for now... code (and comments) are the documentation
123
+ An initial documentation draft can be found [here](./docs/README.md), but in most cases examples, code (and comments) are better than the documentation
124
+
125
+ ## Known implementations
126
+
127
+ Here's a list containing all the known Enigma simulators that use the **enigmapython** API.
128
+
129
+ - [Retrocampus BBS Enigma simulator](https://retrocampus.com/bbs/). When connected to the BBS, type E to access an Enigma M3 cypher machine. ![](img/retrocampus_enigma.png)
130
+
131
+ 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.
132
+
133
+
134
+ ## Known implementations
135
+
136
+ Here's a list containing all the known Enigma simulators that use the **enigmapython** API.
137
+
138
+ - [Retrocampus BBS Enigma simulator](https://retrocampus.com/bbs/). When connected to the BBS, type E to access an Enigma M3 cypher machine. ![](img/retrocampus_enigma.png)
139
+
140
+ 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
+
113
142
 
114
143
  ## Credits/references
115
144
 
116
145
  - Early days experiments with Python and Enigma (where this repo comes from) can be found at: https://github.com/denismaggior8/enigma-cypher
117
- - Rotors wirings have been taken from Crypto Museum at this link https://www.cryptomuseum.com/crypto/enigma/wiring.htm
146
+ - Rotors wirings have been taken from **Crypto Museum** at this link https://www.cryptomuseum.com/crypto/enigma/wiring.htm
118
147
  - Thanks to
119
148
  - Piotte13 https://piotte13.github.io/enigma-cipher/
120
149
  - Cryptii https://cryptii.com
121
150
  - PyEnigma https://pypi.org/project/pyenigma/
122
151
  - 101 computing https://www.101computing.net/enigma-machine-emulator/
152
+ - DenCode Enigma simulator https://dencode.com/cipher/enigma
123
153
 
124
154
  for having helped me testing the correctness of the generated ciphertexts
125
155
 
@@ -11,14 +11,15 @@ class Enigma(Observer):
11
11
  etw = None
12
12
  auto_increment_rotors = False
13
13
 
14
- alphabet = list(ascii_lowercase)
14
+ alphabet_list = None
15
15
 
16
- def __init__(self, plugboard, rotors, reflector,etw,auto_increment_rotors=False):
16
+ def __init__(self, plugboard, rotors, reflector,etw,auto_increment_rotors=False, alphabet=ascii_lowercase):
17
17
  self.plugboard = plugboard
18
18
  self.rotors = rotors
19
19
  self.reflector = reflector
20
20
  self.etw = etw
21
21
  self.auto_increment_rotors = auto_increment_rotors
22
+ self.alphabet_list = list(alphabet)
22
23
  if auto_increment_rotors == True:
23
24
  for rotor in rotors:
24
25
  rotor.add_observer(self)
@@ -42,28 +43,45 @@ class Enigma(Observer):
42
43
  scrambled_char = self.process_char(char)
43
44
  return scrambled_char
44
45
 
46
+ """
47
+ UKW Rotor Rotor Rotor ETW PLUGBOARD
48
+ N 2 1
49
+ ___ ___ ___ ___ ___ ___
50
+ | | | | | | | | | | | |
51
+ | -|--|---|--|---|--|---|--|---|--|---|-- < Key
52
+ | | | | | | | | | | | | |
53
+ | | | | | | | | | | | | |
54
+ | -|--|---|--|---|--|---|--|---|--|---|-- > Lamp
55
+ | | | | | | | | | | | |
56
+ --- --- --- --- --- ---
57
+ """
45
58
  def process_char(self, char):
46
59
  scrambled_char = self.plugboard.switch_char(char)
47
60
  logging.debug("Scrambled letter from plugboard: {}".format(scrambled_char))
61
+ scrambled_char = self.etw.process_char_forward(scrambled_char,0)
62
+ logging.debug("Scrambled letter from ETW: {}".format(scrambled_char))
48
63
  iteration = 0
49
64
  for rotor in self.rotors:
50
65
  if iteration == 0:
51
- scrambled_char = rotor.scramble_letter_index(rotor.wiring,Enigma.alphabet.index(scrambled_char))
66
+ scrambled_char = rotor.scramble_letter_index(rotor.wiring,self.alphabet_list.index(scrambled_char))
52
67
  else:
53
- scrambled_char = rotor.scramble_letter_index(rotor.wiring,Enigma.alphabet.index(scrambled_char)-self.rotors[iteration-1].position)
68
+ scrambled_char = rotor.scramble_letter_index(rotor.wiring,self.alphabet_list.index(scrambled_char)-self.rotors[iteration-1].position)
54
69
  iteration +=1
55
70
  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))
71
+ scrambled_char = self.reflector.scramble_letter_index(self.reflector.wiring,(self.alphabet_list.index(scrambled_char)-self.rotors[iteration-1].position))
57
72
  logging.debug("Scrambled letter from reflector: {}".format(scrambled_char))
58
73
  for rotor in reversed(self.rotors):
59
74
  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))
75
+ scrambled_char = rotor.scramble_letter_index(self.alphabet_list,(rotor.wiring.index(self.shift_letter(scrambled_char,rotor.position,self.alphabet_list))-rotor.position))
61
76
  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))
77
+ scrambled_char = rotor.scramble_letter_index(self.alphabet_list,(rotor.wiring.index(self.shift_letter(scrambled_char, (rotor.position - self.rotors[iteration].position),self.alphabet_list)) - rotor.position))
63
78
  iteration -=1
64
79
  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)
80
+
81
+ # Processing rotor 1 returning signal by ETW
82
+ scrambled_char = self.etw.process_char_backward(scrambled_char,self.rotors[iteration].position)
66
83
  logging.debug("Scrambled letter from ETW: {}".format(scrambled_char))
84
+
67
85
  scrambled_char = self.plugboard.switch_char(scrambled_char)
68
86
  logging.debug("Scrambled letter from plugboard: {}".format(scrambled_char))
69
87
  logging.info("Scrambled letter to lamp: {}".format(scrambled_char))
@@ -78,8 +96,8 @@ class Enigma(Observer):
78
96
  self.rotors[self.rotors.index(observable)+1].double_step_triggered = True
79
97
 
80
98
  @staticmethod
81
- def shift_letter(letter,shift):
82
- return Enigma.alphabet[(Enigma.alphabet.index(letter)+shift) % len(Enigma.alphabet)]
99
+ def shift_letter(letter,shift,alphabet_list):
100
+ return alphabet_list[(alphabet_list.index(letter)+shift) % len(alphabet_list)]
83
101
 
84
102
 
85
103
 
@@ -0,0 +1,9 @@
1
+ from .Enigma import Enigma
2
+ from .PlugboardPassthrough import PlugboardPassthrough
3
+
4
+
5
+ class EnigmaD(Enigma):
6
+
7
+ def __init__(self,rotor1, rotor2, rotor3,reflector,etw,auto_increment_rotors=False):
8
+ rotors = [rotor1, rotor2, rotor3]
9
+ super().__init__(PlugboardPassthrough(),rotors,reflector,etw,auto_increment_rotors)
@@ -0,0 +1,6 @@
1
+ from .Etw import Etw
2
+
3
+ class EnigmaDEtw_JWULCM(Etw):
4
+ wiring = "jwulcmnohpqzyxiradkegvbtsf"
5
+ def __init__(self):
6
+ super().__init__(self.wiring)
@@ -0,0 +1,6 @@
1
+ from .Etw import Etw
2
+
3
+ class EnigmaDEtw_QWERTZ(Etw):
4
+ wiring = "qwertzuioasdfghjkpyxcvbnml"
5
+ def __init__(self):
6
+ super().__init__(self.wiring)
@@ -0,0 +1,11 @@
1
+ from .Rotor import Rotor
2
+
3
+ class EnigmaDRotorI(Rotor):
4
+
5
+ wiring = 'lpgszmhaeoqkvxrfybutnicjdw'
6
+ notch_indexes = [24]
7
+ tag = "D_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 EnigmaDRotorII(Rotor):
4
+
5
+ wiring = 'slvgbtfxjqohewirzyamkpcndu'
6
+ notch_indexes = [4]
7
+ tag = "D_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 EnigmaDRotorIII(Rotor):
4
+
5
+ wiring = 'cjgdpshkturawzxfmynqobvlie'
6
+ notch_indexes = [13]
7
+ tag = "D_III"
8
+
9
+ def __init__(self, position = 0, ring = 0):
10
+ super().__init__(self.wiring, position, ring, self.notch_indexes)
11
+
@@ -0,0 +1,22 @@
1
+
2
+ from string import ascii_lowercase
3
+
4
+ class Etw:
5
+ wiring = None
6
+ alphabet_list = None
7
+
8
+ def process_char_forward(self,char,shift):
9
+ return self.wiring[self.alphabet_list.index(char)+shift]
10
+
11
+ def process_char_backward(self,char,shift):
12
+ myint = (self.alphabet_list.index(char)-shift) % len(self.alphabet_list)
13
+ myletter = self.alphabet_list[myint]
14
+ myint1 = self.wiring.index(myletter)
15
+ return self.alphabet_list[myint1]
16
+
17
+ def __init__(self, wiring, alphabet=ascii_lowercase):
18
+ self.wiring = wiring
19
+ self.alphabet_list = list(alphabet)
20
+
21
+ def __str__(self):
22
+ return self.wiring
@@ -0,0 +1,9 @@
1
+ from .Rotor import Rotor
2
+ from .Reflector import Reflector
3
+ class ReflectorDUKW(Reflector):
4
+
5
+ wiring = 'imetcgfraysqbzxwlhkdvupojn'
6
+ tag = "D_UKW"
7
+
8
+ def __init__(self):
9
+ super().__init__(self.wiring,0)
@@ -13,6 +13,7 @@ class Rotor(Observable):
13
13
  ring = None
14
14
  dot_position = None
15
15
  lookup = {}
16
+ alphabet_list = None
16
17
 
17
18
  @staticmethod
18
19
  def register(tag, class_name):
@@ -38,7 +39,7 @@ class Rotor(Observable):
38
39
  scrambled_letter_index_from_rotor = dictionary.index(dictionary[(self.position + letter_index) % len(dictionary)])
39
40
  return dictionary[scrambled_letter_index_from_rotor]
40
41
 
41
- def __init__(self, wiring, position = 0, ring = 0, notch_indexes=[]):
42
+ def __init__(self, wiring, position = 0, ring = 0, notch_indexes=[], alphabet=ascii_lowercase):
42
43
  self.wiring = wiring
43
44
  self.position = position % len(wiring)
44
45
  self.notch_indexes = notch_indexes
@@ -46,6 +47,7 @@ class Rotor(Observable):
46
47
  self.rotations_counter = 0
47
48
  self.original_wiring = self.wiring
48
49
  self.ring = ring
50
+ self.alphabet_list = list(alphabet)
49
51
  self.set_rotor_ring(ring)
50
52
 
51
53
  def __str__(self):
@@ -59,7 +61,6 @@ class Rotor(Observable):
59
61
  self.wiring = self.original_wiring
60
62
  self.dot_position = list(self.wiring).index("a")
61
63
  logging.debug("Dot position: " + str(self.dot_position))
62
- alphabet = list(ascii_lowercase)
63
64
  for i in range(0, ring):
64
65
  # Set temporary wiring variable
65
66
  temp_wiring = self.wiring
@@ -68,25 +69,25 @@ class Rotor(Observable):
68
69
  # Loop over chars in temporary wiring
69
70
  for char in temp_wiring:
70
71
  # Shift the char by one and add that shifted char to wiring variable
71
- wiring += Rotor.shift(char, 1, alphabet)
72
+ wiring += Rotor.shift(char, 1, self.alphabet_list)
72
73
  # Add one to dot position, make sure we don't exceed the lenght of the alphabet
73
74
  self.wiring = wiring
74
- self.dot_position = (self.dot_position + 1) % len(alphabet)
75
+ self.dot_position = (self.dot_position + 1) % len(self.alphabet_list)
75
76
  logging.debug("Wiring shifted up the alphabet: " + wiring)
76
77
  logging.debug("New dot position: " + str(self.dot_position))
77
78
  i = 0
78
79
  # 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
+ while not self.wiring[self.dot_position] == self.alphabet_list[ring % len(self.wiring)]:
80
81
  i += 1
81
82
  # Rotate the wiring
82
83
  self.wiring = self.wiring[-1:] + self.wiring[:-1]
83
84
  logging.debug("Rotation " + str(i).zfill(2) + "; Wiring: " + self.wiring)
84
85
 
85
86
  @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)]
87
+ def shift(letter, shift, alphabet_list):
88
+ for i in range(0, len(alphabet_list)):
89
+ if alphabet_list[i] == letter:
90
+ return alphabet_list[(i + shift) % len(alphabet_list)]
90
91
 
91
92
  @staticmethod
92
93
  def get_instance_from_tag(tag: str):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: enigmapython
3
- Version: 1.0.0
3
+ Version: 1.1.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
@@ -24,6 +24,17 @@ Welcome to **enigmapython**, a Python package designed to emulate the legendary
24
24
 
25
25
  The following Enigma machine models (along with their rotors, reflectors and plugboards) have been implemented:
26
26
 
27
+ ### Enigma D
28
+
29
+ | Scrambler | Wiring | Notch | Implemented |
30
+ |------- |---------------------------- |------- |------------- |
31
+ | ETW "QWERTZ" | qwertzuioasdfghjkpyxcvbnml | N/A | ✅ |
32
+ | ETW "JWULCM" | jwulcmnohpqzyxiradkegvbtsf | N/A | ✅ |
33
+ | Rotor I | lpgszmhaeoqkvxrfybutnicjdw | y | ✅ |
34
+ | Rotor II | slvgbtfxjqohewirzyamkpcndu | e | ✅ |
35
+ | Rotor III | bdfhjlcprtxvznyeiwgakmusqo | n | ✅ |
36
+ | Reflector UKW | imetcgfraysqbzxwlhkdvupojn | N/A | ✅ |
37
+
27
38
  ### Enigma I
28
39
 
29
40
  | Scrambler | Wiring | Notch | Implemented |
@@ -109,17 +120,36 @@ Please have a look of the [examples](https://github.com/denismaggior8/enigma-pyt
109
120
 
110
121
  ## Documentation
111
122
 
112
- TBD, for now... code (and comments) are the documentation
123
+ An initial documentation draft can be found [here](./docs/README.md), but in most cases examples, code (and comments) are better than the documentation
124
+
125
+ ## Known implementations
126
+
127
+ Here's a list containing all the known Enigma simulators that use the **enigmapython** API.
128
+
129
+ - [Retrocampus BBS Enigma simulator](https://retrocampus.com/bbs/). When connected to the BBS, type E to access an Enigma M3 cypher machine. ![](img/retrocampus_enigma.png)
130
+
131
+ 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.
132
+
133
+
134
+ ## Known implementations
135
+
136
+ Here's a list containing all the known Enigma simulators that use the **enigmapython** API.
137
+
138
+ - [Retrocampus BBS Enigma simulator](https://retrocampus.com/bbs/). When connected to the BBS, type E to access an Enigma M3 cypher machine. ![](img/retrocampus_enigma.png)
139
+
140
+ 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
+
113
142
 
114
143
  ## Credits/references
115
144
 
116
145
  - Early days experiments with Python and Enigma (where this repo comes from) can be found at: https://github.com/denismaggior8/enigma-cypher
117
- - Rotors wirings have been taken from Crypto Museum at this link https://www.cryptomuseum.com/crypto/enigma/wiring.htm
146
+ - Rotors wirings have been taken from **Crypto Museum** at this link https://www.cryptomuseum.com/crypto/enigma/wiring.htm
118
147
  - Thanks to
119
148
  - Piotte13 https://piotte13.github.io/enigma-cipher/
120
149
  - Cryptii https://cryptii.com
121
150
  - PyEnigma https://pypi.org/project/pyenigma/
122
151
  - 101 computing https://www.101computing.net/enigma-machine-emulator/
152
+ - DenCode Enigma simulator https://dencode.com/cipher/enigma
123
153
 
124
154
  for having helped me testing the correctness of the generated ciphertexts
125
155
 
@@ -1,5 +1,11 @@
1
1
  setup.py
2
2
  enigmapython/Enigma.py
3
+ enigmapython/EnigmaD.py
4
+ enigmapython/EnigmaDEtw_JWULCM.py
5
+ enigmapython/EnigmaDEtw_QWERTZ.py
6
+ enigmapython/EnigmaDRotorI.py
7
+ enigmapython/EnigmaDRotorII.py
8
+ enigmapython/EnigmaDRotorIII.py
3
9
  enigmapython/EnigmaI.py
4
10
  enigmapython/EnigmaINorway.py
5
11
  enigmapython/EnigmaINorwayRotorI.py
@@ -43,6 +49,7 @@ enigmapython/Observer.py
43
49
  enigmapython/Plugboard.py
44
50
  enigmapython/PlugboardPassthrough.py
45
51
  enigmapython/Reflector.py
52
+ enigmapython/ReflectorDUKW.py
46
53
  enigmapython/ReflectorNorwayUKW.py
47
54
  enigmapython/ReflectorSonderUKW.py
48
55
  enigmapython/ReflectorUKWA.py
@@ -12,7 +12,7 @@ setup(
12
12
  long_description_content_type='text/markdown',
13
13
  url="https://github.com/denismaggior8/enigma-python",
14
14
  name="enigmapython",
15
- version="1.0.0",
15
+ version="1.1.0",
16
16
  packages=find_packages(
17
17
  # All keyword arguments below are optional:
18
18
  where='.', # '.' by default
@@ -1,14 +0,0 @@
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
File without changes