Guide de programmation du chiffrement de polybius et exemples
Ce guide complet fournit des implémentations complètes du chiffrement Polybius Square dans plusieurs langages de programmation, ainsi que des exemples historiques et des exercices éducatifs pour approfondir votre compréhension de la cryptographie basée sur les coordonnées.
Algorithme Aperçu
Le chiffrement Polybius Square convertit les lettres en paires de coordonnées en fonction de leur position dans une grille. Cette approche basée sur les coordonnées l'a rendue idéale pour la communication longue distance à l'aide de signaux visuels ou auditifs.
Concepts fondamentaux
** Structure rigide**: Les lettres sont disposées dans une grille carrée (généralement 5×5 ou 6×6) Pairs coordonnés: Chaque lettre devient (ligne, colonne) coordonnées I/J Fusion: Dans les grilles 5×5, I et J partagent traditionnellement la même position ** Flexibilité du format**: Les coordonnées peuvent être numériques (1-5) ou alphabétiques (A-E)
Mise en œuvre complète du Python
Classe Polybius de base
class PolybiusSquare:
"""
Complete Polybius Square cipher implementation
Supports both 5x5 and 6x6 grids with multiple coordinate formats
"""
def __init__(self, grid_size='5x5', custom_alphabet=None):
self.grid_size = grid_size
self.size = 5 if grid_size == '5x5' else 6
# Set alphabet based on grid size
if custom_alphabet:
self.alphabet = custom_alphabet.upper()
elif grid_size == '5x5':
# Classical: I and J merged
self.alphabet = 'ABCDEFGHIKLMNOPQRSTUVWXYZ'
else: # 6x6
# Extended: all letters plus digits
self.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
# Create the grid
self.grid = self._create_grid()
# Create reverse lookup for encoding
self.char_to_pos = {}
for row in range(self.size):
for col in range(self.size):
if self.grid[row][col]:
self.char_to_pos[self.grid[row][col]] = (row, col)
def _create_grid(self):
"""Create the character grid"""
grid = []
for i in range(self.size):
row = []
for j in range(self.size):
index = i * self.size + j
if index < len(self.alphabet):
row.append(self.alphabet[index])
else:
row.append('')
grid.append(row)
return grid
def encode(self, text, coordinate_type='numeric', separator=' '):
"""
Encode text to coordinate pairs
Args:
text: Input text to encode
coordinate_type: 'numeric' (1-5) or 'letter' (A-E)
separator: Character to separate coordinate pairs
Returns:
Encoded coordinate string
"""
result = []
for char in text.upper():
# Skip non-alphabetic characters or handle specially
if not char.isalnum():
continue
# Handle J -> I conversion for 5x5 grid
if self.grid_size == '5x5' and char == 'J':
char = 'I'
# Get position
if char in self.char_to_pos:
row, col = self.char_to_pos[char]
if coordinate_type == 'numeric':
coord = f"{row + 1}{col + 1}"
else: # letter
row_letter = chr(65 + row) # A, B, C...
col_letter = chr(65 + col)
coord = f"{row_letter}{col_letter}"
result.append(coord)
return separator.join(result)
def decode(self, coordinates, coordinate_type='numeric'):
"""
Decode coordinate pairs to text
Args:
coordinates: Space-separated coordinate pairs
coordinate_type: 'numeric' or 'letter'
Returns:
Decoded text string
"""
# Handle different separators
import re
pairs = re.split(r'[\s,|\-]+', coordinates.strip())
result = []
for pair in pairs:
if len(pair) == 2:
try:
if coordinate_type == 'numeric':
row = int(pair[0]) - 1
col = int(pair[1]) - 1
else: # letter
row = ord(pair[0]) - 65 # A=0, B=1...
col = ord(pair[1]) - 65
# Validate coordinates
if (0 <= row < self.size and 0 <= col < self.size
and self.grid[row][col]):
result.append(self.grid[row][col])
else:
result.append('?') # Invalid coordinate
except (ValueError, IndexError):
result.append('?') # Parsing error
else:
result.append(pair) # Keep non-coordinate text
return ''.join(result)
def analyze_frequency(self, text):
"""
Analyze character frequency in text
Useful for educational cryptanalysis
"""
frequency = {}
total_chars = 0
for char in text.upper():
if char.isalpha():
frequency[char] = frequency.get(char, 0) + 1
total_chars += 1
# Convert to percentages and sort
freq_analysis = []
for char, count in sorted(frequency.items(),
key=lambda x: x[1], reverse=True):
percentage = (count / total_chars) * 100
coord = self.encode(char)
freq_analysis.append({
'char': char,
'count': count,
'percentage': round(percentage, 2),
'coordinate': coord
})
return freq_analysis
def display_grid(self):
"""Display the grid in a readable format"""
print(f"\nPolybius Square ({self.grid_size}):")
print(" ", end="")
# Column headers
for i in range(self.size):
print(f" {chr(65 + i)}", end="")
print()
# Grid rows
for i, row in enumerate(self.grid):
print(f" {chr(65 + i)} ", end="")
for cell in row:
if cell:
print(f" {cell}", end="")
else:
print(" ", end="")
print()
## Exemples d'utilisation
def main():
# Create 5x5 cipher
cipher = PolybiusSquare('5x5')
print("=== Polybius Square Cipher Examples ===")
# Basic encoding
message = "HELLO WORLD"
encoded = cipher.encode(message)
print(f"\nOriginal: {message}")
print(f"Encoded: {encoded}")
# Decoding
decoded = cipher.decode(encoded)
print(f"Decoded: {decoded}")
# Different coordinate formats
letter_coords = cipher.encode(message, 'letter')
print(f"\nLetter coordinates: {letter_coords}")
print(f"Decoded from letters: {cipher.decode(letter_coords, 'letter')}")
# Concatenated format (no separators)
concat_coords = cipher.encode(message, separator='')
print(f"\nConcatenated: {concat_coords}")
# Frequency analysis
print(f"\n=== Frequency Analysis for '{message}' ===")
freq_analysis = cipher.analyze_frequency(message)
for item in freq_analysis:
print(f"{item['char']}: {item['count']} times "
f"({item['percentage']}%) - coordinate {item['coordinate']}")
# Display grid
cipher.display_grid()
# 6x6 example with digits
print(f"\n=== 6x6 Grid Example ===")
cipher_6x6 = PolybiusSquare('6x6')
mixed_message = "CODE123"
encoded_6x6 = cipher_6x6.encode(mixed_message)
print(f"Message: {mixed_message}")
print(f"Encoded: {encoded_6x6}")
print(f"Decoded: {cipher_6x6.decode(encoded_6x6)}")
if __name__ == "__main__":
main()
Mise en œuvre avancée de JavaScript
/**
* Modern JavaScript Polybius Square Implementation
* ES6+ with advanced features and browser compatibility
*/
class PolybiusSquare {
constructor(gridSize = '5x5', customAlphabet = null) {
this.gridSize = gridSize;
this.size = gridSize === '5x5' ? 5 : 6;
// Set alphabet
if (customAlphabet) {
this.alphabet = customAlphabet.toUpperCase();
} else if (gridSize === '5x5') {
this.alphabet = 'ABCDEFGHIKLMNOPQRSTUVWXYZ'; // I/J merged
} else {
this.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
}
this.grid = this.createGrid();
this.charToPos = this.createLookupMap();
}
createGrid() {
const grid = [];
for (let i = 0; i < this.size; i++) {
const row = [];
for (let j = 0; j < this.size; j++) {
const index = i * this.size + j;
row.push(this.alphabet[index] || '');
}
grid.push(row);
}
return grid;
}
createLookupMap() {
const map = new Map();
for (let row = 0; row < this.size; row++) {
for (let col = 0; col < this.size; col++) {
if (this.grid[row][col]) {
map.set(this.grid[row][col], { row, col });
}
}
}
return map;
}
encode(text, coordinateType = 'numeric', separator = ' ') {
return text.toUpperCase()
.split('')
.filter(char => char.match(/[A-Z0-9]/))
.map(char => {
// Handle J -> I conversion for 5x5
if (this.gridSize === '5x5' && char === 'J') {
char = 'I';
}
const pos = this.charToPos.get(char);
if (pos) {
if (coordinateType === 'numeric') {
return `${pos.row + 1}${pos.col + 1}`;
} else {
const rowLetter = String.fromCharCode(65 + pos.row);
const colLetter = String.fromCharCode(65 + pos.col);
return `${rowLetter}${colLetter}`;
}
}
return ''; // Skip unknown characters
})
.filter(coord => coord.length > 0)
.join(separator);
}
decode(coordinates, coordinateType = 'numeric') {
// Handle various separators
const pairs = coordinates.split(/[\s,|\-]+/).filter(pair => pair.length > 0);
return pairs
.map(pair => {
if (pair.length === 2) {
let row, col;
if (coordinateType === 'numeric') {
row = parseInt(pair[0]) - 1;
col = parseInt(pair[1]) - 1;
} else {
row = pair.charCodeAt(0) - 65;
col = pair.charCodeAt(1) - 65;
}
if (row >= 0 && row < this.size &&
col >= 0 && col < this.size &&
this.grid[row][col]) {
return this.grid[row][col];
}
return '?'; // Invalid coordinate
}
return pair; // Keep non-coordinate text
})
.join('');
}
analyzeFrequency(text) {
const frequency = new Map();
const totalChars = text.replace(/[^A-Z]/g, '').length;
for (const char of text.toUpperCase()) {
if (char.match(/[A-Z]/)) {
frequency.set(char, (frequency.get(char) || 0) + 1);
}
}
return Array.from(frequency.entries())
.map(([char, count]) => ({
char,
count,
percentage: Math.round((count / totalChars) * 100 * 100) / 100,
coordinate: this.encode(char)
}))
.sort((a, b) => b.count - a.count);
}
displayGrid() {
console.log(`\nPolybius Square (${this.gridSize}):`);
console.log(' ' + Array.from({length: this.size}, (_, i) =>
String.fromCharCode(65 + i)).join(' '));
this.grid.forEach((row, i) => {
const rowStr = String.fromCharCode(65 + i) + ' | ' +
row.map(cell => cell || ' ').join(' ');
console.log(rowStr);
});
}
// Utility methods for web applications
toJSON() {
return {
gridSize: this.gridSize,
alphabet: this.alphabet,
grid: this.grid
};
}
exportToCSV(analysis) {
const headers = ['Character', 'Count', 'Percentage', 'Coordinate'];
const rows = analysis.map(item =>
[item.char, item.count, item.percentage, item.coordinate]
);
return [headers, ...rows]
.map(row => row.join(','))
.join('\n');
}
}
// Browser-compatible usage examples
function demonstratePolybius() {
console.log('=== Polybius Square JavaScript Demo ===');
const cipher = new PolybiusSquare('5x5');
// Basic operations
const message = 'CRYPTOGRAPHY';
const encoded = cipher.encode(message);
const decoded = cipher.decode(encoded);
console.log(`Original: ${message}`);
console.log(`Encoded: ${encoded}`);
console.log(`Decoded: ${decoded}`);
// Frequency analysis
const frequency = cipher.analyzeFrequency(message);
console.log('\nFrequency Analysis:');
frequency.forEach(item => {
console.log(`${item.char}: ${item.count} (${item.percentage}%) → ${item.coordinate}`);
});
cipher.displayGrid();
}
// Web API integration example
class PolybiusWebAPI {
constructor() {
this.cipher = new PolybiusSquare();
}
async processText(text, options = {}) {
return new Promise((resolve) => {
setTimeout(() => {
const result = {
original: text,
encoded: this.cipher.encode(text, options.coordinateType),
frequency: this.cipher.analyzeFrequency(text),
timestamp: new Date().toISOString()
};
resolve(result);
}, 100); // Simulate async processing
});
}
batchProcess(textArray) {
return Promise.all(
textArray.map(text => this.processText(text))
);
}
}
// Export for module systems
if (typeof module !== 'undefined' && module.exports) {
module.exports = { PolybiusSquare, PolybiusWebAPI };
}
Exemples et applications historiques
Communications de signaux grecques anciennes
Le système original Polybius utilisait des signaux de torche pour la communication longue distance:
def ancient_torch_signals():
"""
Simulate ancient Greek torch signaling
Each coordinate transmitted as groups of torches
"""
message = "ENEMY APPROACHING"
cipher = PolybiusSquare('5x5')
encoded = cipher.encode(message)
print("Ancient Torch Signal Protocol:")
print(f"Message: {message}")
print(f"Coordinates: {encoded}")
print("\nTorch Signal Instructions:")
for i, coord in enumerate(encoded.split()):
if coord.isdigit() and len(coord) == 2:
row, col = int(coord[0]), int(coord[1])
print(f"Letter {i+1}: {row} torches, pause, {col} torches")
Mise en œuvre du télégraphe Era
Pendant l'ère télégraphique, les coordonnées de Polybius étaient idéales pour la transmission:
def telegraph_encoding():
"""
Telegraph-optimized Polybius encoding
Concatenated format with error detection
"""
def add_checksum(encoded_text):
"""Add simple checksum for error detection"""
checksum = sum(int(digit) for digit in encoded_text if digit.isdigit()) % 100
return f"{encoded_text}{checksum:02d}"
def verify_checksum(received_text):
"""Verify telegram integrity"""
if len(received_text) < 2:
return False, "Too short"
message = received_text[:-2]
expected_checksum = int(received_text[-2:])
actual_checksum = sum(int(d) for d in message if d.isdigit()) % 100
return actual_checksum == expected_checksum, message
cipher = PolybiusSquare('5x5')
message = "URGENT SUPPLIES NEEDED"
# Encode without separators (telegraph style)
encoded = cipher.encode(message, separator='')
secured = add_checksum(encoded)
print("Telegraph Transmission:")
print(f"Original: {message}")
print(f"Encoded: {encoded}")
print(f"With checksum: {secured}")
# Verify and decode
is_valid, clean_message = verify_checksum(secured)
if is_valid:
decoded = cipher.decode(' '.join([clean_message[i:i+2]
for i in range(0, len(clean_message), 2)]))
print(f"Decoded: {decoded}")
else:
print("Checksum failed - transmission error detected")
Conversion du code de la langue de prison
Convertir Polybius en le fameux code de robinet de prison:
def prison_tap_code():
"""
Convert Polybius coordinates to tap code sequences
Used by POWs for wall communication
"""
def text_to_taps(text):
cipher = PolybiusSquare('5x5')
encoded = cipher.encode(text)
tap_sequence = []
for coord in encoded.split():
if len(coord) == 2:
row_taps = int(coord[0])
col_taps = int(coord[1])
# Create tap pattern
row_pattern = '•' * row_taps
col_pattern = '•' * col_taps
tap_sequence.append(f"{row_pattern} | {col_pattern}")
return ' '.join(tap_sequence)
# Historical POW messages
messages = [
"GOD BLESS AMERICA",
"STAY STRONG",
"REMEMBER YOUR TRAINING"
]
print("Prison Tap Code Examples:")
for msg in messages:
taps = text_to_taps(msg)
print(f"\nMessage: {msg}")
print(f"Tap code: {taps}")
Exercices éducatifs
Exercice 1: Analyse de fréquence
Analyser la vulnérabilité des chiffres de Polybius aux attaques de fréquence:
def frequency_vulnerability_demo():
"""
Demonstrate frequency analysis vulnerability
"""
cipher = PolybiusSquare('5x5')
# English text with natural letter frequencies
sample_text = """
THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
THIS IS A SAMPLE TEXT FOR FREQUENCY ANALYSIS
NOTICE HOW CERTAIN LETTERS APPEAR MORE OFTEN
"""
# Encode and analyze
encoded = cipher.encode(sample_text)
frequency = cipher.analyze_frequency(sample_text)
print("Frequency Vulnerability Analysis:")
print(f"Sample text length: {len(sample_text.replace(' ', '').replace('\n', ''))} characters")
print("\nTop 5 most frequent characters:")
for item in frequency[:5]:
print(f"{item['char']}: {item['count']} times ({item['percentage']}%) "
f"→ always encoded as {item['coordinate']}")
print(f"\nEncoded coordinates: {encoded}")
print("\nSecurity note: The coordinate '44' appears frequently,")
print("indicating the letter 'T' is common in English text.")
Exercice 2: Variations de grille
Explorer différentes configurations de grille et leurs implications:
def compare_grid_sizes():
"""
Compare 5x5 vs 6x6 grid characteristics
"""
message = "HELLO123"
# 5x5 grid
cipher_5x5 = PolybiusSquare('5x5')
try:
encoded_5x5 = cipher_5x5.encode(message)
print(f"5x5 encoding: {encoded_5x5}")
except:
print("5x5 grid cannot encode digits")
# 6x6 grid
cipher_6x6 = PolybiusSquare('6x6')
encoded_6x6 = cipher_6x6.encode(message)
print(f"6x6 encoding: {encoded_6x6}")
print("\nGrid Comparison:")
print("5x5: Classical, I/J merged, letters only")
print("6x6: Modern, all letters + digits, longer coordinates")
Exercice 3: Alphabets personnalisés
Expérimentez avec des arrangements de caractère personnalisés:
def custom_alphabet_cipher():
"""
Create Polybius cipher with custom alphabet arrangement
"""
# Keyword-based alphabet (remove duplicates, add remaining letters)
keyword = "CRYPTOGRAPHY"
remaining = "BEFHJKLMNQSUVWXZ" # Letters not in keyword
custom_alphabet = keyword + remaining
print(f"Custom alphabet: {custom_alphabet}")
cipher = PolybiusSquare('5x5', custom_alphabet)
cipher.display_grid()
message = "SECRET MESSAGE"
encoded = cipher.encode(message)
print(f"\nMessage: {message}")
print(f"Encoded with custom alphabet: {encoded}")
Ce guide complet fournit les bases de la compréhension et de la mise en oeuvre des chiffres de Polybius Square dans les environnements de programmation modernes tout en maintenant la précision historique et la valeur éducative.