波利比奥斯密码示例和代码实现

包含 Python 和 JavaScript 实现的完整波利比奥斯方格密码编程指南,以及历史示例和教育练习。

Quick Implementation Examples

Python Implementation

Python - Core Implementation62 lines
Highlighting code...

JavaScript Implementation

JavaScript - Modern ES660 lines
Highlighting code...

Interactive Polybius Examples

Basic Encoding: "HELLO"

beginner

Simple demonstration of Polybius Square encoding.

5x5numbers

Letter Coordinates: "CIPHER"

beginner

Using letters (A-E) instead of numbers for coordinates.

5x5letters

6x6 Grid: "CODE123"

intermediate

Extended 6x6 grid supporting both letters and digits.

6x6numbers

Basic Encoding: "HELLO"

HELLO
23 15 31 31 34
Grid:5x5
Coordinates:numbers
Difficulty:beginner

H is at row 2, column 3 (23). E is at row 1, column 5 (15). L is at row 3, column 1 (31). O is at row 3, column 4 (34).

Grid Visualization

1
2
3
4
5
1
A
B
C
D
E
2
F
G
H
I/J
merged
K
3
L
M
N
O
P
4
Q
R
S
T
U
5
V
W
X
Y
Z

Highlighted cells show character positions

Historical Examples & Applications

Ancient Greek Signals

Original Use Case: Torch signal communication across mountains

Ancient Greek Method28 lines
Highlighting code...

Telegraph Implementation

Industrial Era: Efficient numeric transmission over telegraph lines

Telegraph Era32 lines
Highlighting code...

Prison Tap Code Evolution

Vietnam War Era: POW communication through wall tapping

POW Tap Code39 lines
Highlighting code...

Pop Culture: Indiana Jones

Kingdom of the Crystal Skull: Polybius Square in modern cinema

Cinema Reference40 lines
Highlighting code...

波利比奥斯密码编程指南与示例

本综合指南提供了多种编程语言中波利比奥斯方阵密码的完整实现,以及历史示例和教学练习,以加深您对基于坐标密码学的理解。

算法概述

波利比奥斯方阵密码根据字母在方格中的位置将其转换为坐标对。这种基于坐标的方法使其非常适合使用视觉或听觉信号进行远程通信。

核心概念

方格结构:字母排列在方形网格中(通常为 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}")

本综合指南为在现代编程环境中理解和实现波利比奥斯方阵密码奠定了基础,同时保持历史准确性和教育价值。