Skip to content
All tools
Classical cryptoRuns locallyNo account

XOR cipher decoder and key recovery

XOR text or hex against a key, brute-force single-byte XOR by English scoring, and recover repeating-key XOR by Hamming-distance keysize detection.

Open in ctfpal

XOR is the workhorse of CTF crypto because it is symmetric, byte-oriented, and trivial to implement badly. Every XOR challenge is one of three shapes: a single-byte key, a short repeating key, or a key as long as the message that got reused.

Single-byte XOR: 256 candidates

Try all 256 bytes and score each result for English-likeness. This is the same chi-squared machinery the Caesar solver uses, extended to bytes rather than letters, with a bonus for printable characters and for flag-shaped substrings. It is exhaustive and instant.

Repeating-key XOR: find the keysize first

For a repeating key, the trick is the normalised Hamming distance. Take two adjacent blocks of length K, count the differing bits, divide by K. When K is the true keysize, both blocks were XORed with the same key bytes, so the distance reflects only the plaintext difference and drops sharply. Test K from 2 to 40, take the lowest few, then split the ciphertext into K columns - each column is single-byte XOR, solved by the previous step.

def normalised_distance(data, k):
    blocks = [data[i * k:(i + 1) * k] for i in range(4)]
    pairs = [(a, b) for i, a in enumerate(blocks) for b in blocks[i + 1:]]
    total = sum(hamming(a, b) for a, b in pairs) / len(pairs)
    return total / k          # normalise so keysizes are comparable

best = sorted(range(2, 41), key=lambda k: normalised_distance(ct, k))[:3]
Keysize detection by normalised Hamming distance

Worked example

Single-byte XOR

Input

322b212d011604393a72301d73311d30713471303173202e713f

Result

picoCTF{x0r_1s_r3v3rs1bl3} (key 0x42), ranked first out of all 256 key bytes by English score

Hex input, single-byte key. The brute force is exhaustive - no guessing required.

Load this example in the workspace

Part of a module

4. XOR and the cost of reusing a key

Break single-byte and repeating-key XOR, then recover both plaintexts from a reused one-time pad by crib dragging.

Practise on real challenges

Go deeper

  • XOR, crib dragging, and the two-time padSingle-byte XOR, repeating-key XOR, and keystream reuse are three faces of the same weakness. How to recover a key length from Hamming distance, drag a crib across a XOR of two plaintexts, and know when a stream cipher has handed you the answer.

Related tools