A small cross-platform CLI tool for XOR-ing strings and files with a key.
Why
Apply the same key twice and your data comes back exactly as it was. That makes XOR the simplest building block for quickly scrambling a file, protecting it with a one-time pad, or checking that two tools agree on the same result.
What ships
A single ready-to-run file: no installer, no dependencies to chase, nothing extra to copy next to it. Any file size is possible, from a handful of bytes all the way up to very large archives, with no change to the command.
Where it runs
The same utility runs on Linux, FreeBSD, OpenBSD, NetBSD, and Windows. Each platform gets its own native binary built from the exact same source, so what you learn on one system carries over to every other one without surprises.
String, single file, or two files at once.
Scramble a short message
Mix a short piece of text with a key and print the scrambled result. Give the same text and the same key again and the original comes back — handy for quick checks and experiments.
itps_xor xor-string "hello world" --key "my key"
Scramble a single file
Mix any file with a key to make a scrambled copy next to the original. Run the same command a second time with the same key and the file is back exactly as it started, bit for bit.
itps_xor xor-file -i notes.txt -o notes.scrambled --key "my key"
Scramble two files into one
Combine two files into a single scrambled one. That is how a secret and a shared key get joined — having only one of the two reveals nothing useful about the other on its own.
itps_xor xor-files message.txt sharedkey.bin -o combined.bin
Pass the key however it is easiest for your workflow.
--keyPlain UTF-8 text, applied cyclically.
--hex-keyHexadecimal key string, decoded to raw bytes.
--b64-keyBase64-encoded key, decoded to raw bytes.
--key-fileKey read from a binary file, applied cyclically.
Full reference ships with the binary.
itps_xor --help
itps_xor --version
Common recipes taken straight from itps_xor --help.
itps_xor xor-file -i file1.bin -o file1.enc --key "MySecret"
Result: A new file file1.enc appears next to the original. Each byte of file1.bin has been XOR-ed with the ASCII bytes of MySecret, cycling the key over the length of the input.
itps_xor xor-file -i file1.enc -o file1.dec --key "MySecret"
Result: file1.dec is bit-for-bit identical to the original file1.bin. There is no separate decrypt mode — XOR is its own inverse.
cat file1.bin | itps_xor xor-file --key "MySecret" > file1.enc
Result: Same output as the first example, but produced in a single pipeline — nothing is written to disk until the shell redirects the final stream into file1.enc.
itps_xor xor-file -i file1.bin -o file1.enc --key-file key.bin
Result: file1.enc is file1.bin XOR-ed against the raw bytes of key.bin, cycled as needed. The key can be any size up to the input itself.
itps_xor xor-files plaintext.bin pad.bin -o ciphertext.bin
Result: ciphertext.bin is the byte-wise XOR of the two inputs. If pad.bin was truly random and used only once, the output is a mathematically perfect one-time pad.
itps_xor xor-files big.bin small.bin -o out.bin --pad-zero
Result: out.bin has the length of big.bin. Where small.bin runs out, its bytes are treated as zero — so the tail of big.bin passes through unchanged.
itps_xor xor-string "hello" --key "secret"
Result: Prints a single line of hexadecimal to stdout — the XOR of the UTF-8 bytes of hello against the cycled UTF-8 bytes of secret.
itps_xor xor-string DEADBEEF --input-format hex --hex-key 01020304 --output-format raw > out.bin
Result: Both input and key are decoded from hex to 4 raw bytes, XOR-ed, and written to out.bin as 4 binary bytes with no newline — no textual encoding on the way out.
What itps_xor returns to the shell when it finishes.
| Code | Meaning | When you see it |
|---|---|---|
0 |
success | The command finished and produced the output you asked for. |
1 |
runtime error | Something failed while the command was already running — an I/O problem, a bad or missing key, two input files whose lengths do not match, and similar. |
2 |
bad arguments | The command line itself was not valid — a typo, a missing required flag, or two flags that cannot be used together. |