Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

First Code: A Naive XOR Encryptor

Let’s write our first cryptographic algorithm — or at least something that looks like one.

We’ll implement a simple XOR cipher. This method is insecure and should never be used in real applications — but it’s the perfect teaching tool.

What’s a Cipher?

A cipher is just a method to transform readable data (plaintext) into unreadable data (ciphertext) using a key — and vice versa.

🧭 Word Origin — “Cipher” The word comes from the Arabic “ṣifr” (صفر), meaning “zero” or “empty”. It passed through Latin (cifra), then into French and English as cipher.

What started as a symbol for “nothing” evolved into a word for secret writing — and eventually, encryption algorithms.

What is XOR?

XOR stands for “exclusive or”, a bitwise operation:

ABA XOR B
000
011
101
110

In short: XOR returns 1 if the bits differ, 0 if they’re the same.

The XOR operation flips bits when they differ:

1 ^ 0 = 1
1 ^ 1 = 0
0 ^ 0 = 0

When used for encryption:

cipher = plaintext ^ key
plaintext = cipher ^ key

That’s why XOR can be used to encrypt and decrypt data — if you XOR something twice with the same key, you get the original back.

✅ Simple, reversible, fast — but also dangerously weak when misused.

XOR, Bit by Bit

To truly understand XOR in cryptography, it helps to look at bit-level behavior.

Let’s say you compute:

100 ^ 1

This doesn’t mean 100 to the power of 1. In Rust, ^ is the bitwise XOR operator.

Step-by-step:

100 = 0110 0100
1   = 0000 0001
---------------
XOR = 0110 0101 = 101

✅ Each bit is compared: If they’re different → 1 If they’re the same → 0

100 ^ 1 = 101

This is what makes XOR useful: you can toggle bits with a key, and reverse it by applying the same key again.

Why This?

This example teaches you:

  • The reversible nature of XOR (a ^ b ^ b == a)
  • Handling bytes and slices in Rust
  • Thinking about encryption as a transformation
  • Why key reuse and simplicity are dangerous

Naive XOR in Rust

Here’s how to implement a basic XOR encryptor in Rust:

Filename: src/main.rs

fn main() {
    let message = b"hello world";
    let key = b"key";

    let encrypted = xor_encrypt(message, key);
    let decrypted = xor_encrypt(&encrypted, key);

    println!("Encrypted: {:x?}", encrypted);
    println!("Decrypted: {}", String::from_utf8_lossy(&decrypted));
}

pub fn xor_encrypt(input: &[u8], key: &[u8]) -> Vec<u8> {
    input
        .iter()
        .enumerate()
        .map(|(i, &byte)| byte ^ key[i % key.len()])
        .collect()
}

Output

The output will show the encrypted bytes (in hex) and the original decrypted message.

What’s Wrong With This Cipher?

  • Key reuse makes patterns obvious
  • No randomness or initialization vector (IV)
  • Susceptible to frequency analysis attacks

This cipher is insecure — but it demonstrates important cryptographic concepts:
  • Reversibility
  • Byte-wise transformations
  • Why randomness and key handling matter

You’ll build on this when implementing real-world ciphers like ChaCha20 or AES.