Devlog #11
Last devlog ended with me calling statistics-only scoring the last fake thing in the cracker, and promising the real attack. This is that
The actual attack
A crib is a guessed fragment of plaintext — operators were creatures of habit, and words like “Meldung” (report) show up in everything. With a crib, the cracker stops scoring vibes entirely: every candidate setting decrypts the text, and the crib either appears in it letter-for-letter or it doesn’t. Six exact letters out of 17,576 start positions leaves one setting standing. The five short intercepts that statistics couldn’t touch now each carry a crib — FUNKEN, MORGEN, STEINECKE (the Germans really did sign Steinecke twice) — and all of them break in under a second.
One historical filter made it in: a letter never encrypts to itself, so a crib can only sit where no letter collides with the ciphertext. Fixed-offset guesses get rejected on that rule before the search even runs.
The answer that was wrong and right
The fun started in testing. One intercept’s documented start position is SWV, but my cracker’s top hit came back RVV — and RVV decrypts the message perfectly. Letter for letter, not just the crib window. I was convinced my engine was broken, so I compiled the reference C++ natively and compared: identical output on both. It’s not a bug. This key’s middle rotor sits exactly on its notch, so the famous double-step kicks the left rotor forward on the very first keypress — (R,V,V) and (S,W,V) converge to the same machine state before a single letter is encrypted. Two daily keys, one message. The codebreakers knew this class of equivalent settings; I rediscovered it by being confused for an hour.
Next up
The guided demo — the machine types, X-rays its own wiring, and cracks its own message while a first-time visitor watches.
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.