Classical Ciphers

beginner35 minWriteup

Breaking historical ciphers in CTFs

Learning Objectives

  • Break Caesar cipher
  • Crack Vigenere cipher
  • Solve substitution ciphers
  • Use frequency analysis

Classical ciphers are historical encryption methods that are easily broken by modern standards but still appear frequently in CTFs. Learning to recognize and break them quickly is essential!

Classical ciphers were state-of-the-art hundreds of years ago. Now they're CTF warm-ups! The same principles (substitution, transposition) still underlie modern crypto.

Caesar Cipher

Shifts each letter by a fixed number. ROT13 is Caesar with shift of 13.

bash
1606070;"># Example: "KHOOR" with shift 3
2606070;"># K→H, H→E, O→L, O→L, R→O = "HELLO"
3 
4606070;"># ROT13 (shift 13) - special because decrypt = encrypt
5606070;"># "URYYB""HELLO"
6 
7606070;"># Brute force all 26 shifts
8echo 606070;">#a5d6ff;">"KHOOR" | tr 'A-Za-z' 'N-ZA-Mn-za-m' # ROT13
9 
10606070;"># Python brute force:
11cipher = 606070;">#a5d6ff;">"KHOOR"
12for shift in range(26):
13 plain = 606070;">#a5d6ff;">""
14 for c in cipher:
15 if c.isalpha():
16 shifted = chr((ord(c.upper()) - ord(606070;">#a5d6ff;">'A') - shift) % 26 + ord('A'))
17 plain += shifted
18 else:
19 plain += c
20 print(f606070;">#a5d6ff;">"Shift {shift}: {plain}")
21 
22606070;"># CyberChef: ROT13 Brute Force operation

Quick Check

If ciphertext looks like shifted English (same structure, common patterns), try ROT13 first - it's the most common variant in CTFs!

Substitution Cipher

Each letter maps to a different letter consistently. Unlike Caesar, the mapping is arbitrary.

1606070;"># Example mapping:
2Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ
3Cipher: ZYXWVUTSRQPONMLKJIHGFEDCBA
4 
5606070;"># "HELLO""SVOOL"
6 
7606070;"># Breaking substitution ciphers:
8606070;"># 1. Frequency analysis (E is most common in English)
9606070;"># 2. Pattern matching (THE, AND, common words)
10606070;"># 3. Automated tools
11 
12606070;"># Single letter words: I, A
13606070;"># Common 2-letter: OF, TO, IN, IT, IS, BE, AS, AT, SO
14606070;"># Common 3-letter: THE, AND, FOR, ARE, BUT, NOT, YOU
15606070;"># Common double letters: LL, EE, SS, OO, TT
16 
17606070;"># Frequency in English:
18606070;"># E (12.7%), T (9.1%), A (8.2%), O (7.5%), I (7.0%), N (6.7%)
19 
20606070;"># Tools:
21606070;"># quipqiup.com - Automated solver
22606070;"># dcode.fr/monoalphabetic-substitution
python
1606070;"># Frequency analysis in Python
2from collections import Counter
3 
4cipher = 606070;">#a5d6ff;">"YOUR_CIPHERTEXT_HERE"
5freq = Counter(cipher.upper())
6for char, count in freq.most_common():
7 if char.isalpha():
8 print(f606070;">#a5d6ff;">"{char}: {count} ({count/len(cipher)*100:.1f}%)")

Vigenère Cipher

Polyalphabetic cipher using a keyword. Each letter of the key shifts the corresponding plaintext letter by a different amount.

1606070;"># Key: "KEY"
2606070;"># Plain: "HELLO"
3606070;">#
4606070;"># H + K(10) = R
5606070;"># E + E(4) = I
6606070;"># L + Y(24) = J
7606070;"># L + K(10) = V
8606070;"># O + E(4) = S
9606070;"># Cipher: "RIJVS"
10 
11606070;"># Breaking Vigenère:
12606070;"># 1. Find key length (Kasiski examination, Index of Coincidence)
13606070;"># 2. Split into groups (each shifted by same key letter)
14606070;"># 3. Frequency analysis on each group
15 
16606070;"># Key length detection:
17606070;"># - Look for repeated sequences
18606070;"># - Distance between repeats is multiple of key length
19606070;"># - Index of Coincidence (IC) peaks at correct length
python
1606070;"># Vigenère decrypt with known key
2def vigenere_decrypt(cipher, key):
3 plain = 606070;">#a5d6ff;">""
4 key = key.upper()
5 key_index = 0
6 for c in cipher:
7 if c.isalpha():
8 shift = ord(key[key_index % len(key)]) - ord(606070;">#a5d6ff;">'A')
9 decrypted = chr((ord(c.upper()) - ord(606070;">#a5d6ff;">'A') - shift) % 26 + ord('A'))
10 plain += decrypted
11 key_index += 1
12 else:
13 plain += c
14 return plain
15 
16606070;"># Online tools:
17606070;"># dcode.fr/vigenere-cipher (auto-solves!)
18606070;"># guballa.de/vigenere-solver
dcode.fr can often break Vigenère automatically. If it doesn't work, try providing guessed words that might appear in the plaintext.

