Skip to content

Vigenère Cipher (Cifra de Vigenère)

The Vigenère cipher is a polyalphabetic substitution cipher that was once considered one of the best classical ciphers. Named after Blaise de Vigenère, a French cryptographer from the 16th century, it improves upon simple substitution by using multiple Caesar ciphers with different shift values based on a keyword.

Mathematical Foundation

The Cipher Table (Tabula Recta)

The Vigenère cipher uses a table of alphabets shifted cyclically:

    A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z
  A A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z
  B C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z   A
  C D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z   A   B
  ...
  Z Z   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y

Encryption Formula

Given: - Plaintext character $P$ (position in alphabet, 0-25) - Keyword character $K$ (position in keyword, 0-25)

The ciphertext character $C$ is calculated as:

$$C = (P + K) \mod 26$$

Decryption Formula

$$P = (C - K) \mod 26$$

Example

Plaintext: ATTACKATDAWN
Keyword: LEMON

Position P L E M O L E M O L E M
0 A(0) +L(11) =L(11)
1 T(19) +E(4) =X(23)
2 T(19) +M(12) =G(7)
3 A(0) +O(14) =O(14)
4 C(2) +L(11) =N(13)
5 K(10) +E(4) =Q(14)
6 A(0) +M(12) =O(14)
7 T(19) +O(14) =D(3)
8 A(0) +L(11) =M(12)
9 D(3) +E(4) =H(7)
10 A(0) +M(12) =W(22)
11 W(22) +O(14) =G(6)

Ciphertext: LXGONQODMHWG

Java Implementation

public class VigenereCipher {
    private static final int ALPHABET_SIZE = 26;

    /**
     * Encrypts a message using the Vigenère cipher.
     * @param plaintext The original message (letters only)
     * @param keyword The encryption key
     * @return The encrypted message
     */
    public static String encrypt(String plaintext, String keyword) {
        StringBuilder ciphertext = new StringBuilder();
        int[] keyPositions = getKeywordPositions(keyword);

        for (int i = 0; i < plaintext.length(); i++) {
            char c = plaintext.charAt(i);

            if (Character.isLetter(c)) {
                char base = Character.isUpperCase(c) ? 'A' : 'a';
                int position = c - base;
                int keyPosition = keyPositions[i % keyPositions.length];

                int encryptedPosition = (position + keyPosition) % ALPHABET_SIZE;
                ciphertext.append((char)(base + encryptedPosition));
            } else {
                ciphertext.append(c); // Preserve non-alphabetic characters
            }
        }

        return ciphertext.toString();
    }

    /**
     * Decrypts a message encrypted with the Vigenère cipher.
     * @param ciphertext The encrypted message
     * @param keyword The encryption key
     * @return The decrypted message
     */
    public static String decrypt(String ciphertext, String keyword) {
        StringBuilder plaintext = new StringBuilder();
        int[] keyPositions = getKeywordPositions(keyword);

        for (int i = 0; i < ciphertext.length(); i++) {
            char c = ciphertext.charAt(i);

            if (Character.isLetter(c)) {
                char base = Character.isUpperCase(c) ? 'A' : 'a';
                int position = c - base;
                int keyPosition = keyPositions[i % keyPositions.length];

                int originalPosition = (position - keyPosition + ALPHABET_SIZE) % ALPHABET_SIZE;
                plaintext.append((char)(base + originalPosition));
            } else {
                plaintext.append(c); // Preserve non-alphabetic characters
            }
        }

        return plaintext.toString();
    }

    /**
     * Converts keyword to array of positions (0-25).
     */
    private static int[] getKeywordPositions(String keyword) {
        int[] positions = new int[keyword.length()];
        for (int i = 0; i < keyword.length(); i++) {
            char c = Character.toUpperCase(keyword.charAt(i));
            positions[i] = c - 'A';
        }
        return positions;
    }

    public static void main(String[] args) {
        String message = "ATTACKATDAWN";
        String keyword = "LEMON";

        String encrypted = encrypt(message, keyword);
        System.out.println("Plaintext:  " + message);
        System.out.println("Keyword:    " + keyword);
        System.out.println("Ciphertext: " + encrypted);

        String decrypted = decrypt(encrypted, keyword);
        System.out.println("Decrypted:  " + decrypted);
    }
}

Cryptanalysis: Kasiski Examination and Index of Coincidence

The Vigenère cipher is vulnerable to cryptanalysis through several techniques. The most famous is the Kasiski examination.

Kasiski Examination

This technique exploits repeated patterns in the ciphertext that result from repeating parts of the plaintext aligning with repeating parts of the keyword.

Steps: 1. Find repeated sequences in the ciphertext (at least 3 characters long) 2. Calculate distances between occurrences 3. The greatest common divisor (GCD) of these distances likely reveals the key length 4. Once key length is known, split ciphertext into separate Caesar ciphers and analyze frequencies

Example Kasiski Analysis

Ciphertext: LXGONQODMHWG with repeated pattern analysis...

If we find "ON" appears at positions 3 and 10 (distance = 7), and another pattern repeats every 13 characters, the GCD might be 1. This suggests a key length of 1 or a multiple thereof.

Index of Coincidence (IOC)

The IOC measures the probability that two randomly selected letters from a text are identical. For English text: - Expected IOC ≈ 0.067 (due to letter frequency distribution) - Random text IOC ≈ 0.038 (uniform distribution)

By calculating IOC for different key lengths, we can statistically determine the correct key length.

Security Analysis

Strengths and Weaknesses

Aspect Assessment
Key Space $26^n$ where n is keyword length (larger than Caesar)
Complexity O(n) time, O(1) space
Vulnerability Breakable with Kasiski or frequency analysis on groups
Modern Use Educational only - never for actual security

Why It's Still Taught

Despite being breakable, the Vigenère cipher demonstrates important concepts:

  1. Polyalphabetic Substitution: Using multiple alphabets to obscure letter frequencies
  2. Key Length Impact: Longer keys provide better security (though still not secure)
  3. Historical Significance: Used by governments and militaries for centuries
  4. Foundation for Modern Ciphers: Concepts evolved into modern stream ciphers

Historical Context

The Vigenère cipher was used extensively during the 16th-19th centuries:

  • French Navy: Used in naval communications
  • Diplomatic Communications: Protected state secrets
  • World War I: German military used variants (e.g., ADFGVX)

It wasn't broken until 1863 by Friedrich Kasiski, who published his analysis method. Before that, it was known as the "inexpugnable cipher" (le chiffre indéchiffrable).

Autokey Variant

A more secure variant called Autokey uses the plaintext itself as part of the key stream:

  • Key: LEMON
  • Plaintext: ATTACKATDAWN
  • Extended key: LEMONATTAC... (keyword + plaintext)

This makes frequency analysis much harder but still vulnerable to more advanced attacks.

Comparison with Modern Cryptography

Feature Vigenère AES (Modern)
Key Length Variable (practical: 10-26 chars) 128, 192, or 256 bits
Security Margin None - breakable with enough ciphertext Proven secure for decades
Speed Very fast (simple operations) Fast but more complex
Implementation Easy to implement incorrectly Standardized and vetted

References

  1. Trappe, W., & Washington, L. C. (2006). Introduction to Cryptography with Coding Theory. Pearson.
  2. Stinson, D. R. (2005). Cryptography: Theory and Practice. CRC Press.
  3. Kahn, D. (1967). The Codebreakers: The Story of Secret Writing. Scribner.
  4. Friedman, W. F. (1920). "The Index of Coincidence and Its Application in Cryptography".