用Python手撸一个维吉尼亚密码加解密工具(附完整代码和查表法实现)

张开发
2026/4/19 0:29:09 15 分钟阅读

分享文章

用Python手撸一个维吉尼亚密码加解密工具(附完整代码和查表法实现)
用Python实现维吉尼亚密码从原理到实战工具开发在密码学的历史长河中维吉尼亚密码以其独特的加密方式占据着重要地位。作为多表替换密码的经典代表它不仅出现在各类CTF竞赛中更是理解现代加密算法的基础。本文将带你从零开始用Python构建一个功能完整的维吉尼亚密码工具涵盖加密、解密以及自动破解等核心功能。1. 维吉尼亚密码核心原理维吉尼亚密码由16世纪法国密码学家Blaise de Vigenère发明通过引入密钥概念有效抵抗了传统的频率分析攻击。其核心在于多字母替换系统——每个明文字母根据密钥字母的不同进行独立替换。1.1 数学公式法实现加密过程可以表示为数学运算def formula_encrypt(plaintext, key): ciphertext [] key_len len(key) for i, char in enumerate(plaintext.lower()): if char.isalpha(): # 字母转换为0-25的数字 p ord(char) - ord(a) k ord(key[i % key_len]) - ord(a) # 加密公式(明文 密钥) mod 26 c (p k) % 26 ciphertext.append(chr(c ord(a))) else: ciphertext.append(char) return .join(ciphertext)解密则是加密的逆过程def formula_decrypt(ciphertext, key): plaintext [] key_len len(key) for i, char in enumerate(ciphertext.lower()): if char.isalpha(): c ord(char) - ord(a) k ord(key[i % key_len]) - ord(a) # 解密公式(密文 - 密钥 26) mod 26 p (c - k 26) % 26 plaintext.append(chr(p ord(a))) else: plaintext.append(char) return .join(plaintext)1.2 查表法实现维吉尼亚方阵提供了另一种直观的实现方式ABCDEFGHIJKLMNOPQRSTUVWXYZAABCDEFGHIJKLMNOPQRSTUVWXYZBBCDEFGHIJKLMNOPQRSTUVWXYZACCDEFGHIJKLMNOPQRSTUVWXYZAB.................................................................................ZZABCDEFGHIJKLMNOPQRSTUVWXY查表法实现代码def build_vigenere_table(): table [] for i in range(26): row [] for j in range(26): row.append(chr((i j) % 26 ord(a))) table.append(row) return table def table_encrypt(plaintext, key): table build_vigenere_table() ciphertext [] key_len len(key) for i, char in enumerate(plaintext.lower()): if char.isalpha(): row ord(key[i % key_len]) - ord(a) col ord(char) - ord(a) ciphertext.append(table[row][col]) else: ciphertext.append(char) return .join(ciphertext)2. 完整工具开发实战我们将构建一个命令行工具集成加密、解密和自动分析功能。2.1 工具架构设计import argparse from collections import Counter import string class VigenereCipher: def __init__(self): self.table self._build_table() def _build_table(self): # 同前文查表法实现 pass def encrypt(self, text, key, methodformula): # 实现加密逻辑 pass def decrypt(self, text, key, methodformula): # 实现解密逻辑 pass def crack(self, ciphertext, max_key_length20): # 实现自动破解 pass2.2 命令行接口实现def main(): parser argparse.ArgumentParser(description维吉尼亚密码工具) parser.add_argument(action, choices[encrypt, decrypt, crack], help执行的操作类型) parser.add_argument(--text, requiredTrue, help输入文本) parser.add_argument(--key, help加密/解密密钥) parser.add_argument(--method, choices[formula, table], defaultformula, help加密/解密方法) parser.add_argument(--max-key-length, typeint, default20, help破解时尝试的最大密钥长度) args parser.parse_args() cipher VigenereCipher() if args.action encrypt: if not args.key: raise ValueError(加密操作需要提供--key参数) result cipher.encrypt(args.text, args.key, args.method) elif args.action decrypt: if not args.key: raise ValueError(解密操作需要提供--key参数) result cipher.decrypt(args.text, args.key, args.method) else: result cipher.crack(args.text, args.max_key_length) print(result) if __name__ __main__: main()3. 自动破解算法实现维吉尼亚密码的安全性依赖于密钥长度。当密钥长度小于明文时我们可以使用Kasiski测试和频率分析相结合的方法进行破解。3.1 Kasiski测试确定密钥长度def find_repeated_sequences(ciphertext, min_len3): sequences {} for i in range(len(ciphertext) - min_len 1): seq ciphertext[i:imin_len] if seq.isalpha(): if seq in sequences: sequences[seq].append(i) else: sequences[seq] [i] return {k:v for k,v in sequences.items() if len(v) 1} def estimate_key_length(ciphertext): sequences find_repeated_sequences(ciphertext) distances [] for pos_list in sequences.values(): for i in range(1, len(pos_list)): distances.append(pos_list[i] - pos_list[0]) # 计算所有距离的最大公约数 def gcd(a, b): while b: a, b b, a % b return a if not distances: return None current_gcd distances[0] for d in distances[1:]: current_gcd gcd(current_gcd, d) return current_gcd3.2 频率分析破解密钥英语字母频率统计ENGLISH_FREQ { a: 0.08167, b: 0.01492, c: 0.02782, d: 0.04253, e: 0.12702, f: 0.02228, g: 0.02015, h: 0.06094, i: 0.06966, j: 0.00153, k: 0.00772, l: 0.04025, m: 0.02406, n: 0.06749, o: 0.07507, p: 0.01929, q: 0.00095, r: 0.05987, s: 0.06327, t: 0.09056, u: 0.02758, v: 0.00978, w: 0.02360, x: 0.00150, y: 0.01974, z: 0.00074 }破解单个密钥字符def frequency_analysis(text): counter Counter(c for c in text.lower() if c.isalpha()) total sum(counter.values()) freq {char: count/total for char, count in counter.items()} best_score float(inf) best_shift 0 for shift in range(26): score 0 for char in freq: shifted_char chr((ord(char) - ord(a) - shift) % 26 ord(a)) score abs(freq[char] - ENGLISH_FREQ.get(shifted_char, 0)) if score best_score: best_score score best_shift shift return chr(best_shift ord(a))完整破解流程def crack(self, ciphertext, max_key_length20): # 1. 估计密钥长度 key_length estimate_key_length(ciphertext) if not key_length or key_length max_key_length: key_length max_key_length # 2. 按密钥长度分组 groups [[] for _ in range(key_length)] for i, char in enumerate(ciphertext.lower()): if char.isalpha(): groups[i % key_length].append(char) # 3. 对每组进行频率分析 key [] for group in groups: key_char frequency_analysis(.join(group)) key.append(key_char) return .join(key)4. 实战应用与优化技巧4.1 CTF中的典型应用场景识别维吉尼亚密码特征密文字符频率分布相对均匀密钥长度较短时重复序列间距可能暴露密钥长度性能优化技巧# 使用numpy加速矩阵运算 import numpy as np def np_encrypt(plaintext, key): p np.array([ord(c) - ord(a) for c in plaintext.lower() if c.isalpha()]) k np.array([ord(c) - ord(a) for c in key]) k_repeated np.resize(k, len(p)) c (p k_repeated) % 26 return .join(chr(x ord(a)) for x in c)4.2 防御增强策略增加密钥长度密钥长度超过明文长度时成为一次性密码本理论上是不可破解的引入随机填充def pad_text(text, block_size16): pad_len block_size - (len(text) % block_size) return text .join(random.choice(string.ascii_lowercase) for _ in range(pad_len))多重加密def double_encrypt(plaintext, key1, key2): intermediate vigenere_encrypt(plaintext, key1) return vigenere_encrypt(intermediate, key2)在CTF比赛中遇到维吉尼亚密码题目时首先尝试确定密钥长度然后对分组进行频率分析。如果密文足够长这种方法通常能成功破解短密钥的维吉尼亚加密。

更多文章