A classical, poly-alphabetic, stream cipher. Encrypts a Baudot-coded plaintext bit stream into 5 ciphertext bit streams. Each bit is masked by a fresh keystream bit, so ciphertext symbol frequencies are flattened.
Implemented by the Lorenz machine, an electromechanical inline cipher attachment built by C. Lorenz AG for the German Army high command in World War 2. It sat between a teleprinter and the transmission line, enciphering each character as it was typed and deciphering at the far end. The Allies called the machine and its traffic Tunny.
Baudot Code
A fixed-width (5 bits) character encoding, invented by Émile Baudot in 1870 for printing telegraphs.
Fixed width is the key property. The receiver slices the bit stream every 5 bits to find character boundaries, unlike the variable-length symbols of Morse code. This is why the Lorenz machine treats plaintext as a clean stream of 5-bit units.
A 5-bit code spans only symbols, too few for letters, digits, punctuation, and control codes. 2 of the 32 codes are mode switches rather than characters.
- Letters shift
Following codes are read as letters. - Figures shift
Following codes are read as digits and symbols.
The machine holds the current mode. The same 5-bit pattern means different characters in the 2 modes, so the effective alphabet is about 60 symbols.
Encryption
Each 5-bit Baudot code is XOR-ed with a 5-bit random sequence, generated by 12 shift registers in 3 groups:
- 5 registers, lengths 41, 31, 29, 26, 23.
- 5 registers, lengths 43, 47, 51, 53, 59.
- 2 registers, lengths 61, 37.
Registers
A register is a wheel of pins, 1 per position around its length, each fixed to or . At each tick it outputs the bit at its current position, then advances by 1 position, wrapping at its length.
pairs with for each of the 5 Baudot bit positions, giving 5 parallel lanes.
At each clock tick :
- for .
- , and the registers advance.
- advances every tick, and conditionally triggers to advance.
- conditionally triggers the registers to advance.
- Output .
Key space:
Decryption
The receiver starts the 12 registers from the shared settings and runs the same clocking, producing the identical keystream . XOR is its own inverse, so XOR-ing each 5-bit ciphertext code with returns the plaintext code.
Attacking
The keystream is fully determined once the register settings are fixed, so 2 messages sent in depth, under the same settings, break the cipher.
- XOR the 2 ciphertexts. The keystream cancels, leaving , the XOR of the 2 plaintexts.
- Slide known language fragments against to separate the 2 plaintexts, then XOR either plaintext with its ciphertext to recover the keystream.
- The registers stall on many ticks, so the keystream carries structure. Statistical tests on the ciphertext bits expose the register lengths and starting positions without a depth.
Worked Example
One Baudot character A, code , with keystream bits for this tick.
Encryption XORs the code with the keystream bit by bit.
Ciphertext code is .
Decryption XORs the ciphertext with the same keystream bits.
Recovered code is , the character A.
For the attack, a second message encrypts code at this tick under the same settings, giving ciphertext .
The keystream has cancelled, leaving the XOR of the 2 plaintext codes.