Python implementation of the PlayFair cipher, a classical digraph substitution cipher developed in 1854.
The PlayFair cipher encrypts pairs of letters using a matrix generated from a keyword. It was one of the first practical digraph substitution ciphers and was notably used in military communications.
This repository contains two implementations:
- 5×5 Traditional: Classic PlayFair with 25 letters (I and J share position)
- 6×6 Extended: Modern variant supporting alphanumeric text (A-Z, 0-9)
git clone https://github.com/YonAndualem/PlayFair-Cipher.git
cd PlayFair-CipherNo external dependencies required for core functionality. GUI requires tkinter (usually included with Python).
python3 main.py guipython3 main.py clipython3 main.py testfrom src.cipher import PlayFairCipher
cipher = PlayFairCipher("KEYWORD")
ciphertext = cipher.encrypt("HELLO WORLD")
plaintext = cipher.decrypt(ciphertext)python3 main6x6.py guipython3 main6x6.py clipython3 main6x6.py testfrom src.cipher6x6 import PlayFairCipher6x6
cipher = PlayFairCipher6x6("CRYPTO2026")
ciphertext = cipher.encrypt("PASSWORD123")
plaintext = cipher.decrypt(ciphertext)- Remove duplicate letters from keyword
- Fill remaining spaces with alphabet (A-Z, excluding J)
- Arrange in 5×5 grid
Example with keyword "MONARCHY":
M O N A R
C H Y B D
E F G I K
L P Q S T
U V W X Z
- Remove duplicate characters from keyword
- Fill remaining spaces with unused letters (A-Z)
- Add remaining digits (0-9)
- Arrange in 6×6 grid
Example with keyword "CRYPTO2026":
C R Y P T O
2 6 A B D E
F G H I J K
L M N Q S U
V W X Z 0 1
3 4 5 7 8 9
For each pair of letters:
- Same Row: Replace with letters to the right (wrap around)
- Same Column: Replace with letters below (wrap around)
- Rectangle: Swap the columns of each letter
Apply inverse operations:
- Same row: shift left
- Same column: shift up
- Rectangle: swap columns (same operation)
PlayFair-Cipher/
├── src/
│ ├── cipher.py # 5×5 core algorithm
│ ├── cipher6x6.py # 6×6 extended algorithm
│ ├── gui/
│ │ ├── app.py # 5×5 graphical interface
│ │ └── app6x6.py # 6×6 graphical interface
│ └── cli/
│ ├── demo.py # 5×5 command-line interface
│ └── demo6x6.py # 6×6 command-line interface
├── tests/
│ ├── test_cipher.py # 5×5 test suite
│ └── test_cipher6x6.py # 6×6 test suite
├── main.py # 5×5 application entry point
├── main6x6.py # 6×6 application entry point
└── README.md
- Core Implementation: Clean, well-documented cipher algorithm
- GUI Application: Interactive visual interface with real-time encryption
- CLI Tool: Command-line demonstration and interactive mode
- Test Suite: Comprehensive unit tests
- Historical Accuracy: Implements the original PlayFair cipher
- Alphanumeric Support: Encrypt messages containing both letters and numbers
- 36-Character Matrix: All 26 letters (A-Z) + 10 digits (0-9)
- No Information Loss: No character merging (unlike J→I in 5×5)
- Modern Use Cases: Perfect for passwords, codes, and alphanumeric messages
- Same Interfaces: GUI, CLI, and programmatic API
| Feature | 5×5 Traditional | 6×6 Extended |
|---|---|---|
| Characters | 25 (A-Z, no J) | 36 (A-Z, 0-9) |
| Digit Support | ❌ No | ✅ Yes |
| Character Merging | J → I | None |
| Historical | ✅ Original | Modern variant |
| Use Cases | Text only | Alphanumeric |
- Converts to uppercase
- Replaces J with I
- Removes non-alphabetic characters
- Splits into digraphs (letter pairs)
- Inserts 'X' between duplicate letters
- Pads with 'X' if odd length
- Converts to uppercase
- Removes non-alphanumeric characters
- Splits into digraphs (character pairs)
- Inserts 'X' between duplicate characters
- Pads with 'X' if odd length
5×5:
- 5×5 grid containing 25 letters (I and J share a position)
- Generated deterministically from keyword
- Unique letter positioning ensures reversible encryption
6×6:
- 6×6 grid containing 36 characters (26 letters + 10 digits)
- Generated deterministically from keyword
- All alphanumeric characters supported
- No character sharing or merging
from src.cipher import PlayFairCipher
# Create cipher
cipher = PlayFairCipher("SECRET")
# Encrypt
encrypted = cipher.encrypt("MEET AT NOON")
print(encrypted)
# Decrypt
decrypted = cipher.decrypt(encrypted)
print(decrypted)from src.cipher6x6 import PlayFairCipher6x6
# Create cipher
cipher = PlayFairCipher6x6("CRYPTO2026")
# Encrypt with digits
encrypted = cipher.encrypt("PASSWORD123")
print(encrypted)
# Decrypt
decrypted = cipher.decrypt(encrypted)
print(decrypted)
# Verbose mode (shows steps)
cipher.encrypt("AGENT007", verbose=True)Run the test suites to verify implementations:
5×5 Version:
python3 main.py test6×6 Version:
python3 main6x6.py testTests cover:
- Matrix generation
- Position mapping
- Text preparation
- Encryption/decryption reversibility
- Individual cipher rules
- Edge cases
- Alphanumeric support (6×6 only)
This is a classical cipher for educational and historical purposes. It is not secure for modern cryptographic use and is vulnerable to:
- Frequency analysis
- Known-plaintext attacks
- Chosen-plaintext attacks
MIT License
- Wheatstone, Charles (1854). Original cipher design
- Playfair, Lyon (1854). Promotion and popularization
- Historical military usage in Boer War and WWI
Contributions welcome. Please ensure:
- Code follows existing style
- Tests pass
- New features include tests
- Documentation is updated