Transposition Ciphers

1606070;"># Letters rearranged, not substituted
2 
3606070;"># Rail Fence Cipher
4606070;"># Write zigzag across rails, read rows
5606070;"># 3 rails: "HELLO WORLD"
6606070;"># H . . . O . . . R . .
7606070;"># . E . L . W . O . L .
8606070;"># . . L . . . O . . . D
9606070;"># Read: "HOR EL WOL LOD""HORELWOLLOD"
10 
11606070;"># Columnar Transposition
12606070;"># Write in rows, read by column
13606070;"># Key: "KEY" (sorted: E=1, K=2, Y=3)
14606070;"># Message: "HELLO WORLD"
15606070;">#
16606070;"># K E Y
17606070;"># H E L
18606070;"># L O W
19606070;"># O R L
20606070;"># D
21606070;">#
22606070;"># Read columns in key order (E,K,Y): "EOR HLOD LWL"
23 
24606070;"># Breaking transposition:
25606070;"># - Try common rail counts (2, 3, 4, 5)
26606070;"># - Anagram solver for short texts
27606070;"># - Pattern recognition for common words
28 
29606070;"># Tools:
30606070;"># dcode.fr/rail-fence-cipher
31606070;"># dcode.fr/columnar-transposition-cipher

Other Classical Ciphers

1606070;"># Atbash - Reverses alphabet
2606070;"># A↔Z, B↔Y, C↔X, etc.
3606070;"># "HELLO""SVOOL"
4606070;"># Decrypt same as encrypt!
5 
6606070;"># Playfair - 5x5 grid cipher
7606070;"># Uses bigrams (pairs of letters)
8606070;"># Recognizable by even-length ciphertext, no J
9 
10606070;"># Affine Cipher
11606070;"># E(x) = (ax + b) mod 26
12606070;"># Need to find a and b
13 
14606070;"># Bacon's Cipher
15606070;"># Hides message in formatting
16606070;"># AABBA AAAAB AAAAA AABAA...
17606070;"># A=AAAAA, B=AAAAB, etc.
18 
19606070;"># Morse Code
20606070;"># .- -... -.-. (ABC)
21606070;"># dcode.fr/morse-code
22 
23606070;"># Book Cipher
24606070;"># References positions in a book
25606070;"># "1:2:3" = Book 1, Page 2, Word 3
26 
27606070;"># Polybius Square
28606070;"># 5x5 grid, each letter = row,column
29606070;"># "HELLO""23 15 31 31 34"

Cipher Identification

Use dcode.fr/cipher-identifier when you're unsure. Paste ciphertext, and it suggests likely cipher types based on characteristics!

Essential Tools

1606070;"># Online Solvers
2606070;"># dcode.fr - Best overall, auto-solves many ciphers
3606070;"># quipqiup.com - Substitution cipher solver
4606070;"># guballa.de/vigenere-solver - Vigenère breaker
5 
6606070;"># CyberChef Operations
7606070;"># - ROT13 / ROT13 Brute Force
8606070;"># - Vigenère Decode
9606070;"># - Substitute (manual substitution)
10606070;"># - Rail Fence Cipher Decode
11 
12606070;"># Python Libraries
13pip install pycipher
14 
15from pycipher import Caesar, Vigenere, Playfair
16 
17606070;"># Caesar
18Caesar(3).decipher(606070;">#a5d6ff;">"KHOOR")
19 
20606070;"># Vigenère
21Vigenere(606070;">#a5d6ff;">"KEY").decipher("RIJVS")

Knowledge Check

Quick Quiz
Question 1 of 2

What makes Vigenère harder to break than Caesar?

Key Takeaways

  • ROT13 is the most common Caesar variant in CTFs
  • Substitution ciphers break to frequency analysis
  • Vigenère requires finding key length first
  • dcode.fr auto-solves most classical ciphers
  • quipqiup.com excels at substitution ciphers
  • Pattern recognition beats brute force for classical crypto