Some words first
Cryptography has its own vocabulary, and every exam answer uses it:
- Plaintext: the readable message, like
ATTACK AT DAWN. - Ciphertext: the scrambled message that is actually sent.
- Key: the secret that sender and receiver share. Without it, the ciphertext should be useless.
- Encryption turns plaintext into ciphertext. Decryption turns it back.
The two ciphers on this page are symmetric: the same key locks and unlocks the message. They are thousands of years too old to protect anything today, but every idea in modern cryptography, including AES, started with them.
The Caesar cipher
Julius Caesar hid his military orders by moving every letter 3 places along the alphabet: A became D, B became E, and so on, wrapping around from Z back to A. Number the letters A = 0, B = 1, …, Z = 25. With a key k:
- Encrypt: c = (p + k) mod 26
- Decrypt: p = (c − k) mod 26
The “mod 26” is what makes the alphabet a circle, which is why the 3D model draws it as a cipher wheel. Turn the inner ring k places and every plaintext letter on the outside sits above its ciphertext letter on the inside.
Worked example: ATTACKATDAWN, key 3
| Plaintext | A | T | T | A | C | K | A | T | D | A | W | N |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Position | 0 | 19 | 19 | 0 | 2 | 10 | 0 | 19 | 3 | 0 | 22 | 13 |
| + 3, mod 26 | 3 | 22 | 22 | 3 | 5 | 13 | 3 | 22 | 6 | 3 | 25 | 16 |
| Ciphertext | D | W | W | D | F | N | D | W | G | D | Z | Q |
The ciphertext is DWWDFNDWGDZQ.
Breaking Caesar
Caesar has two fatal weaknesses.
- Only 25 keys. An attacker just tries every shift and keeps the one that reads like English. That is a brute-force attack. Press Brute force in the model and it takes 25 steps.
- Letter counts survive. Every A becomes the same letter, so the most common ciphertext letter is probably E (12.7 % of English text), then T, then A. This is frequency analysis, first described by the Arab scholar Al-Kindi in the 9th century.
ROT13, a Caesar shift of 13, is still used online to hide spoilers. Because 13 + 13 = 26, applying it twice gives back the original.
The Vigenère cipher
Vigenère fixes the second weakness by using many Caesar shifts. The key is a word, written again and again under the message. Each key letter gives the shift for the letter above it (A = 0, B = 1, …):
- Encrypt: cᵢ = (pᵢ + kᵢ mod m) mod 26
- Decrypt: pᵢ = (cᵢ − kᵢ mod m) mod 26
Here m is the length of the key. A cipher that switches between several substitution alphabets like this is called polyalphabetic. Caesar uses only one alphabet, so it is monoalphabetic.
Worked example: ATTACKATDAWN, key LEMON
| Plaintext | A | T | T | A | C | K | A | T | D | A | W | N |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Key | L | E | M | O | N | L | E | M | O | N | L | E |
| Shift | 11 | 4 | 12 | 14 | 13 | 11 | 4 | 12 | 14 | 13 | 11 | 4 |
| Ciphertext | L | X | F | O | P | V | E | F | R | N | H | R |
The ciphertext is LXFOPVEFRNHR. The first A became L but the second A became O. The same plaintext letter now hides behind different ciphertext letters, so simple letter counting no longer works. For 300 years Vigenère was called le chiffre indéchiffrable, the unbreakable cipher.
Textbooks often show the Vigenère square (tableau): a 26 × 26 table whose row is the key letter and whose column is the plaintext letter. Reading the table is exactly the same as turning the wheel to the key letter.
Breaking Vigenère
In 1863 Friedrich Kasiski published the attack.
- Find the key length m. Repeated chunks of ciphertext usually come from the same plaintext chunk meeting the same part of the key. The distances between repeats are multiples of m (the Kasiski examination). The index of coincidence gives the same answer statistically.
- Split the ciphertext into m columns. Letters 0, m, 2m, … were all shifted by the first key letter, so each column is just a Caesar cipher.
- Break each column with frequency analysis.
The lesson: a short key that repeats leaks patterns. If the key is truly random, as long as the message and never reused, Vigenère becomes the one-time pad, which is provably unbreakable. The catch is sharing that much key safely, which is the problem that Diffie–Hellman and RSA later solved.
Code
def shift(ch: str, k: int) -> str:
return chr((ord(ch) - ord("A") + k) % 26 + ord("A")) # A = 0 … Z = 25
def caesar(text: str, k: int) -> str:
return "".join(shift(ch, k) if ch.isalpha() else ch for ch in text.upper())
def vigenere(text: str, key: str, decrypt: bool = False) -> str:
out, j = [], 0
for ch in text.upper():
if not ch.isalpha():
out.append(ch) # keep spaces and punctuation
continue
k = ord(key[j % len(key)].upper()) - ord("A")
out.append(shift(ch, -k if decrypt else k))
j += 1 # only letters use up key letters
return "".join(out)
print(caesar("ATTACK AT DAWN", 3)) # DWWDFN DW GDZQ
print(vigenere("ATTACK AT DAWN", "LEMON")) # LXFOPV EF RNHR
print(vigenere("LXFOPV EF RNHR", "LEMON", True)) # ATTACK AT DAWN
for k in range(1, 26): # brute force
print(k, caesar("DWWDFN DW GDZQ", -k)) # k = 3 reads ATTACK AT DAWN
#include <cctype>
#include <iostream>
#include <string>
using namespace std;
string vigenere(const string& text, const string& key, bool decrypt = false) {
string out;
size_t j = 0;
for (char ch : text) {
if (!isalpha(static_cast<unsigned char>(ch))) { out += ch; continue; }
int x = toupper(ch) - 'A';
int k = toupper(key[j++ % key.size()]) - 'A';
if (decrypt) k = 26 - k; // moving back k = moving forward 26 − k
out += char('A' + (x + k) % 26);
}
return out;
}
// Caesar is Vigenère with a one-letter key: shift 3 is the key "D".
string caesar(const string& text, int k) {
return vigenere(text, string(1, char('A' + (k % 26 + 26) % 26)));
}
int main() {
cout << caesar("ATTACK AT DAWN", 3) << '\n'; // DWWDFN DW GDZQ
cout << vigenere("ATTACK AT DAWN", "LEMON") << '\n'; // LXFOPV EF RNHR
cout << vigenere("LXFOPV EF RNHR", "LEMON", true) << '\n'; // ATTACK AT DAWN
}
Caesar vs Vigenère
| Caesar | Vigenère | |
|---|---|---|
| Key | One number, 0–25 | A word of m letters |
| Shifts per message | One | m different shifts, repeating |
| Type | Monoalphabetic | Polyalphabetic |
| Number of keys | 25 | 26^m |
| Same plaintext letter | Always the same ciphertext letter | Can become different letters |
| Broken by | Brute force or frequency analysis | Kasiski examination, then frequency analysis per column |
Common mistakes
- Forgetting to wrap around. W + 3 is Z, but X + 3 is A, not a symbol after Z. Always take the result mod 26.
- Negative numbers when decrypting. C − 5 = 2 − 5 = −3, and −3 mod 26 = 23 = X. In C++ the
%operator can return a negative number, so add 26 first. - Starting at A = 1. The formulas need A = 0. With A = 1, the key A would shift by one instead of not at all.
- Using up key letters on spaces. In Vigenère only letters consume key letters, so ATTACK AT DAWN and ATTACKATDAWN give the same letters.
Complexity at a glance
| Case / operation | Time | Why |
|---|---|---|
| Encrypt or decrypt n letters | O(n) | One addition mod 26 per letter. |
| Caesar brute force | 25 · O(n) | Only 25 keys to try. |
| Vigenère keys of length m | 26^m | Already 11.9 million for m = 5. |
| Breaking Vigenère once m is known | m Caesar ciphers | Each column is a Caesar cipher with 25 keys. |
Quick check
Test yourself — pick an answer to see if you got it.
1. What is XYZ encrypted with a Caesar cipher, key k = 3?
X (23) + 3 = 26 mod 26 = 0 = A, then Y → B and Z → C. The alphabet wraps around after Z.
2. Decrypt KHOOR with a Caesar cipher, key k = 3.
Move every letter 3 places back. K → H, H → E, O → L, O → L, R → O.
3. With Vigenère, the plaintext letter H meets the key letter C. Which ciphertext letter do you get?
H is 7 and C is 2. (7 + 2) mod 26 = 9, which is J.
4. How many keys does an attacker need to try, at most, to break a Caesar cipher?
A shift of 26 changes nothing, so there are only 25 useful keys. Trying them all takes a moment, even by hand.
5. Why is Vigenère harder to break with simple letter counting than Caesar?
Each key letter gives a different shift, so an E in the message can become many different letters. That flattens the letter counts that frequency analysis relies on.