Skip to content

DCPRevere/enigma

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

enigma

A faithful, historically accurate Enigma M3 in your terminal — the cipher machine that scrambled Wehrmacht and Kriegsmarine traffic through the Second World War, rebuilt in TypeScript and rendered with ink.

Animated Enigma signal path: each keypress traced through the plugboard, rotors, reflector and back, with the lamp lighting and the ciphertext accumulating.

Every keypress, traced through the whole machine — enigma animate "ENIGMA". Type into a live one with enigma live.

This is a complete M3: rotors I–VIII, reflectors B and C (Umkehrwalze), the ring settings (Ringstellung), the plugboard (Steckerbrett), and — crucially — the correct double-stepping anomaly of the middle rotor. Like the real machine it is self-reciprocal: the same settings that encrypt a message decrypt it. Wirings are verified against Wikipedia and the Crypto Museum.

$ enigma HELLOWORLD
ILBDAAMTAZ

$ enigma ILBDAAMTAZ
HELLOWORLD

Encrypting is the default action — there is no separate decrypt command, because the Enigma is reciprocal: running ciphertext back through the same settings recovers the plaintext.


Install & quick start

Build and run

npm install
npm run build          # tsc -> dist/
./dist/cli.js HELLOWORLD

Dev usage (no build step)

npm run dev -- HELLOWORLD
# or directly:
npx tsx src/cli.tsx HELLOWORLD

Once built, if installed as a bin the tool is simply enigma. All examples below use enigma; substitute npx tsx src/cli.tsx (or npm run dev --) while developing.

You can also pipe text in on stdin:

echo "ATTACK AT DAWN" | enigma

Usage

enigma [text] [flags]              # encrypt/decrypt (default)
enigma <command> [text] [flags]

Commands

Command Description
enigma <text> Default. Encrypt/decrypt text (or stdin). One action — the Enigma is reciprocal, so the same settings that encrypt also decrypt.
enigma animate <text> Encrypt with the full animated signal-path visualization (TTY only).
enigma live Interactive: type and watch each keypress flow through the machine (TTY only).
enigma random Print a random valid machine setting (a key sheet).
enigma help Show help.
echo "text" | enigma Read from stdin when no text argument is given.

Flags

Flag Short Argument Default Description
--rotors -r <list> I,II,III Rotors left→right, chosen from IVIII, e.g. "I,II,III".
--reflector -u <B|C> B Reflector (Umkehrwalze).
--positions -p <letters> AAA Grundstellung / start position, e.g. "AAA".
--rings -g <letters|numbers> AAA Ringstellung / ring setting: letters "AAA" or, as on historical key sheets, numbers "01 14 21" (1 = A … 26 = Z).
--plugboard -k <pairs> none Steckerbrett pairs, e.g. "AB CD EF".
--speed -s <multiplier> 1 Animation speed (animate and live): 1 = normal, 2 = twice as fast, 0.5 = half speed.
--key-file <path> Load settings from a JSON key sheet.
--preset <name> Use a named preset: default, kriegsmarine, demo.
--json With random: print the key sheet as JSON, ready for --key-file.

Non-letter characters (spaces, digits, punctuation) pass through unchanged and, faithfully, do not advance the rotors — just as an operator would simply not press a key.

The number of letters in --positions and --rings must match the number of rotors, or the machine reports a friendly error. The same goes for unknown or duplicated rotors, an unknown reflector, and malformed or self-connecting plugboard pairs.


Examples

Round trip: encrypt, then decrypt to recover

Because the machine is reciprocal, feeding the ciphertext back through the same settings returns the plaintext.

$ enigma HELLOWORLD
ILBDAAMTAZ

$ enigma ILBDAAMTAZ
HELLOWORLD

Both runs use the default machine (-r I,II,III -u B -p AAA -g AAA, no plugboard) and each starts fresh from position AAA, so they cancel exactly. When you set a non-default start position, pass the same -p to recover the message.

A custom rotor / reflector / plugboard configuration

$ enigma "ATTACKATDAWN" \
    --rotors II,IV,V \
    --reflector C \
    --positions ABC \
    --rings DEF \
    --plugboard "AB CD EF"
IADZUDPSGFUI

$ enigma "IADZUDPSGFUI" \
    -r II,IV,V -u C -p ABC -g DEF -k "AB CD EF"
ATTACKATDAWN

A random key sheet

$ enigma random
┌──────────────────────────────────┐
│  ENIGMA M3 KEY SHEET             │
├──────────────────────────────────┤
│  Rotors     VIII I II            │
│  Reflector  UKW-B                │
│  Positions  CLE                  │
│  Rings      YYZ                  │
│  Plugboard  GV ME BX CS JQ       │
└──────────────────────────────────┘

Feed those settings straight in via the flags above — or generate the sheet as JSON and use it directly:

$ enigma random --json > key.json
$ enigma --key-file key.json "WEATHER REPORT"
YMKZKQG OWWLPQ
$ enigma --key-file key.json "YMKZKQG OWWLPQ"
WEATHER REPORT

The animated signal path

$ enigma animate A \
    --rotors II,IV,V --reflector C --positions ABC --rings DEF --plugboard "AB CD EF"

