From 8c59c8656bf2c0de4efd3430d5c0279c5822c446 Mon Sep 17 00:00:00 2001
From: Romain Lebbadi-Breteau <romain@lebbadi.fr>
Date: Mon, 18 Jul 2022 17:08:18 -0400
Subject: [PATCH] Update writeup (small fixes)

---
 writeup/writeup.md | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/writeup/writeup.md b/writeup/writeup.md
index 8886568..113ca34 100644
--- a/writeup/writeup.md
+++ b/writeup/writeup.md
@@ -22,7 +22,7 @@ The summary of the challenge is as follows :
 Can you break Enigma without a known plaintext?
 The flag is written in all caps, with spaces and punctuation between words. It does not contain quotes.
 
-To test the machine, you can compile it by running `make -C enigma` then you can test it using example messages from the `messages` folder. For example:
+To test the machine provided by Google, you can compile it by running `make -C enigma` then you can test it using example messages from the `messages` folder. For example:
 
 ```shell
 $ ./enigma/machine VI III II NRS AO BH CU DL FM GW JZ KY PX QV XKR < messages/may_09_2022/comet.plaintext.txt | head
@@ -51,7 +51,7 @@ HFFL VQOX QZMS SASU BQOW HUDK KVPC GTXS MKFN RBBC
 
 Here, I encrypted the file `messages/may_09_2022/comet.plaintext.txt` using the settings from `messages/may_09_2022/settings`, and I got the contents of the file `messages/may_09_2022/comet.ciphertext.txt`
 
-As explained in the README.md file, the Enigma machine can only encrypt/decrypt letters from A-Z, it doesn't support spaces, punctuation or accents. Once you find the correct key for cracking the Enigma machine, you can use the same key to perform a Fernet decryption using the files `*.fernet.txt` in `messages` and get the original message with spaces and everything.
+As explained in the README.md file, the Enigma machine can only encrypt/decrypt letters from A-Z, it doesn't support spaces, punctuation or accents. Once you find the correct key for cracking the Enigma machine, you can use the same key to perform a [Fernet](https://cryptography.io/en/latest/fernet/) decryption using the files `*.fernet.txt` in `messages` and get the original message with spaces and everything.
 
 Now it's time to think about how we can crack it. The first thing to do is to search on your favorite search engine if anything similar has already been done. Since I knew a similar challenge was in the [404 CTF](https://ctftime.org/event/1646), I searched for "404 ctf enigma writeup". I found this link : https://mikelgarcialarragan.blogspot.com/2022/06/criptografia-ccxii-solucion-retos.html
 
@@ -72,13 +72,13 @@ The article explains basically how the Enigma machine worked and how by cracking
 
 You should then have a key that converts the ciphertext to the original plaintext.
 
-I also found a [video of Computerphile](https://www.youtube.com/watch?v=RzWB5jL5RX0) that said approximatly the same thing about how to crack Enigma knowing only the ciphertext.
+I also found a [video of Computerphile](https://www.youtube.com/watch?v=RzWB5jL5RX0) that said approximately the same thing about how to crack Enigma knowing only the ciphertext.
 
 ## First Try - Index of Coincidence
 
 I wrote a script in C++ that used the library provided by the CTF to encrypt/decrypt a given text using a given key, and I tried to crack the rotors and initial positions of the message from May 09. After some time trying to understand how the library worked and how to implement the index of coincidence algorithm, I ended up with [this script](https://git.step.polymtl.ca/romain/googlectf-enigma/-/blob/97d47bbd3cf4c985f0f1fd178bb8ce6fc210d8d0/coincidence.cpp) that tried all possible rotor combinations and all initial positions and calculated the IoC score for each resulting key. At this point my ring settings were always AAA and my plugboard was always empty.
 
-Unfortunately it didn't really work on the May 09 message, not finding the best settings. In order to understand what was going on, I tried cracking a text in French (my native tongue) that I generated from the Internet. My encryption key was "I II VI AAA AA AA AA AA AA AA AA AA AA AA AAA". After fixing some implementations problems, I got a script that worked for cracking my text, but not the one from the CTF. I also noticed that as soon as I was changing the ring settings or the plugboard, my script didn't work anymore. You can download this version of the script [here](https://git.step.polymtl.ca/romain/googlectf-enigma/-/tree/954ac0f262b5cf72a8661ddf01b49fb55055bbd5/) and run it like this:
+Unfortunately it didn't really work on the May 09 message, not finding the best settings. In order to understand what was going on, I tried cracking a text in French (my native tongue) that I generated from the Internet. My encryption key was `I II VI AAA AA AA AA AA AA AA AA AA AA AA AAA` ([link](https://git.step.polymtl.ca/romain/googlectf-enigma/-/blob/master/testdata/long.original)). After fixing some implementations problems, I got a script that worked for cracking my text, but not the one from the CTF. I also noticed that as soon as I was changing the ring settings or the plugboard, my script didn't work anymore. You can download this version of the script [here](https://git.step.polymtl.ca/romain/googlectf-enigma/-/tree/954ac0f262b5cf72a8661ddf01b49fb55055bbd5/) and run it like this:
 
 ```shell
 $ g++ -O3 -std=c++17 crack.cpp fitness/ioc.cpp -o crack
