Before modern crypto became math-heavy enough that you needed a PhD to design it, people used classical ciphers — clever pen-and-paper schemes that protected diplomatic mail, military orders, and the occasional love letter. Most of them are broken today, but they're still worth studying. They're how the field learned to think.
This post walks through three of them: the Vigenère cipher, the Kasiski analysis that breaks it, and the Running Key cipher.
Words to keep straight
Three terms get used interchangeably in casual writing, but they mean different things:
- Cryptography — the design of methods to keep information secret.
- Cryptanalysis — the study of breaking those methods.
- Cryptology — the umbrella that covers both.
A few more we'll use throughout:
- Plaintext — the original message.
- Ciphertext — the message after encryption.
- Cipher — the procedure that turns one into the other.
- Key — the parameter that customises the cipher; the same plaintext and cipher with different keys produce different ciphertexts.
The Caesar cipher, briefly
To set the stage. The Caesar cipher shifts every letter by a fixed amount: shift by 3 and HELLO becomes KHOOR. The key is the shift value, of which there are 25 useful ones.
It's broken by trying all 25 shifts and seeing which one produces English. Less than a second of work.
What broke the Caesar cipher is that each plaintext letter always maps to the same ciphertext letter. Frequency analysis — counting how often each letter appears — is enough to crack it. In English, E is the most common letter; whichever letter dominates the ciphertext is almost certainly the encrypted E.
The Vigenère cipher
Vigenère's trick is to use many shifts in rotation, controlled by a keyword. This is what makes it polyalphabetic: the same plaintext letter can encrypt to different ciphertext letters depending on its position.
How it works
Take a plaintext, repeat the keyword underneath it, then add the two letters position-by-position (treating A=0, B=1, …, Z=25, mod 26):
1Plaintext: ATTACKATDAWN
2Keyword: LEMONLEMONLE (repeated)
3Ciphertext: LXFOPVEFRNHR
The first letter: A + L = 0 + 11 = 11 → L. The second: T + E = 19 + 4 = 23 → X. And so on.
Decryption is the same operation in reverse: subtract the keyword letter from the ciphertext letter.
Why it was strong
Because the same plaintext letter encrypts to different ciphertext letters depending on its position, simple frequency analysis fails — the ciphertext distribution looks much closer to uniform.
For roughly 300 years (16th to 19th century), Vigenère was considered le chiffre indéchiffrable — the indecipherable cipher.
A Java implementation
src/main/java/cipher/Vigenere.java 1public class Vigenere {
2
3 public static String encrypt(String plaintext, String key) {
4 StringBuilder out = new StringBuilder();
5 String upperKey = key.toUpperCase();
6 int keyIdx = 0;
7
8 for (char ch : plaintext.toUpperCase().toCharArray()) {
9 if (Character.isLetter(ch)) {
10 int p = ch - 'A';
11 int k = upperKey.charAt(keyIdx % upperKey.length()) - 'A';
12 out.append((char) (((p + k) % 26) + 'A'));
13 keyIdx++;
14 } else {
15 out.append(ch);
16 }
17 }
18 return out.toString();
19 }
20
21 public static String decrypt(String ciphertext, String key) {
22 StringBuilder out = new StringBuilder();
23 String upperKey = key.toUpperCase();
24 int keyIdx = 0;
25
26 for (char ch : ciphertext.toUpperCase().toCharArray()) {
27 if (Character.isLetter(ch)) {
28 int c = ch - 'A';
29 int k = upperKey.charAt(keyIdx % upperKey.length()) - 'A';
30 out.append((char) (((c - k + 26) % 26) + 'A'));
31 keyIdx++;
32 } else {
33 out.append(ch);
34 }
35 }
36 return out.toString();
37 }
38}
Kasiski analysis: breaking Vigenère
In 1863, the Prussian officer Friedrich Kasiski published a method that cracked Vigenère in the open literature for the first time. The idea is elegant.
Step 1: Find repeated sequences
If a sequence of letters in the plaintext (say, "THE") happens to land underneath the same part of the key on two different occurrences, both occurrences encrypt to the same ciphertext sequence. Repeated plaintext + same key alignment = repeated ciphertext.
Step 2: Measure the gaps
The distance between two such repetitions in the ciphertext is — almost always — a multiple of the key length. If the key is 6 letters long, gaps will be multiples of 6.
Step 3: Find the GCD
If you spot several repeated sequences with gaps of 12, 18, and 30, the key length is likely the GCD of those: gcd(12, 18, 30) = 6.
Step 4: Frequency-analyse each column
Once you know the key length, you can split the ciphertext into L columns, where L is the key length. Each column was encrypted with a single Caesar shift — and Caesar is trivial to break with frequency analysis.
Solve each column independently, paste the shifts together, and you have the keyword.
A small worked example
Suppose the ciphertext contains the trigram RPB at positions 10 and 40, and again at positions 70 and 130.
- Gap 1:
40 − 10 = 30 - Gap 2:
130 − 70 = 60
The likely key length divides both: gcd(30, 60) = 30. The keyword length is probably one of the divisors of 30: 2, 3, 5, 6, 10, 15, or 30. Run the column-wise frequency analysis for each candidate; the one that produces readable English wins.
The Running Key cipher
Vigenère's weakness is the repeating keyword. What if the key is as long as the message itself — and not repeated?
That's the Running Key cipher. The key is a passage from a book (or any other text) of length ≥ the plaintext. Encryption is the same letter-addition as Vigenère, but the key never wraps around.
1Plaintext: ATTACKATDAWN
2Key: (page 47, line 3, char 12 of Pride and Prejudice — "ITISATRUTHUNI…")
3Ciphertext: ...
If the sender and receiver both have the same book and agree on a starting point (often communicated as "page X, line Y, character Z"), they can encrypt arbitrarily long messages with a key that never repeats.
What it gives you
- Kasiski-style analysis can't find a key length because there is no repeating key.
- For short messages from natural-language books, it's still attackable — both the key and the plaintext are English, and a clever cryptanalyst can exploit that.
- If the key were genuinely random and used only once, this becomes the one-time pad: information-theoretically unbreakable.
What the classical ciphers teach you
You probably won't use Vigenère in 2024 — but the lessons it teaches are exactly the lessons modern crypto is built on:
- Repetition is the enemy. Modern block ciphers go to great lengths to make ciphertext look random.
- Statistical structure leaks. Letter frequencies, common bigrams, expected word lengths — all are attack surfaces.
- Key reuse breaks everything. This is true for one-time pads, and it's true for stream ciphers like RC4. (WEP famously fell to key-reuse attacks.)
- A secret is only as secret as its key management. The Running Key cipher is "unbreakable" if both parties securely share the starting position — which is the same problem in miniature that public-key cryptography exists to solve.
Wrap-up
The history of cryptography is a sequence of arms races: a clever cipher gets invented, defenders feel safe, attackers find a structural weakness, defenders invent a better cipher. Vigenère stood up for three centuries; Kasiski cracked it; the running key cipher pushed back; modern crypto pushed the problem into pure mathematics.
Classical ciphers are no longer secure on their own, but they're the perfect playground for understanding why the modern stuff is shaped the way it is.
