波利比奥斯密码编程指南与示例
本综合指南提供了多种编程语言中波利比奥斯方阵密码的完整实现,以及历史示例和教学练习,以加深您对基于坐标密码学的理解。
算法概述
波利比奥斯方阵密码根据字母在方格中的位置将其转换为坐标对。这种基于坐标的方法使其非常适合使用视觉或听觉信号进行远程通信。
核心概念
方格结构:字母排列在方形网格中(通常为 5×5 或 6×6) 坐标对:每个字母变为(行,列)坐标 I/J 合并:在 5×5 方格中,I 和 J 传统上共享同一位置 格式灵活性:坐标可以是数字(1-5)或字母(A-E)
完整 Python 实现
基础波利比奥斯类
class PolybiusSquare:
"""
完整的波利比奥斯方阵密码实现
支持 5x5 和 6x6 方格以及多种坐标格式
"""
def __init__(self, grid_size='5x5', custom_alphabet=None):
self.grid_size = grid_size
self.size = 5 if grid_size == '5x5' else 6
# 根据方格大小设置字母表
if custom_alphabet:
self.alphabet = custom_alphabet.upper()
elif grid_size == '5x5':
# 经典:I 和 J 合并
self.alphabet = 'ABCDEFGHIKLMNOPQRSTUVWXYZ'
else: # 6x6
# 扩展:所有字母加数字
self.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
# 创建方格
self.grid = self._create_grid()
# 创建编码用的反向查找
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):
"""创建字符方格"""
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=' '):
"""
将文本编码为坐标对
Args:
text: 要编码的输入文本
coordinate_type: 'numeric'(1-5)或 'letter'(A-E)
separator: 分隔坐标对的字符
Returns:
编码后的坐标字符串
"""
result = []
for char in text.upper():
# 跳过非字母数字字符或特殊处理
if not char.isalnum():
continue
# 5x5 方格的 J -> I 转换
if self.grid_size == '5x5' and char == 'J':
char = 'I'
# 获取位置
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'):
"""
将坐标对解码为文本
Args:
coordinates: 以空格分隔的坐标对
coordinate_type: 'numeric' 或 'letter'
Returns:
解码后的文本字符串
"""
# 处理不同的分隔符
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
# 验证坐标
if (0 <= row < self.size and 0 <= col < self.size
and self.grid[row][col]):
result.append(self.grid[row][col])
else:
result.append('?') # 无效坐标
except (ValueError, IndexError):
result.append('?') # 解析错误
else:
result.append(pair) # 保留非坐标文本
return ''.join(result)
def analyze_frequency(self, text):
"""
分析文本中的字符频率
适用于教学密码分析
"""
frequency = {}
total_chars = 0
for char in text.upper():
if char.isalpha():
frequency[char] = frequency.get(char, 0) + 1
total_chars += 1
# 转换为百分比并排序
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):
"""以可读格式显示方格"""
print(f"\n波利比奥斯方阵({self.grid_size}):")
print(" ", end="")
# 列标题
for i in range(self.size):
print(f" {chr(65 + i)}", end="")
print()
# 方格行
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()
## 使用示例
def main():
# 创建 5x5 密码
cipher = PolybiusSquare('5x5')
print("=== 波利比奥斯方阵密码示例 ===")
# 基本编码
message = "HELLO WORLD"
encoded = cipher.encode(message)
print(f"\n原始文本:{message}")
print(f"编码结果:{encoded}")
# 解码
decoded = cipher.decode(encoded)
print(f"解码结果:{decoded}")
# 不同坐标格式
letter_coords = cipher.encode(message, 'letter')
print(f"\n字母坐标:{letter_coords}")
print(f"从字母解码:{cipher.decode(letter_coords, 'letter')}")
# 连接格式(无分隔符)
concat_coords = cipher.encode(message, separator='')
print(f"\n连接格式:{concat_coords}")
# 频率分析
print(f"\n=== '{message}' 的频率分析 ===")
freq_analysis = cipher.analyze_frequency(message)
for item in freq_analysis:
print(f"{item['char']}: {item['count']} 次 "
f"({item['percentage']}%)- 坐标 {item['coordinate']}")
# 显示方格
cipher.display_grid()
# 带数字的 6x6 示例
print(f"\n=== 6x6 方格示例 ===")
cipher_6x6 = PolybiusSquare('6x6')
mixed_message = "CODE123"
encoded_6x6 = cipher_6x6.encode(mixed_message)
print(f"消息:{mixed_message}")
print(f"编码:{encoded_6x6}")
print(f"解码:{cipher_6x6.decode(encoded_6x6)}")
if __name__ == "__main__":
main()
高级 JavaScript 实现
/**
* 现代 JavaScript 波利比奥斯方阵实现
* ES6+ 具有高级功能和浏览器兼容性
*/
class PolybiusSquare {
constructor(gridSize = '5x5', customAlphabet = null) {
this.gridSize = gridSize;
this.size = gridSize === '5x5' ? 5 : 6;
// 设置字母表
if (customAlphabet) {
this.alphabet = customAlphabet.toUpperCase();
} else if (gridSize === '5x5') {
this.alphabet = 'ABCDEFGHIKLMNOPQRSTUVWXYZ'; // I/J 合并
} 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 => {
// 5x5 的 J -> I 转换
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 ''; // 跳过未知字符
})
.filter(coord => coord.length > 0)
.join(separator);
}
decode(coordinates, coordinateType = 'numeric') {
// 处理各种分隔符
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 '?'; // 无效坐标
}
return pair; // 保留非坐标文本
})
.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(`\n波利比奥斯方阵(${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);
});
}
// Web 应用工具方法
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');
}
}
// 浏览器兼容的使用示例
function demonstratePolybius() {
console.log('=== 波利比奥斯方阵 JavaScript 演示 ===');
const cipher = new PolybiusSquare('5x5');
// 基本操作
const message = 'CRYPTOGRAPHY';
const encoded = cipher.encode(message);
const decoded = cipher.decode(encoded);
console.log(`原始:${message}`);
console.log(`编码:${encoded}`);
console.log(`解码:${decoded}`);
// 频率分析
const frequency = cipher.analyzeFrequency(message);
console.log('\n频率分析:');
frequency.forEach(item => {
console.log(`${item.char}: ${item.count} (${item.percentage}%) → ${item.coordinate}`);
});
cipher.displayGrid();
}
// Web API 集成示例
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); // 模拟异步处理
});
}
batchProcess(textArray) {
return Promise.all(
textArray.map(text => this.processText(text))
);
}
}
// 模块系统导出
if (typeof module !== 'undefined' && module.exports) {
module.exports = { PolybiusSquare, PolybiusWebAPI };
}
历史示例与应用
古希腊信号通信
原始波利比奥斯系统使用火炬信号进行远程通信:
def ancient_torch_signals():
"""
模拟古希腊火炬信号
每个坐标以一组火炬传输
"""
message = "ENEMY APPROACHING"
cipher = PolybiusSquare('5x5')
encoded = cipher.encode(message)
print("古代火炬信号协议:")
print(f"消息:{message}")
print(f"坐标:{encoded}")
print("\n火炬信号说明:")
for i, coord in enumerate(encoded.split()):
if coord.isdigit() and len(coord) == 2:
row, col = int(coord[0]), int(coord[1])
print(f"字母 {i+1}:{row} 个火炬,停顿,{col} 个火炬")
电报时代的实现
在电报时代,波利比奥斯坐标非常适合传输:
def telegraph_encoding():
"""
电报优化的波利比奥斯编码
带错误检测的连接格式
"""
def add_checksum(encoded_text):
"""添加简单校验和用于错误检测"""
checksum = sum(int(digit) for digit in encoded_text if digit.isdigit()) % 100
return f"{encoded_text}{checksum:02d}"
def verify_checksum(received_text):
"""验证电报完整性"""
if len(received_text) < 2:
return False, "太短"
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"
# 无分隔符编码(电报风格)
encoded = cipher.encode(message, separator='')
secured = add_checksum(encoded)
print("电报传输:")
print(f"原始:{message}")
print(f"编码:{encoded}")
print(f"带校验和:{secured}")
# 验证并解码
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}")
else:
print("校验和验证失败 - 检测到传输错误")
监狱敲击码转换
将波利比奥斯转换为著名的监狱敲击代码:
def prison_tap_code():
"""
将波利比奥斯坐标转换为敲击代码序列
曾被战俘用于穿墙通信
"""
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])
# 创建敲击模式
row_pattern = '•' * row_taps
col_pattern = '•' * col_taps
tap_sequence.append(f"{row_pattern} | {col_pattern}")
return ' '.join(tap_sequence)
# 历史战俘消息
messages = [
"GOD BLESS AMERICA",
"STAY STRONG",
"REMEMBER YOUR TRAINING"
]
print("监狱敲击代码示例:")
for msg in messages:
taps = text_to_taps(msg)
print(f"\n消息:{msg}")
print(f"敲击代码:{taps}")
教学练习
练习一:频率分析
分析波利比奥斯密码对频率攻击的脆弱性:
def frequency_vulnerability_demo():
"""
演示频率分析漏洞
"""
cipher = PolybiusSquare('5x5')
# 具有自然字母频率的英语文本
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
"""
# 编码并分析
encoded = cipher.encode(sample_text)
frequency = cipher.analyze_frequency(sample_text)
print("频率漏洞分析:")
print(f"示例文本长度:{len(sample_text.replace(' ', '').replace(chr(10), ''))} 个字符")
print("\n出现频率最高的 5 个字符:")
for item in frequency[:5]:
print(f"{item['char']}: {item['count']} 次({item['percentage']}%)"
f"→ 始终编码为 {item['coordinate']}")
print(f"\n编码坐标:{encoded}")
print("\n安全说明:坐标 '44' 频繁出现,")
print("表明字母 'T' 在英语文本中很常见。")
练习二:方格变体
探索不同方格配置及其含义:
def compare_grid_sizes():
"""
比较 5x5 与 6x6 方格特性
"""
message = "HELLO123"
# 5x5 方格
cipher_5x5 = PolybiusSquare('5x5')
try:
encoded_5x5 = cipher_5x5.encode(message)
print(f"5x5 编码:{encoded_5x5}")
except:
print("5x5 方格无法编码数字")
# 6x6 方格
cipher_6x6 = PolybiusSquare('6x6')
encoded_6x6 = cipher_6x6.encode(message)
print(f"6x6 编码:{encoded_6x6}")
print("\n方格比较:")
print("5x5:经典版,I/J 合并,仅支持字母")
print("6x6:现代版,所有字母加数字,坐标较长")
练习三:自定义字母表
使用自定义字符排列进行实验:
def custom_alphabet_cipher():
"""
使用自定义字母表排列创建波利比奥斯密码
"""
# 基于关键词的字母表(去除重复字母,添加剩余字母)
keyword = "CRYPTOGRAPHY"
remaining = "BEFHJKLMNQSUVWXZ" # 关键词中没有的字母
custom_alphabet = keyword + remaining
print(f"自定义字母表:{custom_alphabet}")
cipher = PolybiusSquare('5x5', custom_alphabet)
cipher.display_grid()
message = "SECRET MESSAGE"
encoded = cipher.encode(message)
print(f"\n消息:{message}")
print(f"使用自定义字母表编码:{encoded}")
本综合指南为在现代编程环境中理解和实现波利比奥斯方阵密码奠定了基础,同时保持历史准确性和教育价值。