Enigma Coding and Decoding

There are various programs available online for coding and decoding Enigma messages. We have found one of the easiest to setup and use was devised by Ole Kröger.

https://github.com/Wikunia/Enigma.jl

https://opensourc.es/blog/enigma-and-bombe

YouTube: Enigma: Endless possibilities is not enough

YouTube: How to crack the Enigma cipher?


Setup

Enigma.jl is written using the Julia programming language which can be downloaded here:

https://julialang.org/downloads/

When you run Julia you will see the welcome screen…

Enigma.jl is an official Julia package so installing it is really easy. Just type…

] add Enigma

Note: The square right bracket switches the program into package mode.  To return to the julia> prompt, either press backspace when the input line is empty or press Ctrl+C.

You only need to install the program once. Then, to get started, load the Enigma program with…

using Enigma

and initialise the setup…

enigma = EnigmaMachine()

Encoding

To code a message you need to first define the machine settings. Choose any 3 of the possible 5 rotors (set from left to right)…

set_rotors!(enigma, 4,2,1)

Then define the initial rotor positions (again from left to right)…

set_rotor_positions!(enigma, 10,20,4)

The A, B or C reflector (UKW) can be selected by entering value 1,2 or 3…

set_ukw!(enigma::EnigmaMachine, 2)

There are two different ways to set the plugs in the plugboard. Either using the letter pairs…

set_plugboard!(enigma, "AC BE GZ JK ML")

or as integer pairs…

set_plugboard!(enigma, [(1,2),(3,5)])

Finally, define the message to be encoded…

message = "Secret message"

and run Enigma to get the result…

encoded = encode!(enigma, message)

Decoding

If you already know all the settings then you can set them as shown above and simply run…

decoded = decode!(enigma, encoded)

Otherwise you will need to use a “hint”, which is a known (or suspected) word in the coded message. The Bletchley Park codebreakers called this a crib. The longer the word the better, and if you have additional information or guesses you can use them to refine the search. For example, if we are assuming that the word “weatherreport” is part of the message and appears somewhere in the first 45 characters, we would set the crack_message and hint variables using…

crack_message = "HGHXI AGYEY NDIFW PRMDD QSMJG DCAKP FMIZL RVQIZ WRLJM"
hint = "weatherreport"

Then initialise the bombe…

bombe = BombeMachine(crack_message, hint)

and start the decoding program…

enigmas = run_cracking(bombe; log=false)

If the program finds some results it will return the rotors used with their settings, the ukw and the plug combinations…

1 Enigma machine(s):
- III, II, I | 24 24 1 | UKW: B | AB CD EF GH IJ KL MN OP QR ST

To see the possible messages you then need to run…

for enigma in enigmas
encoded = encode!(enigma, crack_message)
println(encoded)
end

Sometimes the hint is not enough to get the correct solution because some plugs can be removed from the actual setting and still produce the hint. If you can’t guess the message from the results generated, you can generate the extra plugs and test all possible combinations. Of course this will take a lot longer.

To set this option use…

enable_ambiguous!(bombe)

and then run the process again with…

enigmas = run_cracking(bombe; log=false)

If you want to narrow down the search parameters you can define some of the settings. You might know that rotor V is not used and the left most rotor is III…

set_possible_rotors!(bombe, 3,1:4,1:4)

Maybe you also know that the rotor position of III is between 1 and 5…

set_possible_rotor_positions!(bombe, 1:5,1:26,1:26)

or that the ukw used was A…

set_possible_ukws!(bombe, 1)

and the hint position starts somewhere in the first 5 places…

set_possible_hint_positions!(bombe, 1:5)
enigmas = run_cracking(bombe; log=false);

Code Reference

EnigmaMachine

EnigmaMachine()
EnigmaMachine(r1::Int,r2::Int,r3::Int,ukw::Int)
set_rotors!(enigma::EnigmaMachine, r1, r2, r3)
set_ukw!(enigma::EnigmaMachine, ukw)
set_rotor_positions!(enigma::EnigmaMachine, p1::Int, p2::Int, p3::Int)
set_plugboard!(enigma::EnigmaMachine, setting::Vector{Tuple{Int,Int}})
set_plugboard!(enigma::EnigmaMachine, setting::String)
encode!(enigma::EnigmaMachine, s::String; input_validation=true, output_style=:enigma)
decode!(enigma::EnigmaMachine, s::String; input_validation=true, output_style=:enigma)
enigma_styled_text(text::String)

Bombe

BombeMachine(secret::String, hint::String)
enable_ambiguous!(bombe::BombeMachine)
disable_ambiguous!(bombe::BombeMachine)
set_possible_rotors!(bombe::BombeMachine, rotor_1, rotor_2, rotor_3)
set_possible_rotor_positions!(bombe::BombeMachine, rp1, rp2, rp3)
set_possible_ukws!(bombe::BombeMachine, ukws)
set_possible_hint_positions!(bombe::BombeMachine, hint_positions)
set_hint!(bombe::BombeMachine, hint::String)
set_secret!(bombe::BombeMachine, secret::String)
run_cracking(bombe::BombeMachine; log=true)