Skip to content

Commit 7b1c9cf

Browse files
version 1.0.0
1 parent baeefa6 commit 7b1c9cf

23 files changed

+2742
-1769
lines changed

README.md

Lines changed: 142 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,144 @@
1+
12
# Enigma Bruteforcer
23

3-
This is a personal tool I use to bruteforce the decryption of Enigma ciphers, emphasizing speed. It's functional, but not yet in a polished library form. Expect frequent breakage until published as a library. The code has reached fair performance, so I decided to release it in alpha form as I continue to improve it.
4+
A tool for bruteforcing enigma ciphers. Currently breaks ciphers where the plugboard is already known.
5+
6+
7+
# Installation
8+
9+
Clone or download the project. Open up `crack_enigma.cpp` and in the `main` function place your code (see Basic Usage below). Compile by running `make` or `make crack_enigma` and run with `./crack_enigma`.
10+
11+
To import into an existing project, you need the the contents of the `source/` and `include/` folders. `include/bruteforce-enigma.h` adds a nicer interface and multithreading, but doesn't contain any core functionality. Compile and link with the .cpp files from `source/`, but you can only compile against one quadgram language file (`qgr.cpp` or `de_qgr.cpp`) at a time. Requires compiling with C++20 and pthreads.
12+
13+
14+
# Basic Usage
15+
16+
**Decipher with a known setting**
17+
```Cpp
18+
Ciphertext ct = "odlio qsapd tbttn ueokz jbqzw hlynd mmbvn dlanx tvrny lvqmj kovre v";
19+
Plugboard plug = "bq cr di ej kw mt os px uz gh";
20+
21+
Enigma enigma {ETW_ABCDEF, m3_I, m3_III, m3_I, m3_UKWB, plug, "BLQ", "BEC"};
22+
23+
Ciphertext pt = enigma.encrypt(ct);
24+
std::cout << pt;
25+
```
26+
27+
28+
To decipher an m4 model, replace `Enigma` above with `Enigma4`, like so.
29+
```Cpp
30+
Enigma4 enigma {ETW_ABCDEF, m3_I, m3_III, m3_I, m4_beta, m4_UKWB_thin, plug, "BLQA", "BECA"};
31+
```
32+
433

5-
Currently cracks ciphers where the plugboard is already known.
34+
**Cracking unknown ring and rotor positions**
635

