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.

Key takeaways
  • 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.
The core insight

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 π\pi from the plaintext alphabet to itself: every occurrence of a plaintext letter pp maps to the same ciphertext letter π(p)\pi(p). Because π\pi is a bijection, the multiset of letter frequencies is merely permuted, not altered. If 'E' is the most common plaintext letter, then π(E)\pi(E) 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 mm: the ii-th plaintext letter is shifted by the key letter at position i  mi \bmod m. This appears to defeat frequency analysis, since the same plaintext letter can map to mm different ciphertext letters depending on position. But the key repeats with period mm, so the sub-sequence of ciphertext letters at positions i,i+m,i+2m,…i, i+m, i+2m, \dots was all encrypted with the same Caesar shift — it is monoalphabetic. Kasiski examination locates the period mm by finding repeated plaintext patterns (which, because of the periodic key, produce repeated ciphertext patterns separated by multiples of mm). The index of coincidence provides an independent, frequency-based estimate of mm. Once mm is known, the ciphertext splits into mm Caesar ciphers, each breakable by ordinary frequency analysis.

How it works

Part 1 — Frequency analysis of monoalphabetic substitution. The attacker has ciphertext CC 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 26!26! 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 mm 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:

χ2=∑i=025(Oi−Ei)2Ei\chi^2 = \sum_{i=0}^{25} \frac{(O_i - E_i)^2}{E_i}

where OiO_i is the observed count of letter ii and Ei=n⋅piE_i = n \cdot p_i is the expected count under English frequency pip_i. The correct shift minimizes χ2\chi^2.

Figure
Kasiski examination: repeated trigram reveals the key period
Plaintext (repeated word "THE" under repeating key "LEMON") CRYPTOISSHORTTHENTHEQ... LEMONLEMONLEMONLEMONL... NCBSSICMDXOXBTAQNMPWL... (illustrative) repeat "THE" at position i repeat "THE" at position i+15 distance = 15 = 3 × 5 Key length candidates: divisors of 15 shared across many repeats → GCD of distances repeatedly points to m = 5 (length of "LEMON") Ciphertext then splits into 5 monoalphabetic Caesar streams, each solvable by frequency analysis.

Complexity & correctness

