Wikijunior:Raspberry Pi/Raspberry Pi Enigma Machine

Presentation edit

 
 
Bletchley Park

GCHQ 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? edit

An 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? edit

How 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 edit

Consulting your Enigma settings sheet, you find out that the settings for today are as follows:

rotorsring settingsplug board settingsrotor start
IV I V20 05 10SX KU QF UN JG TC LA WM OB ZFFNZ

Decrypt a message edit

What is the decrypted message? edit

Here is the secret message: GON XXLXYFQNZIK

  1. Open Python 3, then open the file called decrypt.py
  2. Type in the chosen rotors between the green quote marks '' next to chosen_rotors.
  3. Now type in the letters for the rotor start position between the green quote marks '' next to rotor_start.
  4. Type in the message key GON between the green quote marks '' next to message_key.
  5. Type in the plaintext which is the secret message XXLXYFQNZIK.
  6. Run the program by pressing the F5 key (say yes to saving).

Can you decrypt this message? edit

Use the same Enigma settings but don’t forget to change the message key: LJE OIVGWVHOVHKAU

Encrypt a message edit

  1. Open Python 3, then open the file called encrypt.py
  2. Type in the chosen rotors and the rotor start position again from the settings sheet
  3. Type in the message key BFR between the green quote marks ' ' next to message_key.
  4. Run the program and check it works – the resulting cipher text should be XXLXYFQNZIK for the plain text RASPBERRYPI.

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 edit

Decrypt this message: GED HYZFQOOVVBBKBWPDZLSL

Brute force attack edit

You 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 😟

rotorsring settingsplug board settingsrotor start
21 15 16KL IT PQ MY XC NF VZ JB SH OGPOW

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

  1. Open Python 3, then open the file called bruteforce.py.
  2. Type in the crib text and the corresponding cipher text.
  3. Run the brute force attack to find the rotors and the message key.

Decrypt the message edit

  1. Now open the decrypt.py program you used before.
  2. 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.
  3. Type in the chosen rotors you found via the brute force attack.
  4. 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 edit

DHPCMHCQ PXE

18/05/18
ZOC EJDTLFHR BT UKW.

Setup edit

This 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 edit

The 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 edit

The original PDFs for this tutorial are available on Wikicommons:

Enigma-presentation.pdf edit

Enigma-worksheet.pdf edit

encrypt.py edit

from 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 edit

from 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 edit

cribtext = ""
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)