1. Home
  2. Cryptography & Network Security
  3. Caesar & Vigenère Ciphers

Caesar & Vigenère Ciphers

The two classic shift ciphers. Caesar moves every letter by the same amount; Vigenère uses a key word to give every letter its own shift.

Interactive 3DBeginner10 min readCNSUpdated

Drag to rotate · Right-drag to pan · Click, then scroll to zoom · Space play · ←→ step

What's happening

Pseudocode

    Try this in the 3D model

    • Press Encrypt. Do the three Ts of ATTACKATDAWN all turn into the same letter?
    • The message box now holds the ciphertext. Press Brute force. At which key does readable English appear?
    • Switch to Vigenère and press Encrypt with the key LEMON. What happens to the Ts now?
    • With Caesar, encrypt twice with key 13. Why do you get your message back?

    Some words first

    Cryptography has its own vocabulary, and every exam answer uses it:

    • Plaintext: the readable message, like ATTACK AT DAWN.
    • Ciphertext: the scrambled message that is actually sent.
    • Key: the secret that sender and receiver share. Without it, the ciphertext should be useless.
    • Encryption turns plaintext into ciphertext. Decryption turns it back.

    The two ciphers on this page are symmetric: the same key locks and unlocks the message. They are thousands of years too old to protect anything today, but every idea in modern cryptography, including AES, started with them.

    The Caesar cipher

    Julius Caesar hid his military orders by moving every letter 3 places along the alphabet: A became D, B became E, and so on, wrapping around from Z back to A. Number the letters A = 0, B = 1, …, Z = 25. With a key k:

    • Encrypt: c = (p + k) mod 26
    • Decrypt: p = (c − k) mod 26

    The “mod 26” is what makes the alphabet a circle, which is why the 3D model draws it as a cipher wheel. Turn the inner ring k places and every plaintext letter on the outside sits above its ciphertext letter on the inside.

    Worked example: ATTACKATDAWN, key 3

    Plaintext A T T A C K A T D A W N
    Position 0 19 19 0 2 10 0 19 3 0 22 13
    + 3, mod 26 3 22 22 3 5 13 3 22 6 3 25 16
    Ciphertext D W W D F N D W G D Z Q

    The ciphertext is DWWDFNDWGDZQ.

    Breaking Caesar

    Caesar has two fatal weaknesses.

    1. Only 25 keys. An attacker just tries every shift and keeps the one that reads like English. That is a brute-force attack. Press Brute force in the model and it takes 25 steps.
    2. Letter counts survive. Every A becomes the same letter, so the most common ciphertext letter is probably E (12.7 % of English text), then T, then A. This is frequency analysis, first described by the Arab scholar Al-Kindi in the 9th century.

    ROT13, a Caesar shift of 13, is still used online to hide spoilers. Because 13 + 13 = 26, applying it twice gives back the original.

    The Vigenère cipher

    Vigenère fixes the second weakness by using many Caesar shifts. The key is a word, written again and again under the message. Each key letter gives the shift for the letter above it (A = 0, B = 1, …):

    • Encrypt: cᵢ = (pᵢ + kᵢ mod m) mod 26
    • Decrypt: pᵢ = (cᵢ − kᵢ mod m) mod 26

    Here m is the length of the key. A cipher that switches between several substitution alphabets like this is called polyalphabetic. Caesar uses only one alphabet, so it is monoalphabetic.

    Worked example: ATTACKATDAWN, key LEMON

    Plaintext A T T A C K A T D A W N
    Key L E M O N L E M O N L E
    Shift 11 4 12 14 13 11 4 12 14 13 11 4
    Ciphertext L X F O P V E F R N H R

    The ciphertext is LXFOPVEFRNHR. The first A became L but the second A became O. The same plaintext letter now hides behind different ciphertext letters, so simple letter counting no longer works. For 300 years Vigenère was called le chiffre indéchiffrable, the unbreakable cipher.

    Textbooks often show the Vigenère square (tableau): a 26 × 26 table whose row is the key letter and whose column is the plaintext letter. Reading the table is exactly the same as turning the wheel to the key letter.

    Breaking Vigenère

    In 1863 Friedrich Kasiski published the attack.

    1. Find the key length m. Repeated chunks of ciphertext usually come from the same plaintext chunk meeting the same part of the key. The distances between repeats are multiples of m (the Kasiski examination). The index of coincidence gives the same answer statistically.
    2. Split the ciphertext into m columns. Letters 0, m, 2m, … were all shifted by the first key letter, so each column is just a Caesar cipher.
    3. Break each column with frequency analysis.

    The lesson: a short key that repeats leaks patterns. If the key is truly random, as long as the message and never reused, Vigenère becomes the one-time pad, which is provably unbreakable. The catch is sharing that much key safely, which is the problem that Diffie–Hellman and RSA later solved.

    Code

    def shift(ch: str, k: int) -> str:
        return chr((ord(ch) - ord("A") + k) % 26 + ord("A"))   # A = 0 … Z = 25
    
    def caesar(text: str, k: int) -> str:
        return "".join(shift(ch, k) if ch.isalpha() else ch for ch in text.upper())
    
    def vigenere(text: str, key: str, decrypt: bool = False) -> str:
        out, j = [], 0
        for ch in text.upper():
            if not ch.isalpha():
                out.append(ch)                     # keep spaces and punctuation
                continue
            k = ord(key[j % len(key)].upper()) - ord("A")
            out.append(shift(ch, -k if decrypt else k))
            j += 1                                 # only letters use up key letters
        return "".join(out)
    
    print(caesar("ATTACK AT DAWN", 3))                    # DWWDFN DW GDZQ
    print(vigenere("ATTACK AT DAWN", "LEMON"))             # LXFOPV EF RNHR
    print(vigenere("LXFOPV EF RNHR", "LEMON", True))       # ATTACK AT DAWN
    
    for k in range(1, 26):                                 # brute force
        print(k, caesar("DWWDFN DW GDZQ", -k))             # k = 3 reads ATTACK AT DAWN
    #include <cctype>
    #include <iostream>
    #include <string>
    using namespace std;
    
    string vigenere(const string& text, const string& key, bool decrypt = false) {
        string out;
        size_t j = 0;
        for (char ch : text) {
            if (!isalpha(static_cast<unsigned char>(ch))) { out += ch; continue; }
            int x = toupper(ch) - 'A';
            int k = toupper(key[j++ % key.size()]) - 'A';
            if (decrypt) k = 26 - k;                   // moving back k = moving forward 26 − k
            out += char('A' + (x + k) % 26);
        }
        return out;
    }
    
    // Caesar is Vigenère with a one-letter key: shift 3 is the key "D".
    string caesar(const string& text, int k) {
        return vigenere(text, string(1, char('A' + (k % 26 + 26) % 26)));
    }
    
    int main() {
        cout << caesar("ATTACK AT DAWN", 3) << '\n';                  // DWWDFN DW GDZQ
        cout << vigenere("ATTACK AT DAWN", "LEMON") << '\n';          // LXFOPV EF RNHR
        cout << vigenere("LXFOPV EF RNHR", "LEMON", true) << '\n';    // ATTACK AT DAWN
    }

    Caesar vs Vigenère

    Caesar Vigenère
    Key One number, 0–25 A word of m letters
    Shifts per message One m different shifts, repeating
    Type Monoalphabetic Polyalphabetic
    Number of keys 25 26^m
    Same plaintext letter Always the same ciphertext letter Can become different letters
    Broken by Brute force or frequency analysis Kasiski examination, then frequency analysis per column

    Common mistakes

    • Forgetting to wrap around. W + 3 is Z, but X + 3 is A, not a symbol after Z. Always take the result mod 26.
    • Negative numbers when decrypting. C − 5 = 2 − 5 = −3, and −3 mod 26 = 23 = X. In C++ the % operator can return a negative number, so add 26 first.
    • Starting at A = 1. The formulas need A = 0. With A = 1, the key A would shift by one instead of not at all.
    • Using up key letters on spaces. In Vigenère only letters consume key letters, so ATTACK AT DAWN and ATTACKATDAWN give the same letters.

    Complexity at a glance

    Case / operationTimeWhy
    Encrypt or decrypt n lettersO(n)One addition mod 26 per letter.
    Caesar brute force25 · O(n)Only 25 keys to try.
    Vigenère keys of length m26^mAlready 11.9 million for m = 5.
    Breaking Vigenère once m is knownm Caesar ciphersEach column is a Caesar cipher with 25 keys.

    Quick check

    Test yourself — pick an answer to see if you got it.

    1. What is XYZ encrypted with a Caesar cipher, key k = 3?

    2. Decrypt KHOOR with a Caesar cipher, key k = 3.

    3. With Vigenère, the plaintext letter H meets the key letter C. Which ciphertext letter do you get?

    4. How many keys does an attacker need to try, at most, to break a Caesar cipher?

    5. Why is Vigenère harder to break with simple letter counting than Caesar?

    Saved in this browser.
    Spotted a mistake or a bug in the 3D model?

    Report a mistake

    in Caesar & Vigenère Ciphers. Thank you — every report makes the lesson better for the next reader.

    We'll also include a link to the step of the 3D model you're on and your browser type, so we can reproduce it.