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:
- Polyalphabetic Substitution: Using multiple alphabets to obscure letter frequencies
- Key Length Impact: Longer keys provide better security (though still not secure)
- Historical Significance: Used by governments and militaries for centuries
- 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¶
- Trappe, W., & Washington, L. C. (2006). Introduction to Cryptography with Coding Theory. Pearson.
- Stinson, D. R. (2005). Cryptography: Theory and Practice. CRC Press.
- Kahn, D. (1967). The Codebreakers: The Story of Secret Writing. Scribner.
- Friedman, W. F. (1920). "The Index of Coincidence and Its Application in Cryptography".