Frequency analysis (monoalphabetic).

  • Time: Tabulating counts is O(n)O(n) for ciphertext length nn. The rank-alignment initial guess is O(26log⁡26)O(26 \log 26). The refinement (hill-climbing over swaps) examines O(262)O(26^2) letter-pairs per pass and each scoring pass costs O(n)O(n), so each full refinement pass is O(262n)O(26^2 n); the number of passes until convergence is small in practice (a constant in the tens), giving an overall practical running time of O(n)O(n) to O(262n)O(26^2 n) — linear in ciphertext length for fixed alphabet size. This is exponentially cheaper than the brute-force O(26!)≈4×1026O(26!) \approx 4 \times 10^{26} key search.
  • Space: O(26)O(26) for counts and mapping, O(n)O(n) 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 nn). As n→∞n \to \infty, 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 π\pi applied to the true language rank order. For finite, realistic nn (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 ℓ\ell naively is O(n2)O(n^2) (all pairs of starting positions), or O(n)O(n) average with a hash map keyed by substring, as in the pseudocode. Computing all pairwise distances among repeats of a given substring is O(k2)O(k^2) for kk occurrences, but kk is small in practice, so total cost is dominated by O(n)O(n) to O(n2)O(n^2) in the worst (pathological) case. The index-of-coincidence confirmation loop tries m=1…Mm = 1 \dots M candidate lengths, each costing O(n)O(n), for O(Mn)O(Mn) total — trivial for realistic MM (say, up to 20).
  • Space: O(n)O(n) to index substrings and positions.
  • Once mm is fixed: breaking each of the mm Caesar sub-streams costs O(26⋅n/m)O(26 \cdot n/m) per stream (26 shift trials, each an O(n/m)O(n/m) chi-squared computation), so O(26n)O(26n) total across all mm streams — again linear in nn.
  • Correctness intuition: If the key has period mm and the same plaintext substring of length ℓ≥3\ell \geq 3 appears at two positions whose difference is a multiple of mm, the key letters aligned with each occurrence are identical, so the ciphertext substrings are identical. Repeats at distances not a multiple of mm can occur by coincidence but are statistically rarer for ℓ≥3\ell \geq 3 (a random trigram match probability is roughly (1/26)3≈5.7×10−5(1/26)^3 \approx 5.7 \times 10^{-5} per position pair). Hence the true period mm divides the overwhelming majority of observed repeat-distances, and mm 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, IC≈1/26≈0.038\mathrm{IC} \approx 1/26 \approx 0.038. For natural English (a fixed monoalphabetic shift of English), IC≈0.065\mathrm{IC} \approx 0.065–0.0700.070, because skewed frequencies make two random letters more likely to coincide. Splitting ciphertext into subsequences at the true period mm yields subsequences that are each a straightforward Caesar-shifted English text, so each has IC≈0.065\mathrm{IC} \approx 0.065. Splitting at the wrong period mixes multiple Caesar-shifted alphabets together, which smears the distribution toward uniform, dragging IC\mathrm{IC} toward 0.0380.038. The algorithm's scoring function (distance from 0.06650.0665) 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 substringPositionsDistanceFactors ≥ 2
VMT8, 32242,3,4,6,8,12,24
KZO25, 45202,4,5,10,20
OOK27, 47202,4,5,10,20
VQ40, 60202,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=1..10m = 1..10:

mavg IC
10.041
20.044
30.043
40.048
50.066
60.045

m=5m = 5 gives IC≈0.066\mathrm{IC} \approx 0.066, matching English's ≈0.0665\approx 0.0665 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 m=5m = 5 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)
0210.4
3188.1
941.7
14175.9
......

Shift 9 minimizes χ2\chi^2, so key letter 0 corresponds to a shift of 9, i.e., key letter `'J'` (since A+9=JA + 9 = J). 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 Pi=(Ci−Ki  5)  26P_i = (C_i - K_{i \bmod 5}) \bmod 26 recovers: ``` Plaintext: ATTACKATDAWN... ``` The key insight demonstrated end-to-end: nothing here required guessing the key `LEMON` directly out of 265≈1.1×10726^5 \approx 1.1\times10^7 possibilities. The period reduced the search to five independent 26-way searches (a total of 5×26=1305 \times 26 = 130 trial shifts, each scored in linear time) — an enormous reduction achieved purely by exploiting the periodic structure of the key.

Common pitfalls & traps

PitfallWhy it happensFix
Trusting raw frequency rank as the final answerSmall 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 arithmeticConfusing (C−K)  26(C - K) \bmod 26 with (C+K)  26(C + K) \bmod 26, or 0-indexing vs 1-indexing lettersFix a convention (A=0) and verify on a known test vector before trusting output
Picking the single most common factor from one repeatOne repeated trigram can be coincidental, especially in short textsAggregate factors across many repeats and cross-check with the index of coincidence
Ignoring that IC assumes English-like statisticsIC targets (~0.065–0.070) are language-specific; wrong assumed language misleads the key-length searchRecompute or look up reference IC/frequency tables for the actual suspected plaintext language
Treating spaces/punctuation as ordinary lettersRetained spacing leaks word boundaries and skews frequency countsStrip 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 breakBelieving "long key = safe" without checking if key repeats or is derived from a shorter secretRecognize 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
FW
Friedrich Wilhelm Kasiski
1805–1881 · Prussian infantry officer and cryptanalyst

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.

History
1467
— Leon Battista Alberti describes polyalphabetic substitution using a cipher disk.
1553
— Giovan Battista Bellaso publishes the reciprocal-table cipher later misattributed to Vigenère.
1854
— Charles Babbage privately breaks Vigenère-style ciphers using period-based reasoning, unpublished at the time.
1863
— Friedrich Kasiski publishes the systematic repeated-substring method for finding key length.
1920
— William F. Friedman introduces the index of coincidence as a rigorous statistical measure for cryptanalysis.

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 π\pi. 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 1/n1/\sqrt{n}, 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?

Before this

Where this leads