Week 2 Security Challenge: Caesar Cipher
π‘ Following along? All exercises are open source! Star the AppSec-Exercises repo to track my 48-week journey from Intel Security to AppSec Engineer.
"Why would a security engineer need to know a cipher that's been broken for 2,000 years?"
Because Grace Nolan's security interview list explicitly includes "Caesar cipher and basic crypto" as a common coding challenge. Here's why it matters.
Why Caesar Cipher in Security Interviews?
1. Tests String Manipulation Fundamentals
Security engineers parse logs, analyze malware, and process network data - all requiring strong string skills. Caesar cipher tests:
- Character iteration
- ASCII/Unicode manipulation
- Modular arithmetic
- Case preservation
2. Reveals Cryptography Understanding
Interviewers want to see if you understand:
- Encryption vs Encoding: Caesar is symmetric encryption (requires key)
- Key Space: Only 26 possible keys = trivially brute-forceable
- Frequency Analysis: Statistical attacks on substitution ciphers
- Why Modern Crypto Exists: Understanding what makes AES-256 different
3. Foundation for Real Security Concepts
Caesar cipher introduces:
- Shift operations β ROT13, XOR operations
- Symmetric keys β Shared secret cryptography
- Cryptanalysis β Breaking weak crypto
- Defense in Depth β Why we don't rely on single encryption methods
The Challenge
Used by Julius Caesar to protect military messages in 58 BC, the Caesar cipher shifts each letter by a fixed number of positions in the alphabet.
Example:
HELLO + shift(3) = KHOOR
XYZ + shift(3) = ABC (wraparound!)
The challenge is figuring out how to implement this transformation while preserving case and handling edge cases.
Your Mission: Build It
Part 1: Encryption
"""
Exercise 3: Caesar Cipher Encoder/Decoder
Week 2 - Python Strings Practice
Inspired by: Python Workout, Second Edition by Reuven M. Lerner
- Chapter 3 (Strings), pages 962-1200
- Exercise 5 (Pig Latin), demonstrating string transformation
Security Context: Grace Nolan's Security Coding Challenges
Reference: Extended 48 Week Security Engineering Curriculum, Week 90
"""
def caesar_encrypt(plaintext, shift):
"""
Encrypt text using Caesar cipher.
Args:
plaintext (str): Text to encrypt
shift (int): Number of positions to shift
Returns:
str: Encrypted ciphertext
"""
# Your code here
pass
Part 2: Decryption
def caesar_decrypt(ciphertext, shift):
"""
Decrypt Caesar cipher text.
Args:
ciphertext (str): Encrypted text
shift (int): Number of positions used in encryption
Returns:
str: Decrypted plaintext
"""
# Your code here
pass
Requirements
- β
Preserve case:
HelloβKhoor(notkhoor) - β
Keep non-letters:
Hello, World!βKhoor, Zruog! - β
Handle wraparound:
XYZ + 3βABC - β
Support negative shifts:
shift(-3)= decrypt with shift(3) - β
Work with any shift: Including
shift(26),shift(0),shift(100)
Sample Test Cases (10 from 95)
# Test 1: Basic encryption
assert caesar_encrypt("HELLO", 3) == "KHOOR"
# Test 2: Wraparound
assert caesar_encrypt("XYZ", 3) == "ABC"
# Test 3: Mixed case preserved
assert caesar_encrypt("Hello, World!", 13) == "Uryyb, Jbeyq!"
# Test 4: Non-alphabetic preserved
assert caesar_encrypt("test@example.com", 5) == "yjxy@jcfruqj.htr"
# Test 5: Negative shift (decrypt)
assert caesar_encrypt("KHOOR", -3) == "HELLO"
# Test 6: Decryption
assert caesar_decrypt("KHOOR", 3) == "HELLO"
# Test 7: Round-trip
assert caesar_decrypt(caesar_encrypt("SECURITY", 7), 7) == "SECURITY"
# Test 8: ROT13 (shift 13)
assert caesar_encrypt("HELLO", 13) == "URYYB"
# Test 9: ROT13 property (apply twice = original)
assert caesar_encrypt(caesar_encrypt("Python", 13), 13) == "Python"
# Test 10: Large shift (modulo 26)
assert caesar_encrypt("HELLO", 29) == "KHOOR" # 29 % 26 = 3
Security Lessons from Caesar Cipher
Lesson 1: Brute Force is Trivial
def brute_force_caesar(ciphertext):
"""Try all 26 possible shifts"""
for shift in range(26):
plaintext = caesar_decrypt(ciphertext, shift)
print(f"Shift {shift}: {plaintext}")
brute_force_caesar("KHOOR")
# Output:
# Shift 0: KHOOR
# Shift 1: JGNNQ
# Shift 2: IFMMP
# Shift 3: HELLO β Found it!
# ...
Real-world parallel: Weak passwords with small key spaces (4-digit PIN = 10,000 possibilities)
Lesson 2: Frequency Analysis Breaks It
def frequency_analysis(ciphertext):
"""English: E is most common (12.7%), T is second (9.1%)"""
freq = {}
for char in ciphertext.upper():
if char.isalpha():
freq[char] = freq.get(char, 0) + 1
# Most common letter in ciphertext is likely 'E'
most_common = max(freq, key=freq.get)
likely_shift = (ord(most_common) - ord('E')) % 26
return likely_shift
Real-world parallel: Side-channel attacks, timing attacks, traffic analysis
Lesson 3: Security Through Obscurity Fails
The Caesar cipher relies on the shift value being secret. But even without knowing the shift, it's easily broken.
Real-world parallel:
- Hiding API endpoints doesn't secure them
- Obfuscating code doesn't prevent reverse engineering
- "Security by obscurity" is not a defense
What Makes Modern Crypto Different?
| Caesar Cipher | AES-256 |
|---|---|
| 26 possible keys | 2^256 possible keys |
| Frequency analysis | Resistant to known-plaintext attacks |
| Same letter β same output | CBC/GCM modes prevent patterns |
| Broken in seconds | Computationally infeasible to break |
Interview Follow-Up Questions
Be prepared to answer:
Q: "How would you break this cipher without knowing the shift?"
A: (1) Brute force all 26 shifts, (2) Frequency analysis comparing to English letter frequencies
Q: "What's the difference between Caesar cipher and XOR cipher?"
A: Both are symmetric, but XOR uses binary operations and can have variable-length keys
Q: "Why do we call ROT13 a special case?"
A: Shift of 13 is self-inverse: encrypt(encrypt(x)) = x because 13 + 13 = 26 β‘ 0 (mod 26)
Q: "How would you extend this to support Unicode/emoji?"
A: Need to handle different code point ranges, or use a lookup table instead of modular arithmetic
Real-World Applications (Historical)
1. ROT13 (Still Used Today!)
# Hide spoilers on forums, email, Usenet
rot13 = lambda s: caesar_encrypt(s, 13)
print(rot13("Darth Vader is Luke's father"))
# "Qnegu Inqre vf Yhxr'f sngure"
2. Simple Obfuscation
# Hide config values (NOT secure, just obscured)
api_key = caesar_encrypt("secret_key_12345", 7)
# Decode when needed
real_key = caesar_decrypt(api_key, 7)
Warning: Never use Caesar for real security!
Python Skills You'll Practice
From Python Workout Chapter 3 (pages 962-1200):
- β
String iteration:
for char in text - β
Character checking:
.isalpha(),.isupper(),.islower() - β
ASCII conversions:
ord(),chr() - β String building: Concatenation vs list joining
- β
Modular arithmetic:
(x + shift) % 26
From Grace Nolan's Interview Prep:
- β Algorithmic thinking: Shift operations
- β Edge case handling: Empty strings, special characters
- β Code clarity: Clean, readable implementation
- β Testing mindset: Comprehensive test coverage
Next Steps: Breaking Crypto
After completing this exercise:
1. Build a Cryptanalysis Tool
def crack_caesar(ciphertext):
"""
Automatically crack Caesar cipher using:
1. Brute force (try all 26 shifts)
2. Frequency analysis
3. Dictionary matching (check if result contains English words)
"""
pass
2. Extend to Vigenère Cipher
Multi-character keys: HELLO with key ABC β HFNLP
- Key repeats: H+A, E+B, L+C, L+A, O+B
- More secure than Caesar (but still breakable!)
3. Compare with Modern Crypto
Implement simple XOR cipher, then research:
- Why XOR with random key (one-time pad) is theoretically unbreakable
- Why reusing keys breaks XOR
- How AES differs from substitution ciphers
Resources
Cryptography:
- "The Code Book" by Simon Singh - Excellent history of cryptography
- "Cryptography Engineering" by Ferguson, Schneier, Kohno - Modern crypto
- Stanford Cryptography I (Coursera) - Dan Boneh's course
Python String Manipulation:
- Python Workout, Second Edition by Reuven M. Lerner - Chapter 3 (pages 962-1200)
- Effective Python by Brett Slatkin - Item 11: Slicing sequences
Security Interview Prep:
- Grace Nolan's Notes (gracenolan/Notes on GitHub)
- "Cracking the Coding Interview" - Security-focused problems
- PortSwigger Web Security Academy - Modern crypto vulnerabilities
Get the Full Exercise
β Star the AppSec-Exercises repo on GitHub to get all 95 test cases and follow my security engineering journey!
What's in the repo:
- exercise_03_caesar_cipher_rough.py - Complete exercise with 95 test cases
- My solution - Full implementation with detailed code
- Weekly security challenges aligned with my 48-week curriculum
- LeetCode-style format perfect for interview prep
Why star it?
- Track my progress from Intel Security β AppSec Engineer
- Get notified when new exercises drop weekly
- Contribute your own solutions and test cases
- Build your portfolio alongside mine
All exercises are MIT licensed - use them for your own interview prep!
My Progress: Week 2 of 48
β
DNS Fundamentals
β
TLS/SSL Security
β
Python Workout Chapters 3-4 (Strings, Lists)
β
8 PortSwigger SQL Injection Labs
π Currently: Caesar cipher + cipher suite analyzer
π Grace Nolan's coding challenges: 1/10 complete
Goal: Transition to AppSec Engineer by June 2026
β Follow my journey on GitHub - New exercises every week!
The Big Picture
Understanding why Caesar cipher is broken teaches you:
- β What makes cryptography secure (key space, resistance to attacks)
- β How to think like an attacker (frequency analysis, brute force)
- β Why we don't roll our own crypto (use proven algorithms instead)
- β Foundation for learning modern cryptography (AES, RSA, elliptic curves)
In Week 5, we'll tackle real cryptography: AES, RSA, password hashing with bcrypt/Argon2, and the mistakes that lead to vulnerabilities.
For now, master the fundamentals by building something broken - then learn why it's broken.
π Take Action
- β Star AppSec-Exercises on GitHub - Get weekly security coding challenges
- π¬ Drop a comment - Have you seen Caesar cipher in interviews? What other "broken" security concepts appear?
- π Follow me on Dev.to and GitHub for my full 48-week journey
Currently seeking: Remote Security Engineering roles
Top comments (0)