36+
The smart decipher should be sufficient for almost all ciphers. It uses a similar algorithm that [Practical Cryptography](http://www.practicalcryptography.com/cryptanalysis/breaking-machine-ciphers/cryptanalysis-enigma-part-2/) does, by first finding the best rotor combination and position, and then from the top results finding the best ring positions.
737

8-
# Usage
38+
```Cpp
39+
Ciphertext ct = "NPNKANVHWKPXORCDDTRJRXSJFLCIUAIIBUNQIUQFTHLOZOIMENDNGPCB";
40+
Plugboard plug = "";
941

10-
Open up **crack_enigma.cpp** and in the main function place your code. Using one of the two provided algorithms, pass in an enigma model, a plugboard setting, and your ciphertext. Compile by running `make` or `make crack_enigma` and run with `./crack_enigma`.
42+
EnigmaBase base = {ETW_ABCDEF, m3_IV, m3_V, m3_II, UKWB};
43+
44+
HighScores scores = smart_decipher(base, plug, ct);
45+
scores.print();
46+
```
1147
12-
To import into an existing project, drop the repo into your source tree, include include/bruteforce-enigma.h in a file, and compile and link with the .cpp files in src/. You can only compile against one quadgram language file (qgr.cpp or de_qgr.cpp) at a time.
1348
14-
Enigma models can be found in *models.cpp*. The current list includes:
15-
* m3
16-
* m3 extended (with rotors VI, VII, and VIII added)
17-
* m4 (with only three rotors at the moment)
18-
* railway
19-
* CrypTool m3 (adds reflector UKWA)
20-
* CrypTool railway (different notches)
21-
* enigma I
22-
* norenigma
23-
* sondermaschine
24-
* commercial enigma
49+
**Bruteforcing unknown ring and rotor positions**
2550
26-
Two algorithms are provided to bruteforce an enigma cipher. The first, called `smart_decipher`, should be sufficient for almost all ciphers. It uses a similar algorithm to [Practical Cryptography](http://www.practicalcryptography.com/cryptanalysis/breaking-machine-ciphers/cryptanalysis-enigma-part-2/), by first finding the best rotor combination and position, and then from the top results finding the best ring positions.
51+
The bruteforce decipher goes through every combination of rotor, rotor position, and ring position (except the third ring, which has no effect on finding a solution) of a given enigma model. Since this requires 11.9 million decryptions per rotor configuration, it takes a bit of time to finish. See below for the performance characteristics on my machine.
2752
28-
The second, called `bf_decipher`, goes through every combination of rotor, rotor position, and ring position (except the third ring, which has no effect on finding a solution) of a given enigma model. Since this requires 11.9 million decryptions per rotor configuration, it takes a bit of time to finish. See below for the performance characteristics on my machine.
53+
```Cpp
54+
Ciphertext ct = "NPNKANVHWKPXORCDDTRJRXSJFLCIUAIIBUNQIUQFTHLOZOIMENDNGPCB";
55+
Plugboard plug = "";
56+
57+
EnigmaBase base = {ETW_ABCDEF, m3_IV, m3_V, m3_II, UKWB};
58+
59+
HighScores scores = bruteforce_decipher(base, plug, ct);
60+
scores.print();
61+
```
62+
63+
64+
**Cracking unknown rotors**
65+
66+
Pass in one of the models in `models.h`.
67+
68+
```Cpp
69+
Ciphertext ct = "NPNKANVHWKPXORCDDTRJRXSJFLCIUAIIBUNQIUQFTHLOZOIMENDNGPCB";
70+
Plugboard plug = "";
71+
72+
HighScores scores = smart_decipher(m3_model, plug, ct);
73+
scores.print();
74+
```
2975

30-
Two different scoring functions are provided, `score_by_Qgram` for quadgram scoring, and `score_by_IOC_order` for IOC scoring (maintains ordering, but does not return the actual IOC).
3176

77+
**Bruteforcing unknown rotors**
78+
79+
```Cpp
80+
Ciphertext ct = "NPNKANVHWKPXORCDDTRJRXSJFLCIUAIIBUNQIUQFTHLOZOIMENDNGPCB";
81+
Plugboard plug = "";
82+
83+
HighScores scores = bruteforce_decipher(m3_model, plug, ct);
84+
scores.print();
85+
```
86+
87+
88+
**Changing the scoring model**
89+
90+
Two different scoring functions are provided, `score_by_Qgram` for quadgram scoring (the default), and `score_by_IOC_order` for IOC scoring (maintains ordering, but does not return the actual IOC). You can also provide a custom scoring function, which must take a range of integers as its only parameter.
91+
92+
```Cpp
93+
Ciphertext ct = "NPNKANVHWKPXORCDDTRJRXSJFLCIUAIIBUNQIUQFTHLOZOIMENDNGPCB";
94+
Plugboard plug = "";
95+
96+
HighScores scores = smart_decipher(m3_model, plug, ct, score_by_IOC_order);
97+
scores.print();
98+
```
99+
100+
101+
**Increasing the number of scores**
102+
103+
If you suspect a solution is missed because it is not in the top 10 results (rare), you can increase the number of high scores with a template argument. The smart decipher runtime will be increased by (26 + N)/36 %. The effect on the bruteforce runtime is negligible.
104+
105+
```Cpp
106+
Ciphertext ct = "NPNKANVHWKPXORCDDTRJRXSJFLCIUAIIBUNQIUQFTHLOZOIMENDNGPCB";
107+
Plugboard plug = "";
108+
109+
HighScores scores = smart_decipher<25>(m3_model, plug, ct);
110+
scores.print();
111+
```
112+
113+
114+
115+
# Available Models
116+
117+
Enigma model definitions can be found in `models.cpp`. The list includes:
118+
* M3
119+
* Kriegsmarine (M3 with rotors VI, VII, and VIII added)
120+
* M4
121+
* Enigma I
122+
* Norenigma
123+
* Sondermaschine
124+
* Railway
125+
* CrypTool Railway (different notches and stator)
126+
* CrypTool M3 (adds reflector UKWA to Kriegsmarine)
127+
* Commercial Enigma
128+
* Tirpitz
129+
130+
The following rotor definitions are included, but the unique machine behaviors have not been implemented.
131+
* Swiss K
132+
* Enigma KD
133+
* Zahlwerk
134+
* Enigma G-111
135+
* Enigma G-312
136+
* Enigma G-260
137+
138+
139+
# Advance Usage
140+
141+
Quadgram scoring for German can be found in `de_qgr.h` and `de_qgr.cpp`. There is currently no mechanism to specify the language at runtime, but you can change the import in `score.h` from `qgr.h` to `de_qgr.h`, recompile, and it will just work.
32142

33143

34144
# Performance
@@ -43,19 +153,18 @@ pt: INTELLIGENCEPOINTSTOATTACKONTHEEASTWALLOFTHECASTLEATDAWN
43153
From: http://practicalcryptography.com/cryptanalysis/breaking-machine-ciphers/cryptanalysis-enigma/
44154

45155

46-
| Core i7-6500U, 4 threads | smart_decipher | bf_decipher |
156+
| Core i7 2.5GHz, 4 threads | smart_decipher | bruteforce_decipher |
47157
| ------------------------------ | ----------------------| ----------------------|
48158
| Cipher length | 56 | 56 |
49-
| Enigma model | m3 (250 combinations) | m3 (250 combinations) |
50-
| Solve time | 1.6 sec | 15 min, 16 sec |
51-
| Number of decryptions / second | - | 3.24 x 10^6 |
52-
| Characters / second | - | 181.54 x 10^6 |
53-
159+
| Enigma model | M3 (250 combinations) | M3 (250 combinations) |
160+
| Solve time | 1.6 sec | 13 min, 23 sec |
161+
| Number of decryptions / second | - | 3.70 x 10^6 |
162+
| Characters / second | - | 207.16 x 10^6 |
54163

55164

56-
Scoring with IOC is faster than quadgram, but also is less accurate. IOC scoring fails to solve the above cipher, as due to the plaintext's short length, its IOC is 0.080519, while the IOC scorer looks for the average English score of 0.066.
165+
Scoring with IOC is faster than quadgram, but is also less accurate. It fails to solve the cipher above because its IOC is 0.080519, while the average English IOC is 0.066.
57166

58-
A longer cipher test was done on a text with IOC of 0.062931, which is much closer to the average English score. Even so, the smart_decipher function fails to solve the longer text, likely because IOC does not score well on the partial solutions found during the first part of the decryption process.
167+
The text below has an IOC of 0.062931, which is much closer to English. Even so, the smart_decipher function fails to solve the longer text, possibily because IOC does not score well on the partial solutions found during the first part of the decryption process.
59168

60169
```
61170
ct: YXBMXADQBDBAAYIMKDODAYIXNBDQZFJKOLFVEEQBCLUUXDFVQYGKEYBVRHONJKPJMKUNLYLZUKBKJOA
@@ -68,21 +177,20 @@ pt: THEENIGMACIPHERWASAFIELDCIPHERUSEDBYTHEGERMANSDURINGWORLDWARIITHEENIGMAISONE
68177

69178
From: http://www.practicalcryptography.com/cryptanalysis/breaking-machine-ciphers/cryptanalysis-enigma-part-2/
70179

71-
| Core i7-6500U, 4 threads | bf_decipher |
180+
| Core i7 2.5GHz, 4 threads | bruteforce_decipher |
72181
| ------------------------------ | --------------------- |
73182
| Cipher length | 170 |
74-
| Enigma model | m3 (250 combinations) |
75-
| Solve time | 44 min, 12 sec |
76-
| Number of decryptions / second | 1.12 x 10^6 |
77-
| Characters / second | 190.38 x 10^6 |
78-
183+
| Enigma model | M3 (250 combinations) |
184+
| Solve time | 33 min, 21 sec |
185+
| Number of decryptions / second | 1.48 x 10^6 |
186+
| Characters / second | 252.30 x 10^6 |
79187

80188

81189
# License
82190

83191
Copyright (c) 2020 Mike Castillo under the [MIT License](https://choosealicense.com/licenses/mit/). See LICENSE for the full terms.
84192

85-
Developed with reference to [CrypTool 2](https://www.cryptool.org/en/cryptool2) and [Practical Cryptography](http://www.practicalcryptography.com/cryptanalysis/breaking-machine-ciphers/cryptanalysis-enigma-part-2/).
193+
Developed with reference to [CrypTool 2](https://www.cryptool.org/en/cryptool2), [Practical Cryptography](http://www.practicalcryptography.com/cryptanalysis/breaking-machine-ciphers/cryptanalysis-enigma-part-2/), and [Crypto Museum](https://www.cryptomuseum.com/).
86194

87195
Currently includes some code from Practical Cryptography (*de_qgr.h*, *qgr.h*). I did not find a license, but that code remains under copyright James Lyons © 2009-2012. This project's license will be updated to respect all copyrights as needed.
88196

0 commit comments

Comments
 (0)