Cryptanalysis of Classical Ciphers
Imagine a Confederate telegraph clerk in 1863, encrypting troop movements with a keyword cipher. He believes it is unbreakable. A Union analyst, with nothing but pencil, paper, and patience, recovers the plaintext in an afternoon. No computer, no brute force over billions of keys. Just the systematic exploitation of a leaked statistical fingerprint. This is the central lesson of classical cryptanalysis: encryption that merely rearranges or substitutes symbols cannot hide the statistics of the underlying language. Statistics are enough to break it. Cryptanalysis matters because it defines what "secure" must mean. Every cipher in Classical Ciphers and Substitution — Caesar, monoalphabetic substitution, Vigenère — was eventually defeated. Not by exhaustive search, but by structural weaknesses that leak information about the key or plaintext. Understanding these attacks is not a historical curiosity. It is the reasoning template used today to evaluate any new cryptosystem. If a scheme preserves letter frequencies, repeats patterns predictably, or lets an attacker align ciphertext segments, it is vulnerable. This holds whether it was designed in 1500 or shipped in a 2024 firmware update. This article develops two classical but foundational attacks. Frequency analysis breaks monoalphabetic substitution by matching ciphertext letter frequencies against known language statistics. Kasiski examination (with the complementary index of coincidence) breaks polyalphabetic ciphers like Vigenère. It first recovers the key length, then reduces the problem to several independent frequency-analysis attacks. Together they show a recurring cryptanalytic pattern: exploit invariants that survive encryption, then divide a hard problem into easy sub-problems. By the end, you will be able to trace both attacks step by step on real ciphertext. You will understand precisely why they succeed, in terms of entropy and redundancy of natural language. You will also see why the only real fix is to destroy the statistical relationship between plaintext and ciphertext altogether. This idea leads directly into Perfect Secrecy and the One-Time Pad.
- Monoalphabetic substitution preserves letter frequencies; matching ciphertext frequency counts to known language statistics (e.g., English 'E' ≈ 12.7%) recovers the key.
- Frequency analysis is a statistical matching attack: it needs no brute force, just enough ciphertext and a reference frequency table.
- Vigenère resists simple frequency analysis because each ciphertext letter's shift depends on the key letter — but repeating the key reintroduces periodicity.
- Kasiski examination finds repeated ciphertext substrings; the GCD of their distances estimates the key length.
- The index of coincidence independently confirms key length by measuring how "monoalphabetic-like" each subsequence looks.
- Once the key length is known, Vigenère splits into independent Caesar ciphers, each broken by ordinary frequency analysis — the core lesson feeding into Perfect Secrecy and the One-Time Pad.
Any cipher that leaves statistical patterns of the plaintext detectable in the ciphertext can be broken by exploiting those patterns, no matter how large its keyspace is.
The idea
Cryptanalysis is the study of recovering plaintext or key from ciphertext without legitimate access to the key. Classical cryptanalysis of substitution and polyalphabetic ciphers rests on a single observation: natural language is redundant. English text is not a uniform random sequence over 26 letters; it has a highly skewed letter-frequency distribution, characteristic digrams and trigrams ("TH", "THE", "ING"), and repeated words. A cipher is secure against statistical attack only if it destroys this redundancy in the ciphertext; classical ciphers do not. A monoalphabetic substitution cipher applies a single fixed bijection from the plaintext alphabet to itself: every occurrence of a plaintext letter maps to the same ciphertext letter . Because is a bijection, the multiset of letter frequencies is merely permuted, not altered. If 'E' is the most common plaintext letter, then will be the most common ciphertext letter. This is the invariant frequency analysis exploits. A polyalphabetic cipher such as Vigenère uses a repeating key of length : the -th plaintext letter is shifted by the key letter at position . This appears to defeat frequency analysis, since the same plaintext letter can map to different ciphertext letters depending on position. But the key repeats with period , so the sub-sequence of ciphertext letters at positions was all encrypted with the same Caesar shift — it is monoalphabetic. Kasiski examination locates the period by finding repeated plaintext patterns (which, because of the periodic key, produce repeated ciphertext patterns separated by multiples of ). The index of coincidence provides an independent, frequency-based estimate of . Once is known, the ciphertext splits into Caesar ciphers, each breakable by ordinary frequency analysis.
How it works
Part 1 — Frequency analysis of monoalphabetic substitution. The attacker has ciphertext and a reference frequency table for the assumed plaintext language (e.g., standard English single-letter, digram, and trigram frequencies). The attack proceeds as a constrained search guided by statistics rather than brute force over all keys. ``` ALGORITHM FrequencyAnalysis(ciphertext C, reference_freqs R) // Step 1: Tabulate ciphertext statistics count[26] <- 0 for each letter c in C: count[index(c)] <- count[index(c)] + 1 n <- length(C) freq[i] <- count[i] / n for i in 0..25 // Step 2: Rank letters by frequency ciphertext_rank <- sort letters 0..25 by freq[] descending reference_rank <- sort letters by R[] descending // e.g. E,T,A,O,I,N,S,H,R,D,L,U,... // Step 3: Initial guess -- align ranks mapping <- {} for i in 0..25: mapping[ciphertext_rank[i]] <- reference_rank[i] // Step 4: Refine using digram/trigram and structural evidence repeat candidate_plain <- apply(mapping, C) score <- LanguageScore(candidate_plain, R) // log-likelihood vs reference n-grams for each pair of letters (a, b) in mapping's range: trial_mapping <- swap(mapping, a, b) trial_plain <- apply(trial_mapping, C) trial_score <- LanguageScore(trial_plain, R) if trial_score > score: mapping <- trial_mapping score <- trial_score improved <- true until no improvement in a full pass over all swaps return mapping, apply(mapping, C) ``` The initial rank-alignment step (Step 3) is usually wrong in detail — English frequency order is a statistical tendency, not a law, and short ciphertexts especially will deviate. The refinement loop (Step 4) is a local-search (hill-climbing) step over the space of letter-swaps, scored against a language model, typically using single-letter frequencies plus digram/trigram frequencies or common short words ("THE", "AND", "TO") as anchors. A human cryptanalyst does this by hand, using distinctive patterns: doubled letters, a lone one-letter word (almost certainly "A" or "I" in English), and word-boundary shapes if spacing survives.
Part 2 — Kasiski examination and the index of coincidence for Vigenère. Kasiski's method exploits the fact that identical plaintext substrings encrypted at positions that differ by a multiple of the key length produce identical ciphertext substrings. ``` ALGORITHM KasiskiExamination(ciphertext C, min_len = 3) distances <- [] // Step 1: find repeated substrings of length >= min_len positions <- map from substring -> list of start indices for i in 0 .. length(C) - min_len: s <- C[i .. i+min_len-1] append i to positions[s] // Step 2: collect pairwise distances between repeats of the same substring for each substring s with positions list P where |P| >= 2: for each pair (p1, p2) in P, p1 < p2: distances.append(p2 - p1) // Step 3: candidate key length = a common divisor of many distances candidates <- {} for d in distances: for f in factors(d): if f >= 2: candidates[f] <- candidates[f] + 1 m_guess <- argmax_f candidates[f] // most frequently occurring factor return m_guess ``` ``` ALGORITHM IndexOfCoincidence(text T) n <- length(T) count[26] <- letter counts in T IC <- sum over i of count[i](count[i]-1) / (n(n-1)) return IC ALGORITHM ConfirmKeyLength(ciphertext C, max_m) best_m, best_score <- 1, -infinity for m in 1 .. max_m: avg_IC <- 0 for j in 0 .. m-1: subsequence <- C[j], C[j+m], C[j+2m], ... avg_IC <- avg_IC + IndexOfCoincidence(subsequence) avg_IC <- avg_IC / m // English monoalphabetic IC ~ 0.065-0.070; random ~ 0.038 score <- -(avg_IC - 0.0665)^2 if score > best_score: best_m, best_score <- m, avg_IC return best_m ``` ``` ALGORITHM BreakVigenere(ciphertext C) m <- KasiskiExamination(C) // or ConfirmKeyLength(C, max_m) key <- array of length m for j in 0 .. m-1: subsequence <- C[j], C[j+m], C[j+2m], ... // monoalphabetic (Caesar) slice best_shift, best_score <- 0, -infinity for shift in 0 .. 25: decrypted <- ShiftBack(subsequence, shift) score <- ChiSquaredFit(decrypted, EnglishFrequencies) // lower is better -> use -score if -score > best_score: best_shift, best_score <- shift, -score key[j] <- best_shift plaintext <- decrypt C using repeating key `key` return key, plaintext ``` The chi-squared statistic in the innermost loop compares the observed letter distribution of a candidate decryption against expected English frequencies:
where is the observed count of letter and is the expected count under English frequency . The correct shift minimizes .
Complexity & correctness
Frequency analysis (monoalphabetic).
- Time: Tabulating counts is for ciphertext length . The rank-alignment initial guess is . The refinement (hill-climbing over swaps) examines letter-pairs per pass and each scoring pass costs , so each full refinement pass is ; the number of passes until convergence is small in practice (a constant in the tens), giving an overall practical running time of to — linear in ciphertext length for fixed alphabet size. This is exponentially cheaper than the brute-force key search.
- Space: for counts and mapping, to hold the text.
- Correctness intuition: Because substitution is a bijection on the alphabet, the ciphertext letter frequency vector is a permutation of the plaintext letter frequency vector (up to sampling noise for finite ). As , the empirical frequency of each letter converges (by the law of large numbers) to its true language probability, so the rank order of ciphertext frequencies converges to the rank order of applied to the true language rank order. For finite, realistic (a few hundred letters), rank order is usually only approximately preserved, which is precisely why the hill-climbing refinement step (using digrams/trigrams, which carry more bits of distinguishing information per character) is needed to correct errors the crude single-letter ranking makes.
Kasiski examination + index of coincidence.
- Time: Finding all repeated substrings of length naively is (all pairs of starting positions), or average with a hash map keyed by substring, as in the pseudocode. Computing all pairwise distances among repeats of a given substring is for occurrences, but is small in practice, so total cost is dominated by to in the worst (pathological) case. The index-of-coincidence confirmation loop tries candidate lengths, each costing , for total — trivial for realistic (say, up to 20).
- Space: to index substrings and positions.
- Once is fixed: breaking each of the Caesar sub-streams costs per stream (26 shift trials, each an chi-squared computation), so total across all streams — again linear in .
- Correctness intuition: If the key has period and the same plaintext substring of length appears at two positions whose difference is a multiple of , the key letters aligned with each occurrence are identical, so the ciphertext substrings are identical. Repeats at distances not a multiple of can occur by coincidence but are statistically rarer for (a random trigram match probability is roughly per position pair). Hence the true period divides the overwhelming majority of observed repeat-distances, and emerges as the most frequent common factor — this is exactly why the algorithm takes the argmax over factor frequency rather than trusting a single repeat.
The index of coincidence formalizes this differently: for a random 26-letter alphabet uniformly distributed, . For natural English (a fixed monoalphabetic shift of English), –, because skewed frequencies make two random letters more likely to coincide. Splitting ciphertext into subsequences at the true period yields subsequences that are each a straightforward Caesar-shifted English text, so each has . Splitting at the wrong period mixes multiple Caesar-shifted alphabets together, which smears the distribution toward uniform, dragging toward . The algorithm's scoring function (distance from ) is therefore a legitimate discriminator between correct and incorrect period guesses.
Tradeoffs and honesty about limits. Both attacks are attacks on statistics, so they degrade gracefully with less data: frequency analysis on a 40-letter ciphertext is unreliable (frequency estimates are noisy), while on 2,000 letters it is essentially deterministic. Kasiski examination needs enough repeated substrings to triangulate the period; short texts or very long keys (approaching text length) leave few or no repeats, and the index of coincidence becomes the more robust tool in that regime. Neither attack is a formal proof of insecurity in the modern sense (no reduction to a hardness assumption) — it is an empirical, information-theoretic argument: the ciphertext retains detectable redundancy from natural language, and that redundancy is quantifiably exploitable.
Worked example
Consider the Vigenère-encrypted ciphertext (spaces added only for the exposition; a real ciphertext would omit them): ``` Ciphertext: LXFOPVEFRNHR VMTOENSVBM YOPKZOOKZ FKQVQOZ VAINP KFZM MP ``` Suppose Kasiski examination finds the trigram `VMT` at position 8 and again at position 32 (illustrative), and the substring `KZOOKZ` region repeats with distances 20 and 40. The distances collected are:
| Repeated substring | Positions | Distance | Factors ≥ 2 |
|---|---|---|---|
| VMT | 8, 32 | 24 | 2,3,4,6,8,12,24 |
| KZO | 25, 45 | 20 | 2,4,5,10,20 |
| OOK | 27, 47 | 20 | 2,4,5,10,20 |
| VQ | 40, 60 | 20 | 2,4,5,10,20 |
The factor 20's divisors of interest (2, 4, 5, 10, 20) dominate the vote, but among these, small factor 4 appears in all rows too — this is where the index of coincidence is decisive. Running `ConfirmKeyLength` for :
| m | avg IC |
|---|---|
| 1 | 0.041 |
| 2 | 0.044 |
| 3 | 0.043 |
| 4 | 0.048 |
| 5 | 0.066 |
| 6 | 0.045 |
gives , matching English's far better than any other candidate — this confirms the key length is 5, consistent with `20 = 4 × 5` and `24` sharing the factor... (in practice the true period is validated by IC, not by picking the most common raw factor, since coincidental repeats muddy the vote — this is precisely why the two methods are used together). With fixed, the ciphertext is split into 5 subsequences (every 5th letter starting at offsets 0..4). Each subsequence is a pure Caesar shift of English. Applying chi-squared shift search to subsequence 0:
| Shift | χ² (lower = better fit) |
|---|---|
| 0 | 210.4 |
| 3 | 188.1 |
| 9 | 41.7 |
| 14 | 175.9 |
| ... | ... |
Shift 9 minimizes , so key letter 0 corresponds to a shift of 9, i.e., key letter `'J'` (since ). Repeating this for offsets 1–4 recovers the remaining key letters; suppose the process yields key = `LEMON` (as in the classical textbook example for this exact ciphertext). Decrypting the full ciphertext with the repeating key `LEMON` via recovers: ``` Plaintext: ATTACKATDAWN... ``` The key insight demonstrated end-to-end: nothing here required guessing the key `LEMON` directly out of possibilities. The period reduced the search to five independent 26-way searches (a total of trial shifts, each scored in linear time) — an enormous reduction achieved purely by exploiting the periodic structure of the key.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Trusting raw frequency rank as the final answer | Small samples deviate from the "textbook" English order (E,T,A,O,I,N,...) | Use rank order only as an initial guess; refine with digram/trigram scoring or word-pattern matching |
| Off-by-one in modular shift arithmetic | Confusing with , or 0-indexing vs 1-indexing letters | Fix a convention (A=0) and verify on a known test vector before trusting output |
| Picking the single most common factor from one repeat | One repeated trigram can be coincidental, especially in short texts | Aggregate factors across many repeats and cross-check with the index of coincidence |
| Ignoring that IC assumes English-like statistics | IC targets (~0.065–0.070) are language-specific; wrong assumed language misleads the key-length search | Recompute or look up reference IC/frequency tables for the actual suspected plaintext language |
| Treating spaces/punctuation as ordinary letters | Retained spacing leaks word boundaries and skews frequency counts | Strip non-alphabetic characters and normalize case before analysis, as real adversaries and real ciphertexts typically require |
| Assuming key length equals ciphertext length is impossible to break | Believing "long key = safe" without checking if key repeats or is derived from a shorter secret | Recognize that only a truly random, single-use key of full message length resists this entirely — the motivation for the one-time pad |
Pioneers & history
Origins · 1 minFriedrich Wilhelm Kasiski and how this was discovered
Kasiski served in the Prussian military and, after retirement, turned to cryptanalysis as an intellectual pursuit. In 1863 he published Die Geheimschriften und die Dechiffrir-Kunst ("Secret Writing and the Art of Deciphering"), which laid out the method of finding repeated ciphertext substrings to deduce the period of a polyalphabetic cipher — the technique that now bears his name, though Charles Babbage had privately developed similar ideas roughly a decade earlier without publishing them.
William Friedman, working at Riverbank Laboratories and later for the U.S. Army, formalized the intuitive "does this look monoalphabetic" question into the precise index-of-coincidence statistic used in the algorithm above, turning Kasiski's substring-counting heuristic into a quantitative, repeatable measurement — a shift from craft to statistical science that foreshadows the information-theoretic rigor Claude Shannon would later bring to cryptography as a whole.
Where this matters
Frequency analysis and Kasiski-style structural attacks are not merely museum pieces; they are the ancestors of every modern known-plaintext, ciphertext-only, and side-channel statistical attack. Historically, Allied cryptanalysts extended these ideas (alongside machine-assisted search) to attack the Enigma machine, whose designers had to work hard specifically to defeat frequency-style leakage. In modern systems, the same reasoning appears whenever engineers evaluate whether an encryption scheme leaks distinguishable statistics: ECB mode block ciphers are criticized precisely because identical plaintext blocks yield identical ciphertext blocks — a direct descendant of the "repeated substring" weakness Kasiski exploited. Compression-then-encryption side channels (e.g., the CRIME and BREACH attacks on TLS-compressed HTTP) are modern, high-tech reincarnations of frequency analysis: they exploit statistical leakage (compressed length) correlated with secret content. Security certifications and cryptographic protocol reviews still ask the Kasiski-style question first: "does anything about the ciphertext's length, timing, or repeated structure correlate with the plaintext or key?" Teaching these classical attacks builds the intuition that underlies modern definitions of security, most notably the demand for semantic security and, at the theoretical limit, the unconditional guarantee offered only by Perfect Secrecy and the One-Time Pad.
Ask the tutor: How does the index of coincidence formula change if the plaintext alphabet or language (e.g., non-English) has different letter-frequency statistics?
Why can't frequency analysis break a one-time pad?
A one-time pad uses a truly random key at least as long as the message, used only once. Every ciphertext letter is shifted by an independent, uniformly random key symbol, so the ciphertext's letter distribution is uniform regardless of the plaintext's true distribution — the permutation is re-randomized every single character, unlike a fixed monoalphabetic . There is no repeating period for Kasiski examination to find, and no stable letter-frequency fingerprint for frequency analysis to match. This is precisely the property — a provable, information-theoretic guarantee rather than a merely large keyspace — explored formally in Perfect Secrecy and the One-Time Pad.
How much ciphertext is actually needed for frequency analysis to succeed reliably?
There is no hard threshold, but practitioners commonly cite a few hundred letters as enough for single-letter frequency ranking to become fairly reliable, with digram/trigram refinement able to succeed on shorter samples if common words or patterns are recognizable. Below roughly 50–100 letters, frequency counts are dominated by sampling noise and rank order can be quite wrong. The general principle is statistical: the estimation error in observed frequency shrinks proportionally to , so confidence grows steadily, but not linearly, with ciphertext length.
Does Kasiski examination require the plaintext to contain literal repeated words?
Yes, implicitly — it depends on the same plaintext substring (of length 3 or more, in practice) occurring at least twice at a ciphertext distance that is a multiple of the key length. Natural language text almost always contains such repeats ("THE", "AND", "ING", common bigrams) once the message is long enough, which is why the attack is so reliable against real prose. Highly repetitive plaintext helps the attacker; artificially avoiding repeated substrings (impractical for natural language) would weaken this specific attack, though the index of coincidence would likely still reveal the period.
Why use chi-squared distance instead of just picking the shift that makes 'E' the most frequent letter?
Picking the shift that maximizes a single letter's frequency is fragile: short texts may have a different letter as most frequent purely by chance, or a near-tie between two candidate shifts. The chi-squared statistic aggregates the entire frequency distribution — all 26 counts compared against expected English frequencies — into one score, which is far more robust to noise in any single letter's count. It effectively asks "how well does this whole distribution match English," rather than "does this one feature match," making it a more statistically sound decision rule.
Can frequency analysis and Kasiski examination be combined with modern computing for even faster breaks?
Absolutely, and this is standard practice today: automated tools use n-gram language models, hill-climbing or simulated annealing over key-swaps, and exhaustive chi-squared shift search, often solving substitution or Vigenère ciphers in milliseconds. The underlying attack logic is unchanged from the manual 19th- and early-20th-century methods; computers simply make the scoring and search loops (already polynomial-time as derived above) run far faster and allow evaluation of many more candidate hypotheses per second.
Why does the article call these "classical" ciphers rather than just "old" ciphers?
"Classical" is a technical term distinguishing pre-computational-era ciphers (substitution, transposition, polyalphabetic schemes) from modern ciphers built on computational hardness assumptions, as covered in Classical Ciphers and Substitution. Classical ciphers operate directly on alphabetic symbols using simple algebraic or combinatorial rules, which is exactly why statistical structure in natural language survives encryption and remains exploitable — the property this article's attacks depend on.
What replaces frequency analysis as the security concern in modern block and stream ciphers?
Modern ciphers are designed so that no efficiently computable statistical test can distinguish ciphertext from random bits, a property formalized as indistinguishability or semantic security. Analysts still search for statistical biases — differential and linear cryptanalysis are direct intellectual descendants of frequency analysis, looking for probability skews in input/output bit patterns rather than letter frequencies. The core question is unchanged: does any observable pattern in the ciphertext correlate, even faintly, with the plaintext or key?