Wikijunior:Raspberry Pi/Raspberry Pi Enigma Machine
Presentation
editGCHQ and Raspberry Pi Foundation CC-BY-SA 4.0
Based on the Raspberry Pi OctoPi tutorial: https://projects.raspberrypi.org/en/projects/octapi-brute-force-enigma
What is the Enigma machine?
editAn Enigma machine is a device used for encrypting and decrypting messages. It was developed in the early 20th century and was used extensively by the Germans during World War II to encode their military communications.
The Enigma machine was famously broken by Alan Turing and his team at Bletchley Park, who developed techniques for cracking the Enigma code. This played a crucial role in the Allied victory in World War II, as it allowed them to intercept and decode important messages sent by the Germans.
How does the Engima machine work?
editHow does an Enigma machine work? on YouTube
The Enigma machine consists of:
- a keyboard for typing in the message
- a series of rotors that perform the encryption and decryption
- a reflector that bounces the electrical current back through the rotors in the opposite direction
The rotors can be set in different positions, allowing for a large number of possible combinations and making it difficult for an attacker to decode the message.
Worksheet
editConsulting your Enigma settings sheet, you find out that the settings for today are as follows:
rotors | ring settings | plug board settings | rotor start |
---|---|---|---|
IV I V | 20 05 10 | SX KU QF UN JG TC LA WM OB ZF | FNZ |
Decrypt a message
editWhat is the decrypted message?
editHere is the secret message: GON XXLXYFQNZIK
- Open Python 3, then open the file called
decrypt.py
- Type in the chosen rotors between the green quote marks
''
next tochosen_rotors
. - Now type in the letters for the rotor start position between the green quote marks
''
next torotor_start
. - Type in the message key
GON
between the green quote marks''
next tomessage_key
. - Type in the plaintext which is the secret message
XXLXYFQNZIK
. - Run the program by pressing the F5 key (say yes to saving).
Can you decrypt this message?
editUse the same Enigma settings but don’t forget to change the message key: LJE OIVGWVHOVHKAU
Encrypt a message
edit- Open Python 3, then open the file called
encrypt.py
- Type in the chosen rotors and the rotor start position again from the settings sheet
- Type in the message key
BFR
between the green quote marks' '
next tomessage_key
. - Run the program and check it works – the resulting cipher text should be
XXLXYFQNZIK
for the plain textRASPBERRYPI
.
Now it’s time to encrypt your own message!
- Choose a different three letter
message_key
and type it in - Choose a different plaintext message and type it in. Make sure there are no spaces!
- Run the program, then write down the encrypted key and the cipher text and give it to someone else to decrypt
Challenge
editDecrypt this message: GED HYZFQOOVVBBKBWPDZLSL
Brute force attack
editYou need to know the Enigma settings to be able to decrypt the message!
Here are today's settings. Unfortunately, someone has spilt some ink on the rotor settings 😟
rotors | ring settings | plug board settings | rotor start |
---|---|---|---|
21 15 16 | KL IT PQ MY XC NF VZ JB SH OG | POW |
Crib text is where you know both the plain text and the cipher text.
Crib text: WEATHER
Cipher text: VZTLMPU
Can you decrypt this message using a brute force attack if you know the crib text and part of the settings?
VZTLMPUSLKTEXYWZWKXDOTT
Brute force attack
edit- Open Python 3, then open the file called
bruteforce.py
. - Type in the crib text and the corresponding cipher text.
- Run the brute force attack to find the rotors and the message key.
Decrypt the message
edit- Now open the
decrypt.py
program you used before. - Type in the
rotor start
setting, and this time you will need to type in the ring and plug board settings from the settings sheet as well. - Type in the
chosen rotors
you found via the brute force attack. - This time we already know the decrypted message key. Find this line of code:
decrypted_message_key = machine.process_text(message_key)
.
Change it to say decrypted_message_key = '???'
where ???
is the three-letter key you found in the brute force attack.
- What is the secret message?
Final challenge
editDHPCMHCQ PXE
18/05/18
ZOC EJDTLFHR BT UKW.
Setup
editThis tutorial uses the py-enigma module by Brian Neal to provide the Enigma machine functionality.
You can install a copy of py-enigma on your Raspberry Pi (or your computer) by running this command from the Terminal:
sudo pip3 install py-enigma
Further reading
editThe Wikijunior World War II book has a section on the Enigma machine which goes into a lot of detail on how it worked.
The best place to learn about the Enigma machine is by visiting Bletchley Park near Milton Keynes in the United Kingdom.
The Imitation Game (2014) is a film starring Benedict Cumberbatch as Alan Turing who cracks the Enigma machine. The film is age-rated 12 (PG-13 in the USA), so it's for older children and adults.
The Raspberry Pi Foundation recommends the biography Dilly — The Man Who Broke Enigmas (2010, ISBN 9781906447151) by Mavis Batey. The book is about Alfred Dillwyn Knox who was Britain's Chief Cryptographer during World War II.
Files
editThe original PDFs for this tutorial are available on Wikicommons:
encrypt.py
editfrom enigma.machine import EnigmaMachine
chosen_rotors = '' # Type a space between each rotor e.g. V IV I
rotor_start = ''
message_key = ''
plaintext = 'RASPBERRYPI' # The message you want to encrypt
print("You started with message key " + message_key + " and plaintext " + plaintext)
# Set up the Enigma machine
machine = EnigmaMachine.from_key_sheet(
rotors=chosen_rotors,
reflector='B',
ring_settings='20 5 10',
plugboard_settings='SX KU QP VN JG TC LA WM OB ZF')
# Set the initial position of the Enigma rotors
machine.set_display(rotor_start)
# Encrypt the message key (the three letters you chose)
encrypted_message_key = machine.process_text(message_key)
print("The encrypted message key is " + encrypted_message_key)
# Set the rotor start position to the UNENCRYPTED message key
machine.set_display(message_key)
# The result
ciphertext = machine.process_text(plaintext)
print("The cipher text is: " + ciphertext)
decrypt.py
editfrom enigma.machine import EnigmaMachine
chosen_rotors = '' # Type a space between each rotor e.g. V IV I
rotor_start = ''
message_key = ''
plaintext = '' # The message you want to decrypt
print("You started with message key " + message_key + " and plaintext " + plaintext)
# Set up the Enigma machine
machine = EnigmaMachine.from_key_sheet(
rotors=chosen_rotors,
reflector='B',
ring_settings='20 5 10',
plugboard_settings='SX KU QP VN JG TC LA WM OB ZF')
# Set the initial position of the Enigma rotors
machine.set_display(rotor_start)
# Decrypt the message key
decrypted_message_key = machine.process_text(message_key)
print("The decrypted message key is " + decrypted_message_key)
# Set the rotor start position to the DECRYPTED message key
machine.set_display(decrypted_message_key)
# The result
ciphertext = machine.process_text(plaintext)
print("The cipher text is: " + ciphertext)
bruteforce.py
editcribtext = ""
ciphertext = ""
# All possible combinations of rotors
rotors = [ "I II III", "I II IV", "I II V", "I III II",
"I III IV", "I III V", "I IV II", "I IV III",
"I IV V", "I V II", "I V III", "I V IV",
"II I III", "II I IV", "II I V", "II III I",
"II III IV", "II III V", "II IV I", "II IV III",
"II IV V", "II V I", "II V III", "II V IV",
"III I II", "III I IV", "III I V", "III II I",
"III II IV", "III II V", "III IV I", "III IV II",
"III IV V", "IV I II", "IV I III", "IV I V",
"IV II I", "IV II III", "IV I V", "IV II I",
"IV II III", "IV II V", "IV III I", "IV III II",
"IV III V", "IV V I", "IV V II", "IV V III",
"V I II", "V I III", "V I IV", "V II I",
"V II III", "V II IV", "V III I", "V III II",
"V III IV", "V IV I", "V IV II", "V IV III" ]
def find_rotor_start( rotor_choice, ciphertext, cribtext ):
from enigma.machine import EnigmaMachine
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
machine = EnigmaMachine.from_key_sheet(
rotors=rotor_choice,
reflector='B',
ring_settings='21 15 16',
plugboard_settings='KL IT PQ MY XC NF VZ JB SH OG')
# Search over all possible rotor starting positions
for i in range(len(alphabet)): # search for rotor 1 start position
for j in range(len(alphabet)): # search for rotor 2 start position
for k in range(len(alphabet)): # search for rotor 3 start position
# Generate a possible rotor start position
start_pos = alphabet[i] + alphabet[j] + alphabet[k]
# Set machine initial starting position and attempt to decrypt
machine.set_display(start_pos)
plaintext = machine.process_text(ciphertext)
#print("Plain: " + plaintext + ", Crib: " + cribtext)
# Check if decrypted text is the same as the crib text
if (plaintext == cribtext):
return( rotor_choice, start_pos )
return( rotor_choice, "null" )
print("Brute force crypt attack on Enigma message " + ciphertext)
print("Crib text " + cribtext )
# Try all rotor settings
for rotor_setting in rotors:
print("Trying rotors " + rotor_setting)
rotor_choice, start_pos = find_rotor_start( rotor_setting, ciphertext, cribtext )
if (start_pos != "null"):
print("Machine setting found!")
print("Rotors: " + rotor_choice)
print("Message key: " + start_pos)
print("Using crib " + cribtext)
exit(0)