← ACARA Digital Technologies Years 9–10

Brute-forcing a Caesar cipher in Python

A loop that tries every Caesar shift from 1 to 25. Each pass decrypts the message and prints the shift beside the result, so you can spot the readable one.

Understanding Brute-forcing a Caesar cipher in Python in ACARA Digital Technologies Years 9–10

What it does: The loop calls decrypt with every shift and prints each result, so the readable message can be found. range() stops one before its end value, so range(1, 26) gives 1 to 25. range(1, 25) would miss shift 25. The right shift turns the ciphertext back into readable text. The other attempts look like nonsense. break ends the loop. continue only skips to the next shift, so the loop would keep going. A tiny key space means a computer can test every key in a fraction of a second.

Common mistakes: This prints the original scrambled message every time, so you never see the decrypted attempts. It should be print(shift, out) to show the shift beside each result. A for statement must end with a colon. It should be for shift in range(1, 26):.

Class: _____________________  ·  Name: _____________________  ·  Date: _________

Free printable worksheet with full answer key — or add this module to a class and your students practise it interactively.

This module's key terms are also in a printable crossword (Modules 876–944) and word search (Modules 860–944).

Take this worksheet further — free with Cloodit

Each concept is reinforced from every angle — learned, then applied, then tested.

Learning
Duo
Which loop tries every Caesar shift from 1 to 25?
for shift in range(1, 26):for shift in range(1, 25):
Matches
for shift in range(1, 25):
↓
range(1, 25) stops at 24, so shift 25 is never tried and the correct answer could be missed. It should be range(1, 26).
Applying
Meanings
Term
for shift in range(1, 26):
Meaning
A loop that tries every Caesar shift from 1 to 25. Each pass decrypts the message and prints the shift beside the result, so you can spot the readable one.
Practice
def decrypt(text, shift):
Testing
Gaps
for shift in (1, 26):
Check Answer
Spots
3 out = decrypt(msg, shift)
4 print(shift, msg)

Cloodit turns curriculum-aligned coding content into journeys students work through one biome at a time.

The 'Fox' badge — Cunning Debugger, one of Cloodit's 106 collectible badges
Students earn collectable badges

Over 100 of them, across seven natural biomes.

Study Buddy
Students build a real study resource

Turns their work into revision material ready for Flash Cards and Exam study.

Diamond Dash — one of Cloodit's live, competitive Sprint games
Students lock in with Sprints

Live, competitive practice for the start of the lesson or a teacher-led lesson finisher.

A Cloodit certificate of achievement, ready to personalise and print
Custom printable certificates

Honour your top performers, or encourage a student who's trying hard — ready to print in seconds.

Quick Questions

1. Which loop tries every Caesar shift from 1 to 25?
A. for shift in range(1, 25):
B. for shift in range(1, 26): ✓
range() stops one before its end value, so range(1, 26) gives 1 to 25. range(1, 25) would miss shift 25.
2. Why does the loop use range(1, 26) and not range(1, 25)?
A. range() stops before the end value, so 26 is needed to include shift 25 ✓
B. range() includes the end value, so 26 gives shifts 1 to 26
The end value in range() is never reached. Stopping at 26 means the last shift tried is 25.
3. Which line prints the shift beside each attempt?
A. print(decrypt(message, shift))
B. print(shift, decrypt(message, shift)) ✓
Printing the shift next to the result lets you see which key gave the readable text.
4. What happens on each pass of the brute-force loop?
A. It decrypts the message with the current shift and prints the result ✓
B. It encrypts the message again using the same shift every time
Each pass uses a new shift value from the loop, and the attempt is decrypted and printed so you can check it.
5. How do you spot the correct shift in the printed list?
A. It is the attempt that reads as normal English ✓
B. It is the attempt with the largest shift number
The right shift turns the ciphertext back into readable text. The other attempts look like nonsense.

Match the Pairs

for shift in range(1, 26): → Loop that tries every possible Caesar shift from 1 to 25 in turn
print(shift, decrypt(secret, shift)) → Shows each shift number beside the message it produces, so you can spot the readable one
To brute-force a Caesar cipher, try every shift from 1 to 25 and decrypt the message each time → for shift in range(1, 26): print(shift, decrypt(secret, shift))
The brute-force loop can stop as soon as a known word appears in the decrypted text → if "hello" in text: break
for shift in range(1, 25): → range(1, 25) stops at 24, so shift 25 is never tried and the correct answer could be missed. It should be range(1, 26).
for shift in range(1, 26): print(decrypt(secret, shift)) → The shift is not printed beside each result, so you cannot tell which shift produced the readable message. It should print shift as well.

Key Term

for shift in range(1, 26):
A loop that tries every Caesar shift from 1 to 25. Each pass decrypts the message and prints the shift beside the result, so you can spot the readable one.

Fill in the Blanks

1. for shift in range(1, 26): result = decrypt(message, shift) print(shift, result)
Hint: Type the built-in function that produces the series of shift numbers to loop through.
2. for shift in range(1, 26): result = decrypt(message, shift) print(shift, result)
Hint: Type the stop value. range() stops just before it, so the last shift tried is 25.
3. for shift in range(1, 26): result = decrypt(message, shift) print(shift, result)
Hint: Type the loop variable that shows which shift produced each attempt.
4. result = decrypt(message, shift) if "the" in result: break
Hint: Type the keyword that stops the loop once a known word has been found.
5. for shift in range(1, 26): result = decrypt(message, shift) print(shift, result)
Hint: Type the name of the function that undoes the Caesar cipher using the current shift.

Spot the Error

Question 1
A msg = "KHOOR"
B for shift in range(1, 26):
C out = decrypt(msg, shift)
D print(shift, msg)
Line D — This prints the original scrambled message every time, so you never see the decrypted attempts. It should be print(shift, out) to show the shift beside each result.
Question 2
A for shift in range(1, 26)
B out = decrypt(msg, shift)
C print(shift, out)
Line A — A for statement must end with a colon. It should be for shift in range(1, 26):
Question 3
A msg = "WKLV LV IXQ"
B for shift in range(1, 25):
C out = decrypt(msg, shift)
D print(shift, out)
Line B — range(1, 25) stops at 24, so shift 25 is never tried. To try every shift from 1 to 25 you need range(1, 26).
Question 4
A for shift in range(26, 1):
B out = decrypt(msg, shift)
C print("Shift", shift, out)
Line A — range(26, 1) counts up from 26 and is empty, so the loop never runs. The start must be smaller than the stop: range(1, 26).
Question 5
A for shift in range(1, 26):
B out = decrypt(msg, shift)
C if "THE" == out:
D print(shift, out)
E break
Line C — == only matches if the whole message is exactly THE. To stop when a known word appears anywhere in the text, use in: if "THE" in out:

Student with a class code? Join your class →