@@ -169,6 +169,8 @@ I then proceeded to implement the Sinkov algorithm, using unigram frequencies fr
 | adjust_plugboard     | try_adjust_plugboard | 4 575 000  | 3000    |
 | finalAdjust          | try_final            | 456 976    | 676     |
 
+Iterations: Number of possible keys tried in the function. These are spread across the indicated number of threads.
+
 `find_rotor_order` finds the 3000 best rotor settings and initial positions, then `adjust_ring_settings` finds the best ring setting for each of the 3000 best results, then same for `adjust_plugboard`, which finds the best plugboard configuration for each of the 3000 results from before, then `finalAdjust` cracks the initial positions and ring settings again from the best result after `adjust_plugboard`. This should give you the right key for cracking basically any message. For better results, I used the Sinkov algorithm for `find_rotor_order` and `adjust_ring_settings`, then Quadgrams for `adjust_plugboard` and `finalAdjust`. We can now crack `messages/may_09_2022/comet.ciphertext.txt` using this command:
 
 ```shell
@@ -188,7 +190,7 @@ Files /dev/stdin and ./messages/may_09_2022/comet.plaintext.txt are identical
 
 However, the key is not exactly the same, the leftmost ring setting and initial position differ. I eventually understood that for each leftmost ring setting, there was an equivalent leftmost initial position that gave exactly the same result, so I added a `find_all_solutions` function that computed for the best key what were the right initial positions for each leftmost ring setting. The CTF team later published an updated script for `encrypt_modern.py` that converted our key to one that would always work for the Fernet cipher, with a leftmost ring setting forced to "A".
 
-Another problem that was also later fixed by the CTF team, was the order of the plugs in the plugboard. It doesn't matter if you use the first or the second version of this same key:
+Another problem that was also later fixed by the CTF team, was the order of the plugs in the plugboard. It doesn't matter if you use the first or the second version of this same key where the order of plugboard pairs differ:
 
 ```
 VI III II VRS AO BH CU DL FM GW JZ KY PX QV FKR
@@ -207,8 +209,7 @@ $ ./crack 0 < messages/may_12_2022/flag.ciphertext.txt
 3 : VII IV I ZSM AH BO CL DU FW GM JY KZ PV QX AJQ : -12947.5
 ...
 $ ./enigma/machine VII IV I ZSN AH BO CL DU FW GM JY KZ PV QX AJR < messages/may_12_2022/flag.ciphertext.txt
-$ ./encrypt_modern.py decrypt VII IV I ZSN AH BO CL DU FW GM JY KZ PV QX AJR < messages/may_12
-_2022/flag.fernet.txt
+$ ./encrypt_modern.py decrypt VII IV I ZSN AH BO CL DU FW GM JY KZ PV QX AJR < messages/may_12_2022/flag.fernet.txt
 
 Traceback (most recent call last):
   File "/home/romain/dev/googlectf/googlectf-enigma/./encrypt_modern.py", line 54, in <module>
@@ -253,7 +254,7 @@ I then submitted the flag `CTF-{DU HAST GETAN, WAS TURING NICHT KONNTE}`, which
 
 I really enjoyed this challenge, that required a lot of reading, but also good programming skills and even some ability to understand German in some cases. I learned a lot about how the Enigma machine worked, but also how you can use statistics to evaluate the quality of a partially decrypted text, and also how to use threading and cloud platforms to bruteforce a cipher algorithm.
 
-There are also a lot of things I could have done better. For example, if I had read more patiently the information available to me, I would have avoided a lot of rabbit holes, because I just didn't understand how some aspects of Enigma worked, like the leftmost ring setting that doesn't change the decryption result. I also should have tested my code one part at a time to discover my implementation errors earlier.
+There are also a lot of things I could have done better. For example, if I had read more patiently the information available to me, I would have avoided a lot of rabbit holes, because I just didn't understand how some aspects of Enigma worked, like the leftmost ring setting that doesn't change the decryption result. I also should have tested my code one part at a time to discover my implementation errors earlier. Finally, I probably could have saved a lot of CPU time by just keeping less "good results" and running one part at a time, instead of re-solving everything when I had an error at the third or fourth step.
 
 Even in the context of a competition with limited time, you have to remember to take a break, try to pause and understand what you are doing, talk about it with your teammates, in order to solve a complex problem.
 
@@ -277,3 +278,5 @@ Here is a list of URLs that helped me solve this challenge.
 - https://github.com/mikepound/enigma : The code from the Computerphile video
 - https://git.step.polymtl.ca/romain/googlectf-enigma : My Git repository
 - https://translate.google.com/ : A website useful when trying to understand german
+
+I would also like to thank [PolyHx](https://cyber.polyhx.polymtl.ca/) for inviting me in their CTF team, [Polytechnique Montréal](https://polymtl.ca/) for giving me access to countless academic papers online, and Jimmy Bell for helping me translate my German plaintext into understandable text.
-- 
GitLab