StegoToolkit

XOR Brute Force Tool

Brute-force single-byte XOR, break repeating-key XOR and recover keys from known plaintext. Ranked results with flag detection, all processed in your browser.

Single + repeating key
Crib / known plaintext
Ranked results
XOR Brute Forcer
Input format
0 bytes · limit 5 MiB (pasted, after decoding)
Try a sample:

🔒 Your input is processed locally in your browser. This tool does not send it to our servers or pass it to analytics or advertising code.

How to use the XOR brute forcer (5 steps)

  1. Add the data: Paste text, hex, Base64 or binary, or load a file. Limits: pasted input up to 5 MiB after decoding to bytes (the same limit for all four formats; it counts decoded bytes, not typed characters), uploaded files up to 20 MiB, data handed over from another tool up to 20 MiB. The Input tab shows the byte count and suggests a format without forcing it. The three samples load fixed examples.
  2. Pick what you know: On the Method tab choose: no key (single byte), a longer key, part of the plaintext (a crib), the key itself, two messages with one key, a whole file, a short multi-byte key, rolling or counter XOR, or a chain of steps.
  3. Read the ranked results: The Results tab ranks candidates by how much they read like text. A ranking is a heuristic, not a proof: check the preview before trusting it.
  4. Use a key and read the output: Use this key sends the decoded bytes to the Output tab: text, hex and Base64 views, a UTF-8 validity line and a download. Edit one byte of the key there and the output is recomputed.
  5. Send it on: Send the result to the Encoding Auto-Decoder, ROT Solver, Number Base Converter or Hex Viewer. The data is kept in this browser for up to 30 minutes and replaced by the next transfer; Clear shared data removes it now.

How XOR Encryption Works

XOR compares two bits and returns 1 only when they differ: 0 XOR 0 = 0, 0 XOR 1 = 1, 1 XOR 0 = 1, 1 XOR 1 = 0. Applied to a byte it flips every bit where the key byte has a 1. The key trick is that XOR undoes itself: (p XOR k) XOR k = p. So the same key encrypts and decrypts, and from any two of plaintext, key and ciphertext you can compute the third.

A worked byte: the letter f is 0x66 (01100110). With the key byte 0x2a (00101010) the result is 0x4c (01001100), the letter L. XOR 0x4c with 0x2a again and you are back at 0x66. Real CTF files repeat this for every byte; with a longer key, byte i is combined with key byte i mod key length.

Single-Byte XOR Brute Force

A one-byte key has only 256 possibilities, so the tool tries all of them and ranks the outputs. Printable text alone is a weak test: for the 16-byte sample 4c464b4d51524558754359754c5f4457, 50 of the 256 keys give output that is entirely ASCII printable (0x20–0x7E), and 53 if tab, line feed and carriage return are also allowed. The ranking therefore uses an English score as well, plus a flag-prefix badge.

The English score compares the letter-and-space mix of the output with English (26 letters and the space; digits and punctuation are neutral), multiplies by the share of bytes that count and subtracts a penalty for control and high bytes. For text in scripts without ASCII letters (Chinese, for example) the English score is near zero, so the tool also measures the share of bytes inside valid multi-byte UTF-8 sequences (counted only when at most 2% of the bytes are invalid) and ranks by the larger of the two, the text score. The table is sorted by flag-prefix tier, then text score, then text-like share, then the key. Entropy is shown as a hint and never used for ranking. Key 0x00 appears as the unchanged input so you can see it is a candidate, not a result.

Repeating-Key XOR: Finding the Key Length

When the key is longer than one byte, the tool scores every length from 2 to 40 that has at least 8 × length bytes of data with two measures. The Hamming score takes the bit distance between four pairs of neighbouring blocks, averages them and divides by the length (lower is better). The Index of Coincidence is computed per column and averaged (higher is better). Each measure ranks the lengths, the two ranks are averaged, and ties go to the smaller length.

This is a guided repeating-key attack, not an exhaustive search of every possible multi-byte key: statistical key-length estimates and per-column scoring narrow the candidates (the top 3 key bytes per column), and you can correct any byte by hand. Length detection is ambiguous by nature, so the tool shows the combined top 5 plus the top 3 of each measure, says when the two measures disagree and lets you type any length from 1 to 64. For the 228-byte prose fixture encrypted with the key ICE (true length 3), the combined top 5 is 24, 27, 6, 12, 18; length 3 appears only through the Index of Coincidence top 3, and the tool shows the disagreement notice. For the same text with the key flag (true length 4), length 28 ranks first and length 4 second, which is the Index of Coincidence favouring multiples when columns are short.

