凯撒密码密钥推断在常规语句中失效的原因及优化方案咨询
凯撒密码密钥推断方法问题分析与优化方案
一、原方法存在的问题
原方法通过计算加密文本与标准字母频率的差值,经(差值+50)%50/3归一化后取平均值作为密钥,核心问题如下:
- 小文本样本偏差被放大:单句短文本的字母频率与标准频率偏差极大,低频字母的随机波动会拉偏整体平均值,导致密钥推断错误。
- 归一化逻辑与凯撒密码特性不匹配:凯撒密码是26位字母循环位移,原方法使用50取模的归一化完全脱离加密逻辑,无法准确映射位移关系。
- 未区分字母权重:所有字母的频率差被同等对待,但标准频率中高频字母(如E、T)的稳定性远高于低频字母,平均计算会让低频字母的错误干扰结果。
二、更优的凯撒密码密钥推断方案
核心思路:高频字母匹配+频率相关性校验,贴合凯撒密码的位移特性,优先利用高频字母的稳定性缩小候选范围,再通过整体频率相关性验证选出最优解。
具体步骤:
- 统计加密文本的字母频率,提取Top3高频字母。
- 选取标准英文Top3高频字母:E(12.7%)、T(9.1%)、A(8.2%)。
- 计算每个加密高频字母与标准高频字母的位移差(
(密文字母ASCII - 标准字母ASCII) mod 26),生成候选密钥集合。 - 对每个候选密钥,计算解密后文本的字母频率与标准频率的皮尔逊相关系数,系数最高的即为最优密钥。
- 针对极短文本(字母数<50),额外检测解密结果中是否包含常见英文单词(如"the"、"and"),进一步校验密钥准确性。
三、优化后的代码实现
主程序(调整密钥推断逻辑)
import os import collections import string from scipy.stats import pearsonr # 假设ManageFile和Caesar类已实现 attempts = 0 max_attempts = 3 while attempts < max_attempts: input_file_name = input("请输入要分析的文件: ") if input_file_name.endswith('.txt') and os.path.exists(input_file_name): input_text = ManageFile.openFile(input_file_name) if input_text is None: print("错误: 无法读取输入文件。") attempts += 1 else: # 内置标准英文字母频率表 STANDARD_FREQUENCIES = { 'A': 8.2, 'B': 1.5, 'C': 2.8, 'D': 4.3, 'E': 12.7, 'F': 2.2, 'G': 2.0, 'H': 6.1, 'I': 7.0, 'J': 0.15, 'K': 0.77, 'L': 4.0, 'M': 2.4, 'N': 6.7, 'O': 7.5, 'P': 1.9, 'Q': 0.095, 'R': 6.0, 'S': 6.3, 'T': 9.1, 'U': 2.8, 'V': 0.98, 'W': 2.4, 'X': 0.15, 'Y': 2.0, 'Z': 0.074 } analyzer = OptimizedFrequencyAnalyzer(input_text, STANDARD_FREQUENCIES) inferred_cipher_key = analyzer.analyze_text() print("推断出的凯撒密码密钥(位移次数):", inferred_cipher_key) decrypt_file = input("是否解密文件? (y/n): ").lower() if decrypt_file == 'y': decrypted_text = Caesar(inferred_cipher_key).decrypt(input_text) print("解密文本:") print(decrypted_text) inner_attempts = 0 while inner_attempts < max_attempts: output_file_name = input("请输入输出文件名: ") if output_file_name.endswith('.txt'): if os.path.exists(output_file_name): overwrite = input(f"文件'{output_file_name}'已存在,是否覆盖? (y/n): ").lower() if overwrite != 'y': print("解密已取消。") break else: print(f"正在覆盖文件'{output_file_name}'...") ManageFile(input_text, inferred_cipher_key).toFile(output_file_name, decrypted_text) print(f"解密文本已保存到'{output_file_name}'") break else: print("无效的输出文件名,请包含'.txt'扩展名。") inner_attempts += 1 else: print("3次尝试后仍无法读取文件,返回主菜单。") else: print("解密已取消。") break else: print("无效的输入文件名或文件不存在,请包含'.txt'扩展名。") attempts += 1 if attempts >= max_attempts: print("3次尝试后仍无法读取文件,返回主菜单。")
优化后的频率分析类
class OptimizedFrequencyAnalyzer: def __init__(self, text, standard_freq): self._text = text.upper() self._standard_freq = standard_freq self._cleaned_letters = [c for c in self._text if c.isalpha()] self._letter_counts = collections.Counter(self._cleaned_letters) self._total_letters = len(self._cleaned_letters) def _get_candidate_keys(self): # 提取加密文本Top3高频字母 top_cipher_chars = [char for char, _ in self._letter_counts.most_common(3)] # 标准英文Top3高频字母 top_standard_chars = ['E', 'T', 'A'] candidate_keys = set() for cipher_char in top_cipher_chars: for standard_char in top_standard_chars: # 计算位移差:(密文字母 - 明文字母) mod26 即为密钥 key = (ord(cipher_char) - ord(standard_char)) % 26 candidate_keys.add(key) # 若候选过少,补充所有可能密钥(适配极短文本) if len(candidate_keys) < 5: candidate_keys.update(range(26)) return candidate_keys def _calculate_correlation(self, key): # 计算当前密钥解密后的字母频率与标准频率的皮尔逊相关系数 decrypted_freq = {} for char in string.ascii_uppercase: plain_char = chr((ord(char) - ord('A') - key) % 26 + ord('A')) count = self._letter_counts.get(char, 0) decrypted_freq[plain_char] = (count / self._total_letters) * 100 if self._total_letters > 0 else 0 # 按字母顺序提取频率列表用于计算相关性 standard_vals = [self._standard_freq[char] for char in string.ascii_uppercase] decrypted_vals = [decrypted_freq[char] for char in string.ascii_uppercase] corr, _ = pearsonr(standard_vals, decrypted_vals) return corr def analyze_text(self): if self._total_letters == 0: return 0 candidate_keys = self._get_candidate_keys() # 计算每个候选密钥的频率相关性 key_correlation = {key: self._calculate_correlation(key) for key in candidate_keys} # 取相关性最高的密钥 best_key = max(key_correlation, key=key_correlation.get) # 极短文本额外校验:检测常见英文单词 if self._total_letters < 50: decrypted_text = Caesar(best_key).decrypt(self._text) common_words = {'THE', 'AND', 'OF', 'TO', 'A', 'IN', 'IS', 'IT'} decrypted_words = set([word.upper() for word in decrypted_text.split()]) # 若无常见单词,尝试相关性次高的密钥 if not decrypted_words & common_words: sorted_keys = sorted(key_correlation.items(), key=lambda x: -x[1]) for key, _ in sorted_keys[1:]: test_text = Caesar(key).decrypt(self._text) test_words = set([word.upper() for word in test_text.split()]) if test_words & common_words: best_key = key break return best_key
四、优化方案的优势
- 适配小文本场景:通过高频字母匹配缩小候选范围,再用相关性校验过滤错误,单句文本也能准确推断密钥。
- 逻辑贴合加密特性:基于26位循环的位移差计算,完全匹配凯撒密码的加密逻辑,避免无效归一化的干扰。
- 权重分配合理:优先利用高频字母的稳定性,同时通过相关性校验综合所有字母的频率匹配度,减少随机波动影响。
内容的提问来源于stack exchange,提问作者molly k
相关产品推荐
相关产品推荐

