Keyword Cipher Examples: Complete Programming Guide with Code
This comprehensive guide provides practical examples and complete programming implementations of the keyword cipher. Whether you're learning cryptography, implementing cipher algorithms, or studying historical encryption methods, these examples offer hands-on experience with monoalphabetic substitution ciphers.
Basic Examples
Simple Keyword Transformation
Let's start with a straightforward example using the keyword "ZEBRA":
Keyword: ZEBRA
Standard Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Cipher Alphabet: ZEBRACKDFGHIJLMNOPQSTUVWXY
Encryption Process:
- Plaintext: HELLO WORLD
- Mapping: H→G, E→J, L→K, L→K, O→F
- Ciphertext: GJKKF VFEKX
Step-by-Step Transformation:
- Remove duplicates from keyword: ZEBRA (no duplicates)
- Append remaining letters: ZEBRACKDFGHIJLMNOPQSTUVWXY
- Map each plaintext letter to corresponding cipher letter
- Preserve spaces and punctuation
Historical Diplomatic Example
Keyword: MONARCHY
Context: 17th century European diplomatic cipher
Plaintext: THE TREATY IS SIGNED
Ciphertext: TDO THIPTS YA AYGFOH
This example demonstrates how diplomatic communications were encrypted during the Age of Enlightenment, where keyword ciphers provided sufficient security for political correspondence.
Programming Implementations
Python Implementation
Here's a complete Python class for keyword cipher operations:
class KeywordCipher:
def __init__(self, keyword):
"""Initialize the cipher with a keyword."""
self.keyword = keyword.upper()
self.standard_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
self.cipher_alphabet = self._generate_cipher_alphabet()
self.encrypt_map = self._create_encrypt_map()
self.decrypt_map = self._create_decrypt_map()
def _generate_cipher_alphabet(self):
"""Generate cipher alphabet from keyword."""
# Remove duplicates while preserving order
seen = set()
clean_keyword = ''.join(char for char in self.keyword
if char.isalpha() and char not in seen
and not seen.add(char))
# Add remaining letters
remaining = ''.join(char for char in self.standard_alphabet
if char not in clean_keyword)
return clean_keyword + remaining
def _create_encrypt_map(self):
"""Create encryption mapping dictionary."""
mapping = {}
for i, char in enumerate(self.standard_alphabet):
mapping[char] = self.cipher_alphabet[i]
mapping[char.lower()] = self.cipher_alphabet[i].lower()
return mapping
def _create_decrypt_map(self):
"""Create decryption mapping dictionary."""
mapping = {}
for i, char in enumerate(self.cipher_alphabet):
mapping[char] = self.standard_alphabet[i]
mapping[char.lower()] = self.standard_alphabet[i].lower()
return mapping
def encrypt(self, plaintext):
"""Encrypt plaintext using the keyword cipher."""
return ''.join(self.encrypt_map.get(char, char) for char in plaintext)
def decrypt(self, ciphertext):
"""Decrypt ciphertext using the keyword cipher."""
return ''.join(self.decrypt_map.get(char, char) for char in ciphertext)
def get_alphabet_mapping(self):
"""Return the alphabet mapping for analysis."""
return {
'standard': self.standard_alphabet,
'cipher': self.cipher_alphabet,
'keyword': self.keyword
}
# Example usage
def main():
# Create cipher instance
cipher = KeywordCipher('CRYPTOGRAPHY')
# Test messages
messages = [
"Hello World",
"The quick brown fox jumps over the lazy dog",
"ATTACK AT DAWN"
]
print(f"Keyword: {cipher.keyword}")
print(f"Cipher Alphabet: {cipher.cipher_alphabet}")
print("-" * 50)
for message in messages:
encrypted = cipher.encrypt(message)
decrypted = cipher.decrypt(encrypted)
print(f"Original: {message}")
print(f"Encrypted: {encrypted}")
print(f"Decrypted: {decrypted}")
print(f"Match: {message == decrypted}")
print("-" * 30)
if __name__ == "__main__":
main()
JavaScript Implementation
Browser-compatible JavaScript version with DOM integration:
class KeywordCipher {
constructor(keyword) {
this.keyword = keyword.toUpperCase();
this.standardAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
this.cipherAlphabet = this.generateCipherAlphabet();
this.encryptMap = this.createEncryptMap();
this.decryptMap = this.createDecryptMap();
}
generateCipherAlphabet() {
// Remove duplicates from keyword
const uniqueKeyword = [...new Set(this.keyword.split(''))]
.filter(char => /[A-Z]/.test(char))
.join('');
// Generate remaining letters
const remaining = this.standardAlphabet
.split('')
.filter(char => !uniqueKeyword.includes(char))
.join('');
return uniqueKeyword + remaining;
}
createEncryptMap() {
const map = new Map();
for (let i = 0; i < this.standardAlphabet.length; i++) {
const std = this.standardAlphabet[i];
const cipher = this.cipherAlphabet[i];
map.set(std, cipher);
map.set(std.toLowerCase(), cipher.toLowerCase());
}
return map;
}
createDecryptMap() {
const map = new Map();
for (let i = 0; i < this.standardAlphabet.length; i++) {
const std = this.standardAlphabet[i];
const cipher = this.cipherAlphabet[i];
map.set(cipher, std);
map.set(cipher.toLowerCase(), std.toLowerCase());
}
return map;
}
encrypt(plaintext) {
return plaintext
.split('')
.map(char => this.encryptMap.get(char) || char)
.join('');
}
decrypt(ciphertext) {
return ciphertext
.split('')
.map(char => this.decryptMap.get(char) || char)
.join('');
}
// Utility methods for web integration
static createFromForm() {
const keyword = document.getElementById('keyword').value;
return new KeywordCipher(keyword);
}
encryptFromDOM() {
const plaintext = document.getElementById('plaintext').value;
const result = this.encrypt(plaintext);
document.getElementById('ciphertext').value = result;
return result;
}
decryptFromDOM() {
const ciphertext = document.getElementById('ciphertext').value;
const result = this.decrypt(ciphertext);
document.getElementById('plaintext').value = result;
return result;
}
}
// Web interface integration
document.addEventListener('DOMContentLoaded', function() {
let cipher = null;
// Initialize cipher when keyword changes
document.getElementById('keyword').addEventListener('input', function() {
const keyword = this.value;
if (keyword) {
cipher = new KeywordCipher(keyword);
updateAlphabetDisplay();
}
});
// Encrypt button handler
document.getElementById('encryptBtn').addEventListener('click', function() {
if (cipher) {
cipher.encryptFromDOM();
}
});
// Decrypt button handler
document.getElementById('decryptBtn').addEventListener('click', function() {
if (cipher) {
cipher.decryptFromDOM();
}
});
function updateAlphabetDisplay() {
if (cipher) {
document.getElementById('standardAlphabet').textContent =
cipher.standardAlphabet;
document.getElementById('cipherAlphabet').textContent =
cipher.cipherAlphabet;
}
}
});
Advanced Examples
Strength Testing Algorithm
def analyze_keyword_strength(keyword):
"""Analyze the cryptographic strength of a keyword."""
analysis = {
'length': len(keyword),
'unique_letters': len(set(keyword.upper())),
'duplicates': [],
'strength': 'weak'
}
# Find duplicate letters
seen = set()
for char in keyword.upper():
if char in seen:
analysis['duplicates'].append(char)
seen.add(char)
# Determine strength
if analysis['length'] >= 8 and len(analysis['duplicates']) == 0:
analysis['strength'] = 'strong'
elif analysis['length'] >= 6 and len(analysis['duplicates']) <= 1:
analysis['strength'] = 'medium'
return analysis
# Usage example
keywords = ['SECRET', 'CRYPTOGRAPHY', 'ZEBRA', 'SUPERCALIFRAGILISTICEXPIALIDOCIOUS']
for keyword in keywords:
strength = analyze_keyword_strength(keyword)
print(f"{keyword}: {strength['strength']} "
f"(Length: {strength['length']}, "
f"Duplicates: {len(strength['duplicates'])})")
Frequency Analysis Tool
def frequency_analysis(text):
"""Perform frequency analysis on text."""
from collections import Counter
import string
# Clean text (letters only)
clean_text = ''.join(char.upper() for char in text if char.isalpha())
# Count frequencies
letter_counts = Counter(clean_text)
total_letters = len(clean_text)
# Calculate percentages
frequencies = {}
for letter in string.ascii_uppercase:
count = letter_counts.get(letter, 0)
frequencies[letter] = (count / total_letters) * 100 if total_letters > 0 else 0
# Sort by frequency
sorted_freq = sorted(frequencies.items(), key=lambda x: x[1], reverse=True)
return sorted_freq, total_letters
# English language frequency reference
ENGLISH_FREQ = {
'E': 12.7, 'T': 9.1, 'A': 8.2, 'O': 7.5, 'I': 7.0, 'N': 6.7,
'S': 6.3, 'H': 6.1, 'R': 6.0, 'D': 4.3, 'L': 4.0, 'C': 2.8
}
def compare_with_english(text_frequencies):
"""Compare text frequencies with standard English."""
comparison = []
for letter, freq in text_frequencies[:12]: # Top 12 letters
english_freq = ENGLISH_FREQ.get(letter, 0)
difference = abs(freq - english_freq)
comparison.append((letter, freq, english_freq, difference))
return comparison
Interactive Learning Examples
Progressive Difficulty Examples
Beginner Level
Keyword: CAT
Plaintext: I LOVE CATS
Process: Simple 3-letter keyword, easy to understand
Intermediate Level
Keyword: JAVASCRIPT
Plaintext: Programming is fun and educational
Challenge: Longer keyword with duplicate letters to remove
Advanced Level
Keyword: CRYPTANALYSIS
Plaintext: Frequency analysis reveals patterns in monoalphabetic substitution ciphers
Complexity: Technical vocabulary and longer text for realistic analysis
Historical Case Studies
Example 1: Mary Queen of Scots (1586)
Historical Context: Babington Plot communications
Keyword: MARIE (simplified for example)
Original Message: "The deed will be done on Thursday"
Encrypted: "Rdj kjjk vpmm yj kghj gh Rdqxakit"
Historical Note: The actual cipher used was more complex, but keyword-based substitution was a component of the nomenclator system that ultimately led to Mary's downfall.
Example 2: Telegraph Era (1850s)
Commercial Context: Business communications
Keyword: TELEGRAPH
Cost Consideration: Shorter encrypted messages saved money
Example: "PROFITS UP" → "QUHDITJ RQ"
Practical Exercises
Exercise 1: Basic Implementation
Create a keyword cipher using your name as the keyword and encrypt a personal message.
Exercise 2: Strength Comparison
Compare the cipher alphabets generated by these keywords:
- SHORT
- MEDIUM
- VERYLONGKEYWORD
Analyze how keyword length affects the substitution pattern.
Exercise 3: Breaking Practice
Try to break this keyword cipher: Ciphertext: "MJKKP VPEKX! LPHJ YGPJFKXJ FP XJVJEHJFJ QGJ JFXEFJ GRA FPQGJHKJX HGJAKJ"
Hints:
- Common English text
- Keyword is a common 6-letter word
- Look for the pattern of the most frequent letter
Exercise 4: Algorithm Optimization
Implement a version that handles:
- Multiple keywords (rotating between them)
- Non-English alphabets
- Number preservation options
Best Practices
Security Considerations
- Keyword Selection: Use long, random keywords without repeated letters
- Message Length: Shorter messages are harder to analyze
- Context Awareness: Consider what information might be available to attackers
Implementation Guidelines
- Input Validation: Always validate and sanitize keyword input
- Case Handling: Decide how to handle uppercase/lowercase consistently
- Error Handling: Manage edge cases like empty keywords or special characters
- Performance: For large texts, optimize mapping lookups
Educational Applications
- Progressive Learning: Start with simple examples and increase complexity
- Visual Aids: Show alphabet mappings clearly
- Interactive Tools: Allow students to experiment with different keywords
- Historical Context: Connect examples to real historical usage
The keyword cipher serves as an excellent introduction to cryptographic concepts while providing practical programming challenges. These examples demonstrate both the implementation details and the analytical techniques necessary for understanding classical substitution ciphers in their historical and educational context.