animate shows the electrical journey of each keypress in real time (see the animation at the top of this README). Every scrambling layer — the plugboard, each rotor, and the reflector — is drawn as its full 26-letter substitution, and you watch a single wire light up on the way down into the reflector, then the same tables light again on the way back up. The rotor windows spin as they step, and the lamp glows when the signal arrives. Use --speed to slow it down or speed it up (--speed 0.5 for half speed, --speed 3 for 3× faster).

Reading a rotor's table: the top row is the input alphabet A..Z; the bottom row is where each letter is wired. An amber marks the wire the signal took going in; a steel-blue marks the wire it takes coming back — the same table, traversed in reverse. The plugboard shows its pairs as a strip (A↔B C↔D), and the reflector highlights both ends of the pair it swaps (X↔J), which is what makes the machine reciprocal.

Interactive live mode

$ enigma live
$ enigma live --preset kriegsmarine --speed 2

live turns your terminal into a working Enigma you type into. Each key you press flows through the machine on screen — the rotors step, the signal traces its path, the lamp lights — while your plaintext and the accumulating ciphertext build up in two panels. You can also paste whole messages: every pasted letter runs through the machine in order, and the last one is animated. Backspace undoes a keystroke (the machine is rebuilt and the remaining text replayed, since a real Enigma can't step backwards), and Esc or Ctrl-C quits and prints the full transcript. It needs an interactive terminal (a TTY).


How it works

The signal path. Pressing a key sends current from the keyboard through the plugboard, then right-to-left through each rotor in turn, into the reflector, and back left-to-right out through the rotors, through the plugboard once more, and finally to a lamp. Every stage is a fixed permutation; the rotors' contribution changes because they rotate.

Stepping and the double-step anomaly. Before each keypress is encoded, the rotors advance. The rightmost rotor always steps. When a rotor sits on its turnover (notch) position, it carries the rotor to its left one step on the next press. The famous quirk: because the pawl engages the notch mechanically, when the middle rotor reaches its own turnover it advances both the left rotor and itself — so the middle rotor moves on two consecutive keypresses. This implementation reproduces that anomaly exactly.

Ring settings (Ringstellung). The ring rotates the internal wiring relative to the alphabet ring and the notch. It doesn't change which letter shows in the window, but it shifts where in the message the turnovers fall and offsets the substitution — a second layer of key material beyond the start positions.

The plugboard (Steckerbrett). Up to 13 disjoint letter pairs are swapped on the way in and again on the way out. It is an involution (if A↔B then B↔A), unplugged letters pass straight through, and it enormously enlarges the key space.

Why it's reciprocal. The reflector guarantees that the whole transform is its own inverse: if A encodes to I under some setting, then I encodes to A under the same setting. That is why one machine setting both encrypts and decrypts. The historical corollary — and a genuine cryptographic weakness — is that no letter can ever encode to itself, a fact the Bletchley Park codebreakers exploited relentlessly.


Library use

The core machine ships as a plain, dependency-free library through the package's main export:

import { EnigmaMachine } from 'enigma-cli';

const enigma = new EnigmaMachine({
  rotors: ['I', 'II', 'III'],
  reflector: 'B',
  positions: 'AAA',
  rings: 'AAA',
  plugboard: 'AB CD EF',
});

console.log(enigma.encode('HELLOWORLD')); // IKACBBMTBF (settings-dependent)

// Full signal path for a single keypress, for visualization:
const trace = enigma.traceChar('A');
console.log(trace.output, trace.windows, trace.stepped);

ROTORS, REFLECTORS, ALPHABET, and friends are also exported for building your own tooling.


Historical accuracy

This is a Wehrmacht/Kriegsmarine Enigma M3:

  • Rotors I–VIII. I–V are the army/air-force set; VI–VIII are the additional naval rotors (each with two turnover notches).
  • Reflectors B and C (Umkehrwalze B and C).
  • Entry wheel (Eintrittswalze): straight-through, as on the M3.
  • Ring settings, plugboard, and the middle-rotor double-step are all modelled.

All wirings and turnover positions are verified against Wikipedia — Enigma rotor details and the Crypto Museum wiring tables.

Rotor wirings and turnovers

The wiring is the forward substitution at zero orientation with ring setting A (Ringstellung 01). The turnover letter is the window position from which the rotor to the left is carried.

Rotor Wiring (A→Z) Turnover
I EKMFLGDQVZNTOWYHXUSPAIBRCJ Q
II AJDKSIRUXBLHWTMCQGZNPYFVOE E
III BDFHJLCPRTXVZNYEIWGAKMUSQO V
IV ESOVPZJAYQUIRHXLNFTGKDCMWB J
V VZBRGITYUPSDNHLXAWMJQOFECK Z
VI JPGVOUMFYQBENHZRDKASXLICTW Z, M
VII NZJHGRCXMYSWBOUFAIVLPEKQDT Z, M
VIII FKQHTLXOCBJSPDZRAMEWNIUYGV Z, M

Reflectors (Umkehrwalze)

Reflector Wiring (A→Z)
B YRUHQSLDPXNGOKMIEBFZCWVJAT
C FVPJIAOYEDRZXWGCTKUQSBNMHL

About

A beautiful, historically-accurate Enigma M3 machine for your terminal

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors