Weymouth, UKSoftware, security, and things built to understand themUpdated 11 November 2026

Tom Taylor

I build software people rely on.

The Lab

Lab · Cipher machine simulator

Lorenz SZ40

A simulator of the WWII German teleprinter cipher machine that models its twelve wheels rather than faking the output. I rebuild it every time I learn a new language.

Lorenz SZ40 in action

The Lorenz SZ40 was the cipher attachment the German high command used for teleprinter traffic in the Second World War. Breaking it at Bletchley Park drove the building of Colossus, one of the first electronic computers. At university I was set the task of rebuilding it in software. I enjoyed it so much that it became my “hello, world”: whenever I learn a new language or platform, I build the Lorenz machine in it.

How the machine works

A teleprinter sends each character as five on/off signals, the Baudot code. The SZ40 hides each character by combining it with five bits of key, one bit per channel, using exclusive-or. Doing the same again with the same key gets the original back, so one machine both encrypts and decrypts.

The key comes from twelve wheels with pins that are set up in advance:

  • Five chi wheels step forward on every character.
  • Five psi wheels step only some of the time, and all together.
  • Two motor wheels decide when the psi wheels step. The larger one steps every character, and it drives the smaller one, which in turn lets the psi wheels move.

Each key bit is the chi wheel’s pin XOR the psi wheel’s pin for that channel. Because the psi wheels move irregularly, the key never settles into a simple repeating pattern. My simulators model each wheel, its pins and the stepping rules directly, rather than approximating what the machine produced, so the same wheel settings give the same result in every version.

One machine, many languages

The C++ console version: a text menu for setting wheel positions and encrypting a message
The original C++ version, a console app with a keyboard-driven menu.
  • C++ (university). A console application with no libraries beyond the C++ standard library. It has a keyboard-driven menu, and it can also run straight from the command line for scripting.
  • Windows Forms. My first desktop GUI application. It isn’t pretty, and with no multithreading it is slow, but it taught me the forms model I would later use every day at work.
  • Delphi (2018). When I joined a company that writes most of its software in Delphi, the Lorenz machine was the first thing I wrote in it. Object Pascal’s readability and memory management made it the cleanest version so far.
  • Android (2019). A full app in Java, published on Google Play. See below.
  • TypeScript. A Node version, written while moving into web development.
The Windows Forms version encrypting text, with the wheel positions shown changing
The Windows Forms version.

The Android app

The Android app, with a grid of wheel values above options for real-time simulation and its speed
The Android app, showing the wheel values as the machine works.

The Android version was one of the first hobby apps I put on a store, and the first I earned money from (a little). It added things the desktop versions never had:

  • A speed control. A modern phone encrypts a message instantly, so you can slow the machine down and watch the wheels turn one character at a time.
  • Import and export. You can save encrypted messages along with the pin settings, so someone else can load them and read them on another device.
  • Android features. It plugs into the system share sheet, and saved messages can be locked behind biometric authentication.
  • A free and paid tier. Building in-app purchases, privacy policies and store listings taught me how much work sits around an app, beyond the code itself.

It also made me take threading seriously. Phones have many slow cores, and the simulation runs off the main thread so the interface stays smooth.

Why I keep rebuilding it

Porting the same well-understood program is the fastest way I know to learn a platform properly. The problem stays fixed, so everything I learn is about the language: how it handles memory, structure, user interfaces and tooling.