When most of the best lengths share a divisor that is not itself listed (for example 36, 33, 6, 24 and 30 all divide by 3), the tool adds a hint to check that divisor, because multiples of the true length often score best; it is a hint and never a decision. Once a length is chosen each column is solved as a single-byte XOR with the English score, and the top 3 key bytes per column stay clickable so a wrong byte can be changed. There is also a most-frequent-character mode: tell the tool the most common plaintext byte (space or null) and each key byte is taken from the most common ciphertext byte in its column.

Known-Plaintext Attack (Crib)

If you know any part of the plaintext, the key is the ciphertext XOR the known bytes. Enter the crib, the byte offset where it sits in the ciphertext and, if you know it, the key length. Key position for crib byte i is (offset + i) mod length. If two recovered bytes land on the same key position and differ, that length is rejected and the first conflict is shown.

Without a length the tool tests every period shorter than the crib and proposes the smallest consistent one. On the sample 0d09180c1e010417260216260d101716 the crib flag{ at offset 0 recovers the bytes k e y k e; periods 1, 2 and 4 are inconsistent, 3 is consistent and the key is key. The crib xor at offset 5 with length 3 recovers y, k, e at key positions 2, 0, 1 — the first recovered byte is key byte 2, not byte 0. A crib that covers only some key positions leaves ? at the others and the tool will not decrypt until they are filled.

File header cribs apply the same idea to the start of common files: MZ (4D 5A), ZIP (50 4B 03 04), PNG (the first four signature bytes, 89 50 4E 47), GIF (47 49 46 38, “GIF8”), PDF (25 50 44 46, “%PDF”), ELF (7F 45 4C 46) and gzip (1F 8B 08). Only these leading bytes are used, so a header crib fixes at most four key bytes. If every derived key byte is equal, that is a single-byte key (MZ 90 00 encrypted with 0x5c starts 11 06 cc 5c, and the MZ header gives 0x5c).

XOR Crib Dragging and the Two-Time Pad

If two messages were encrypted with the same keystream starting at the same position, XORing the two ciphertexts cancels the keystream and leaves plaintext 1 XOR plaintext 2. Guess a word in one message and slide it along; the bytes it implies in the other message are shown at every offset, and readable ones are highlighted. Equal key length is not enough: with a repeating key the same key started at a different phase does not cancel.

Example: attack at dawn and retreat at six, both encrypted with the repeating key K3y!. The crib “ at ” at offset 6 gives “t at” in the other message. When the second message is shifted by one key position, the same crib gives 2c 4a 19 3e, which is not text — the method does not apply. If the messages differ in length, only the overlap is used and the extra bytes are reported as unmatched.

File Scan, Multi-Byte Keys, Rolling XOR and Chained Steps

File scan searches for text-like runs and selected file signatures under each of the 256 single-byte keys; it does not decrypt and validate the whole file, and a hit does not prove that a recovered file is valid or fully decrypted. It covers a whole file or a byte range, read in 1 MiB pieces. For each key it reports the longest text-like run, the number of runs of at least N bytes (default 16) and signature candidates for ZIP, PNG, PDF, GIF and ELF at any offset, and MZ only at the start of the range. Runs and signatures that cross a 1 MiB boundary are counted once. You can cancel; a cancelled scan keeps what it found and is labelled partial.

Single-byte search versus multi-byte search: the single-byte mode tests exactly 256 keys and ranks them, so its limit is that the ranking can mislead on short data; the multi-byte mode is a bounded exhaustive search whose key count depends on the key length and the byte set you allow, so its limit is a search space that can become enormous. Multi-byte keys: a 2-byte key has 65,536 possibilities; a 4-byte key over every byte value has 4,294,967,296, which the page refuses to start. Pick a smaller byte set (printable characters, letters and digits, lowercase letters or hex digits) and the page shows the exact key count, measures this device's speed on a short test and gives a time estimate — an estimate, not a promise. Keys are screened on the first 256 bytes.

Rolling XOR uses the previous byte as part of the next byte's key, and the two variants behave differently: with the previous ciphertext byte (c[i] = p[i] XOR c[i-1]) the start value affects only the first plaintext byte; with the previous plaintext byte (c[i] = p[i] XOR p[i-1]) the start value carries through every later byte. Counter XOR changes the key by position: c[i] = p[i] XOR ((start + i × step) mod 256), with a step you set (default 1). The tool tries all 256 start values for each mode. A chained-steps panel runs XOR, Base64 decode or encode and hex decode or encode in order and keeps every stage. A settings link copies only the method, format, flag switches, offset, key length and charset — never the input, a key, a crib or any output.

Why Printable Does Not Mean Correct

Short ciphertexts decode to printable-looking text under many keys: 50 of 256 for the 16-byte sample. Treat the top row as a lead. Check that the preview is a sentence you recognise, that the flag badge (if any) matches a prefix you expect, and that the UTF-8 line reports no invalid sequences. Binary payloads are legitimate: a candidate with control bytes is ranked lower, never removed.

When the Output Looks Wrong

Garbled output usually means a wrong key length or one wrong key byte (compare the neighbouring candidates in the column solver), data that was not XOR to begin with (try the Encoding Auto-Decoder first for Base64 or hex layers), a key that is longer than the data allows the length detection to see (fewer than 8 × length bytes), or a variant such as rolling XOR. Null bytes in the input and the key are preserved, so an all-zero stretch of output often means the key byte equals the ciphertext byte there.

Examples

Input: 4c464b4d51524558754359754c5f4457 (hex), Single byte

Result: Rank 1: key 0x2a, flag{xor_is_fun}, badge “starts with flag{ (heuristic)”. 50 of 256 keys are entirely ASCII printable, 53 text-like.

Meaning: Many keys look like text. Here the flag badge is what puts the real key first: with only 16 bytes and few letters, its English score is lower than several wrong keys' scores, so a short sample should be judged by the preview and the badge, not the score alone.

Input: 0d09180c1e010417260216260d101716 (hex), crib flag{ at offset 0

Result: Recovered bytes k e y k e. Periods 1, 2 and 4 are inconsistent; period 3 is proposed; key key; output flag{xor_is_fun}.

Meaning: Five known bytes were enough because the key repeats every three.

Input: Same ciphertext, crib xor at offset 5, key length 3

Result: Recovered y, k, e at key positions 2, 0, 1; assembled key key.

Meaning: The first recovered byte is key byte 2 because 5 mod 3 = 2.

Input: 228-byte prose, key ICE (hex fixture)

Result: Combined top 5 lengths: 24, 27, 6, 12, 18. Length 3 appears via the IoC top 3 and the methods disagree. Column solving at length 3 returns ICE.

Meaning: Detection is ambiguous; type the length you suspect.

Input: MZ 90 00 with key 0x5c

Result: 11 06 cc 5c; the MZ header crib gives 0x5c for both bytes.

Meaning: A file header is a ready-made crib.

Input: attack at dawn / retreat at six, key K3y! (aligned)

Result: Crib “ at ” at offset 6 gives “t at”. Shifted by one key position it gives 2c 4a 19 3e.

Meaning: The method works only when the keystream lines up.

Input: this is a test vs wokka wokka!!!

Result: Hamming distance 37 bits.

Meaning: The distance behind the key-length score.

Input: Bytes 6162ffc3a9e282 in the output

Result: 2 invalid UTF-8 sequences (3 bytes): the stray ff and the truncated e2 82.

Meaning: Invalid sequences are counted, never silently replaced.

How it works

1. Parse

The input is decoded to bytes in the format you chose: hex accepts spaces, new lines, commas, 0x and \x prefixes and names the position of an odd digit; Base64 accepts both alphabets with or without padding; binary needs a multiple of 8 bits. The size cap applies to decoded bytes.

2. Try the keys

Heavy work runs in a Web Worker so the page stays responsive. Single-byte scoring covers all 256 keys; inputs over 1 MiB are ranked on their first 64 KiB and the full decode runs when you pick a key; a key-byte column longer than 64 KiB is scored on its first 64 KiB.

3. Score

English score = fit × coverage × (1 − penalty), with fit measured against a 27-symbol table (26 letters and space). The text score is the larger of the English score and the share of valid multi-byte UTF-8 text. Ranking order: flag-prefix tier, text score, text-like share, key value.

4. Show alternatives

Key lengths come with both scores and both ranks; each key byte keeps its top 3 candidates; a crib shows every recovered byte with its key position and every consistent period.

5. Output safely

The text view draws every non-printable byte as a dot and counts them (hex and Base64 views are one click away), and a byte-level UTF-8 validator reports invalid sequences instead of replacing them. Output is rendered as plain text only.

What the results mean

ResultWhat it meansWhat to do
starts with flag{ (heuristic)The decoded bytes start with that prefix at the offset you set, compared case-sensitively.Read the whole output: a matching prefix is a lead, not proof. Prefixes under 3 bytes get the badge but no ranking boost.
Possible textAt least 90% of the output bytes are text-like.Check that it makes sense; text-like bytes also occur by chance.
The two methods disagreeThe Hamming and Index of Coincidence rankings put different lengths first.Try several lengths; check smaller divisors of the top ones.
Most of the best lengths are multiples of NThe top lengths share the divisor N and N itself is not listed.Try N as the key length; the real key is often the divisor.
Not enough dataA length needs at least 8 × length bytes to be scored.You can still type that length by hand.
No evidence of a periodNo period shorter than the crib is consistent.Type the key length, or use a longer crib.
ConflictTwo recovered bytes for the same key position differ at that length.That length is rejected; try another or check the offset.
Partial: scanned X of Y bytesA file scan was cancelled.The numbers cover only the scanned part.
N invalid sequences (M bytes)The output is not valid UTF-8 at those places.Normal for binary output; for text, suspect a wrong key byte.

Limitations

  • Rankings are heuristics. Very short data (the 16-byte sample's real key has a lower English score than several wrong keys), source code and binary payloads can rank below a wrong key, so check the preview.
  • The flag badge only compares bytes at the offset you set; flags that start later or use another prefix need a custom prefix or offset.
  • Key-length detection needs about 8 × length bytes and can favour multiples of the true length; it is a suggestion, never a decision.
  • Pasted input is limited to 5 MiB after decoding, files to 20 MiB, and data sent to another tool to 20 MiB. Inputs over 1 MiB are ranked on their first 64 KiB, so the ranking may not reflect patterns that occur later in the data (a correct key can rank low when the start is not representative); picking a key still decrypts the whole input.
  • The multi-byte search is bounded: more than 100,000,000 keys is refused, and its time estimate comes from a short test on your device.
  • The ranking is tuned for text with ASCII letters. In a limited benchmark (one 20 KB slice of one Project Gutenberg book per language, six different random keys per language; not six independent texts and not a broad multilingual validation) the single-byte key ranked first in 6 of 6 cases for Spanish, German, French, Russian and Chinese (for scripts without ASCII letters the share of valid multi-byte UTF-8 text is used), and a 5-byte repeating key was recovered exactly in 6 of 6 cases for all five (reproduce with npm run test:external:ctf-xor after downloading the books). A key-byte column of Chinese text is not recognisable on its own, so the column solver also checks whether neighbouring columns together make valid UTF-8 and switches to that reading only when the decoded sample scores clearly higher as valid UTF-8 text. That test used one Chinese book (a 20 KB slice of a Qing-dynasty novel) and keys of 2 to 13 bytes. Limits: on a synthetic text of Chinese characters only (no ASCII at all) a key whose length is a multiple of 3 was not recovered (the solver returned a different key), because the low bits of a continuation byte cannot be told apart without a known plaintext; use a crib or a flag prefix there. A separate measurement on plain-text extracts of Japanese, Korean and Chinese Wikipedia articles (2 or 3 articles per language, 24 random trials per size, keys of 3, 5, 6, 8 and 9 bytes, the true key length given to the column solver) recovered the repeating key exactly in 24 of 24 trials for all three languages at 20 KB; at 2 KB in 23 to 24 (Japanese), 24 (Korean) and 18 to 24 (Chinese) of 24; at 500 bytes in 16 to 24 (Japanese), 23 to 24 (Korean) and 5 to 24 (Chinese) of 24. At 200 bytes or less some key lengths fall to 0 to 5 of 24, and the single-byte key ranked first in only 4 to 13 of 24 trials. Key lengths that are multiples of 3, and 9 in particular, are the weakest, and the automatic length suggestion often puts a multiple of the true length first, so check the other length chips. These are small benchmarks, not a general validation for these languages; other scripts are untested.
  • Rolling XOR with the previous ciphertext byte depends on the start value only for the first plaintext byte, so every start value gives the same text after it; rolling XOR with the previous plaintext byte and counter XOR depend on it throughout.
  • The two-time-pad method only works when both messages used the same keystream at the same positions.
  • A file-signature hit means the first bytes match, not that the file is valid. Scan timing has not been benchmarked and no speed figure is claimed.
  • Only XOR-style ciphers: no AES, RSA or hash cracking, and no server-side processing.

Privacy

Your input is processed locally in your browser. This tool does not send it to our servers or pass it to analytics or advertising code: what you type is never put in the page address, analytics events carry feature names only, and decoded output is rendered as plain text. This statement is about this tool's own code; it does not cover third-party scripts, and a browser page cannot fully prevent other scripts on the same page from reading it. Optional analytics and advertising scripts load only after you accept optional cookies (before any choice, a network log of this page shows no request to any other host); if you accept them, those providers' scripts load and can see the page. The page itself has no ad slots. Files are read locally and never uploaded. If you use Send to another tool, the result (at most 20 MiB) is stored in your browser's IndexedDB so the next page can read it; it is not sent to a server, the next page ignores it after 30 minutes, a newer transfer replaces it and Clear shared data removes it at once. Deleting it when you close the tab is not guaranteed. Only your pinned result tabs are remembered in localStorage — never your input, key, crib or output.

Frequently Asked Questions

What is XOR encryption?

XOR combines each data byte with a key byte bit by bit: a result bit is 1 only where the two bits differ. Because XOR undoes itself, the same key encrypts and decrypts. It is simple, common in CTF puzzles and malware obfuscation, and weak when the key is short or reused.

How do I brute-force a single-byte XOR key?

Paste the data, choose “I don't know the key (single byte)” and press Try all 256 keys. The table ranks the 256 outputs by likelihood of readable text; Use this key shows the full decoded output. This is also the way to approach an xor decrypt online question when the key is one byte.

Why do many keys give printable output?

Short data decodes to printable bytes under many keys. For the 16-byte sample, 50 of 256 keys give output that is entirely ASCII printable (0x20–0x7E) and 53 if tab, LF and CR are allowed. That is why the ranking uses an English score and a flag badge instead of printability alone.

How does the tool rank results?

In order: a flag-prefix match of at least 3 bytes, the text score (the English score, how close the letter-and-space mix is to English and reduced by control and high bytes, or for scripts without ASCII letters the share of valid multi-byte UTF-8 text, whichever is larger), the share of text-like bytes, then the key value. The ranking is a heuristic, not a probability, and entropy is shown only as a hint.

How do I find the key length of repeating-key XOR?

Choose “Key is longer than one byte” and press Find likely key lengths. Each length from 2 to 40 with at least 8 × length bytes gets a Hamming score and an Index of Coincidence score; the two ranks are averaged. Pick a chip, or type a length yourself, to solve the columns.

Why can key-length detection give more than one answer?

Short or unusual text weakens both measures, and multiples of the true length often score well. In the 228-byte fixtures, the true length 3 is not in the combined top 5, and for a key of length 4 the length 28 ranks first. The tool shows several candidates, tells you when the two methods disagree and accepts any length you type.

What is a known-plaintext (crib) attack?

If you know some plaintext and where it sits in the ciphertext, the key bytes there are ciphertext XOR plaintext. Enter the crib and its offset; with a key length the key wraps around and conflicting bytes reject that length, without one the smallest consistent period is proposed.

Can I recover the key if I know the flag format?

Yes, when the flag is at a known offset: the crib presets flag{, CTF{, HTB{ and picoCTF{ use offset 0. The first five key positions come out directly; with the key length entered, the key is complete only when the crib covers every key position (for flag{ that means a key of at most 5 bytes), otherwise the missing positions show as ? until another crib fills them.

What input formats are supported?

Text (UTF-8), hex (spaces, 0x and \x prefixes accepted), Base64 (standard and URL-safe, padding optional) and binary, plus file upload up to 20 MiB. Pasted input is limited to 5 MiB after decoding.

Is my data uploaded?

Your input is processed locally in your browser. This tool does not send it to our servers or pass it to analytics or advertising code. Third-party scripts are not covered by that statement: a browser page cannot fully prevent other scripts on the same page from reading it, and the absence of network requests from this tool does not prove otherwise. On this site, analytics and advertising scripts load only after you accept optional cookies; in a browser test with a network log, loading this page before any cookie choice contacted no host other than this site. If you accept optional cookies, those providers' scripts load and can see the page. The page has no ad slots. Analytics events carry feature names only.

What is a two-time pad?

Two messages encrypted with the same keystream at the same positions. XORing the ciphertexts removes the keystream and leaves the XOR of the two plaintexts; dragging a guessed word across reveals the other message. It is available under “Two messages, same key”, and only applies when the keystreams line up.

Why does the result contain unreadable characters?

Usually a wrong key or key length, one wrong key byte, or data that is not XOR-encrypted. Non-printable bytes are shown as dots and counted, and the UTF-8 line reports invalid sequences. Compare the next-best candidates or change one key byte on the Output tab.

How is this different from the Encoding Auto-Decoder's XOR check?

The Encoding Auto-Decoder peels encoding layers (Base64, hex, URL and more) and includes a quick single-byte XOR attempt as one step. This tool is the full workbench: ranked 256-key results, key-length analysis, column solving, cribs, two messages, file scans and bounded multi-byte searches.