Biterra Labs preview / Intro to Cryptography
Classic ciphers are old letter-shuffling methods. They are weak by modern standards, which is why they still appear in beginner challenges. The skill is spotting what kind of text you have before you start shifting letters.
You usually do not know the original text, so you cannot prove what "survived." Start with the structure still visible in the ciphertext:
| Input | Visible evidence | First move |
|---|---|---|
WKH FOXH LV WKH ZRUG! | Mostly letters; spaces and ! remain; WKH repeats | Try all 25 Caesar shifts |
VGhpcyBpcyBCYXNlNjQ= | Letters and digits with = padding; no word spacing | Test Base64 on the encoding page |
c8c3dec9deccd1d1 | Only hex digits and even length | Convert the hex to bytes; consider XOR only if the challenge hints at it |
The first input is a classic-cipher candidate because a letter-only transformation could leave those word boundaries and repeated patterns in place. The other two should be classified as representations before you start shifting letters.
Each letter is shifted by a fixed number of alphabet positions. The alphabet wraps around after Z.
| Plaintext letter | Shift forward by 3 |
|---|---|
A | D |
B | E |
F | I |
G | J |
L | O |
X | A |
Y | B |
Z | C |
Apply the same shift to every letter:
| Position | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| Plaintext | F | L | A | G |
| Shift forward by 3 | I | O | D | J |
The encrypted text is IODJ. To decrypt it, shift every letter back by 3.
There are 25 non-identity shifts, so trying all of them is reasonable. Spaces and punctuation usually stay put, which is a clue: the transformation is acting on letters, not on the whole file.
On this platform, flags look like bitctf{{...}}. If a shift produces that prefix, treat it as a strong candidate and read the whole result.
ROT followed by a number.ROT13 is Caesar with a shift of 13. ROT5, ROT7, and similar names use the number as the shift. If the challenge does not give the shift, do not try to infer it from one character: test all 25 possibilities and read the results.
import string
ciphertext = "ovgpgs{{ebgngr_gur_nycunorg}}"
for shift in range(1, 26):
source = string.ascii_lowercase
target = source[-shift:] + source[:-shift]
plaintext = ciphertext.translate(str.maketrans(source, target))
print(f"ROT {shift:2}: {plaintext}")
const ciphertext = "ovgpgs{{ebgngr_gur_nycunorg}}";
const alphabet = "abcdefghijklmnopqrstuvwxyz";
for (let shift = 1; shift < 26; shift += 1) {
const plaintext = [...ciphertext].map(character => {
const index = alphabet.indexOf(character);
return index === -1
? character
: alphabet[(index - shift + 26) % 26];
}).join("");
console.log(`ROT ${shift}: ${plaintext}`);
}
In CyberChef, use ROT13 when the shift is known to be 13 or ROT13 Brute Force to display every rotation. dCode's Caesar tool is another quick way to compare all shifts.
Read the full candidates. A familiar prefix is useful evidence, but the rest of the plaintext should also make sense.
Each letter maps to another letter, but not by a single shift. The search space is far too big to brute-force by hand. Instead use what survived: repeated words, likely short words (A, I, THE), and letter frequency.
Caesar is a special case of substitution. If a uniform shift works, you do not need the harder method.
A substitution changes the letters but preserves their pattern:
| Word | Pattern | Possible ciphertext | What survived |
|---|---|---|---|
MEET | 0-1-1-2 | XQQM | The middle letter repeats |
NOON | 0-1-1-0 | ABBA | The first and last letters match |
TO BE TO | 0-1 / 2-3 / 0-1 | XR QL XR | The same two-letter word repeats |
These patterns do not reveal the answer by themselves. They let you test guesses without losing track of which letters must map consistently.
| Cipher | How it transforms text | Example and clue | First move |
|---|---|---|---|
| Caesar / ROT-n | Shifts every letter by the same amount; ROT13 means a shift of 13 | KHOOR ZRUOG keeps the space; shifting every letter back by 3 gives HELLO WORLD | Use the named shift or try all 25 |
| Atbash | Reverses the alphabet: A ↔ Z, B ↔ Y, and so on | SVOOL becomes HELLO; mirror or reversed-alphabet hints point to it | Apply Atbash once |
| Simple substitution | Replaces each letter with one fixed different letter | XQQM XQ XQQM preserves the doubled letter and repeated word shape | Test likely words and repeated patterns |
| Vigenère | Uses a repeating keyword, so the shift changes from letter to letter | LXFOPV EF RNHR does not yield to one Caesar shift; the challenge may hint at a keyword | Look for a key or key-length clue before choosing a solver |
| Playfair | Encrypts pairs of letters using a keyed 5×5 grid | BM OD ZB XD NA arrives naturally in pairs; look for grid or square hints | Find the keyword and build the grid |
| Rail Fence | Rearranges letters in a zigzag without replacing them | WECRLTEERDSOEEFEAOCAIVDEN contains the original letters in a scrambled order; look for rail or zigzag hints | Try a small number of rails |
This course focuses on Caesar and simple substitution. The other rows are recognition clues: use them when the challenge gives you a matching hint, not simply because Caesar failed.
A challenge gives you:
ovgpgs{{ebgngr_gur_nycunorg}}
Work through the evidence in order:
bitctf{{rotate_the_alphabet}}
The prefix and the readable phrase agree, so ROT13 is the answer. If no shift produced coherent text, the next reasonable test would be simple substitution rather than more Caesar guessing.
Classic ciphers are not acceptable protection for real data. In challenges the plaintext is often English or a flag. If none of the Caesar shifts is coherent, revisit the evidence before choosing another cipher family.
Text A
WKH FOXH LV WKH ZRUG
Text B
VGhpcyBpcyBCYXNlNjQ=
Which one is a Caesar candidate, and what should you do with the other?
Answer: Text A. Its spaces survived and WKH repeats, which are useful Caesar or substitution clues. Text B is Base64-shaped; decode it before you start shifting letters.
Indy's Scroll
Before trying tools, look at the text.