feat: close the dCode / CrypTool 2 coverage gaps - #7
Merged
Conversation
A capability audit against dCode and CrypTool 2 (docs/gap-analysis.md) found four real holes and one CLI-surface gap. All five are closed. Every cipher is validated against a published vector before its cracker is trusted, and every cracker is plant-gated on settings it planted itself. New cipher types: * polybius — existed as PolybiusSquare inside 22 files but was not a registry entry, so `butt encode polybius` did not work. Solved outright: each coordinate pair is one plaintext letter, so relabelling turns it into the monoalphabetic problem the substitution solver already handles. * collon — the last missing 5x5 grid cipher. Annealing the square (the obvious attack) scored 0/5 in 45s; the ciphertext can only contain ten distinct letters, which makes it another monoalphabetic solve. 5/5 in 1.7s. * ubchi — WWI German double columnar reusing one key. The reuse is the weakness: widths 2..8 are under 46000 orders, so the permutation is enumerated. * chaocipher — Byrne's dynamic alphabets; matches Exhibit 1 exactly. crack returns [] by design: one wrong cell corrupts the whole remaining decrypt, so a nearly correct key scores like a random one and there is no gradient to climb. * m94 — Jefferson cylinder with the documented 25-disk table. Positions j and j+width share a disk, making the disk order a bipartite assignment solved exactly by Hungarian plus an n-gram climb: a full 25-disk order from 228 letters in <1s. * enigma — M3, rotors I-VIII, reflectors B/C, rings, plugboard. Matches AAAAA -> BDZGO and the canonical 26-letter output. crack is Gillogly's three phases; a 60-rotor-order sweep runs in ~2.5 min. buttcrack.wrappers — the transport layer a puzzle wraps around its cipher, wired into `butt transform`: repeating-key XOR with key-length recovery, base32/85/N, ROT47/5/18, keyboard geometry, phone keypad, tap code, NATO, Braille, and a generic Transcriptor. New flags: --xor, --apply, --wrap, --transcribe, --list-wrappers. stats --autocorrelation / --friedman — both computations already existed but were unreachable from the CLI and ungated. Exposing them showed neither was fit to report, and both had been feeding diagnose and cipher_id all along: * Scoring lags against the 1/26 floor makes every lag significant for monoalphabetic or transposed text, so a harmonic search always found a period. Now gated on IoC and reported as a refusal. 4/4 false positives removed. * Ranking a period by its own lag is backwards — English is anti-correlated at distance 2-3, so a true period-2 key reads z<0 at lag 2 while lags 4, 6, 8 spike. Plant gate 3/12 -> 18/19. * A key repeating a letter d apart makes lag d genuinely coincide, so candidate_periods reports the ladder instead of one confidently wrong number. Also hardened: XOR key length is chosen by a length-penalised quadgram score (raw fitness rises monotonically with key length, so the winner was always max_keysize), and letters-in/letters-out wrappers must read as English before being reported. The word-length leak gate now covers 10 ciphers instead of 2, with a matching assertion for the coordinate ciphers whose output is digits. Not implemented, with reasons in the wrappers docstring: ROT8000, PGP word list, periodic table, DTMF, semaphore, pigpen. Enigma and Chaocipher are excluded from `auto` because their searches take minutes, not the seconds `auto` budgets. Tests: 970 fast tests pass; 179 are new. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI's lint gate was failing on this branch: two I001 unsorted-import blocks (ciphers/__init__.py, ciphers/collon.py) and five files whose compact multi-entry dict/expression layout ruff format rejects. Formatting only — no behavior change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159mM39E2XA2ExfLsB1VUXW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.