本节摘要:替换密码把明文里的每个字母替换成另一个字母,是密码史上最古老的系统化门派。本节拆解它的两级形态——只移位的凯撒密码与任意乱配的单表替换,算清两者的密钥空间(25 对 26 的阶乘),并解释为什么密钥空间扩大了十几个数量级,安全性却几乎没有改善。
苏维托尼乌斯在《十二帝王传》里记下了凯撒的用法:私人书信中,把每个字母沿字母表向后移三位——A 写成 D,B 写成 E,X 绕回写成 A。收到信的人按反方向移三位即可还原。这就是凯撒密码,规则一句话讲完,却包含了替换密码家族的全部要素:一条变换规则(移位)、一个可更换的参数(移几位)、一条逆变换(反移)。
移位量是这里的密钥。凯撒惯用 3,但移位量可以取 1 到 25 中的任何值——取 0 等于不加密,取 26 与取 0 等价,所以有效密钥只有 25 个。数字 13 的移位后来以 ROT13 的名字在互联网时代复活,用来隐藏剧透与谜底:它自反的特性(加密两次即还原)让它成不了正经加密,却成了一种文化梗。

轮盘图暴露了凯撒密码的结构本质:所有可能的变换就是内圈轮子的 25 个旋转位置。破译者不需要任何聪明才智,只要转一圈试过去——25 次尝试,人力都能完成。罗马时代的多数对手既不识字也没有密码意识,这 25 把"钥匙"才显得够用;一旦对手开始认真分析,凯撒密码的寿命就到了头。
直觉的下一步是:既然规则太规整,那就让替换彻底不规整——构造一张任意的对照表,每个明文字母映射到某个固定的密文字母,26 个字母两两乱配,A 可以对应 Q,B 可以对应 Z。这叫单表替换密码(monoalphabetic substitution),十六、十七世纪的欧洲外交界大量使用,字母配对表即密钥。
它的密钥空间是多少?26 个字母的全排列:26! ≈ 4.03×10²⁶。做个对比:宇宙年龄约 4.3×10¹⁷ 秒,就算每秒验完一亿张替换表,穷举完全部密钥也远超宇宙寿命。从暴力穷举的角度,单表替换看似固若金汤。
问题在于,破译者根本不必穷举。单表替换有一条改不掉的宿命:**同一个明文字母,无论出现在哪里,永远变成同一个密文字母。**明文里 E 出现的频率、位置分布、与其他字母的搭配习惯,全部原封不动地转录到密文里,只是换了件马甲。9 世纪肯迪的频率分析正是冲着这条宿命去的——1.6 节将完整演示这场解剖。单表替换用十几个数量级的密钥空间,换来的只是一句话的嘲讽:"数一数哪个字母最多。"
下面的代码把两种形态都实现出来,并附上一个 25 次循环的凯撒穷举器:
# 凯撒与单表替换(演示用,不代表任何真实强度) def caesar(text, k): out = [] for ch in text: if 'A' <= ch <= 'Z': # 只处理大写字母 out.append(chr((ord(ch) - 65 + k) % 26 + 65)) else: out.append(ch) # 空格与标点原样保留 return "".join(out) cipher = caesar("ATTACK AT DAWN", 3) print(cipher) # DWWDFN DW GDZQ # 凯撒穷举:25 个候选密钥一次跑完 for k in range(1, 26): guess = caesar(cipher, -k) if "ATTACK" in guess: # 用关键词命中判断 print("移位量 =", k, "->", guess) # -> 移位量 = 3 -> ATTACK AT DAWN # 单表替换:用字典表示乱配的替换表 table = dict(zip("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "QWERTYUIOPASDFGHJKLZXCVBNM")) # 一张任意配对表 enc = "".join(table.get(c, c) for c in "HIDE THE GOLD") print(enc) # 密文保留了原文字母的频率结构
| 维度 | 凯撒移位 | 单表替换 |
|---|---|---|
| 密钥形态 | 移位量 1–25 | 26 字母乱配对照表 |
| 密钥空间 | 25 | 26! 约 4×10²⁶ |
| 穷举难度 | 徒手可完成 | 计算上不可行 |
| 实际破法 | 直接穷举 | 频率分析 |
| 致命弱点 | 规则过于规整 | 同字母恒映射同密字 |
⚠️ 常见误解:把"密钥空间大"当成"安全"。凯撒到单表替换的跨越把穷举成本抬高了十几个数量级,但对统计攻击的抵抗力是零。衡量强度看的从来不是最难的那种攻击,而是最省力的那种。
这一节的结论指向一个更深的问题:替换字母这条路,有没有可能既保住"密钥空间大",又抹平"同字母恒映射"的死穴?答案是把一张表拆成多张轮换使用——维吉尼亚密码,也就是 1.5 节的主角。
练习一:把本节的凯撒穷举器改成频率打分版——不靠关键词命中,而是给 25 个候选移位各算一次字母频率与英语标准频率的吻合度,取最高分。你会发现短密文(几十个字母)经常打错分,而两百字母以上几乎必中:统计攻击的置信度与样本量正相关,这正是 1.6 节的伏笔。
练习二:构造一张关键词单表替换表:以单词 CIPHER 开头去重写出,余下字母按字母表顺序接续,得到一张以关键词开头的对照表。这类"关键词密码"在十六世纪的通信里最为流行——它兼顾了可记忆性与对照表的随机感,也原封不动地保留了频率分析的全部破绽。
两道练习的共同结论:替换密码的全部游戏都在替换表上,而它的安全上限早已被语言统计锁死。
报纸的填字游戏与儿童的密码棒谜题至今仍偏爱凯撒与关键词替换,原因恰在于它们的破绽可控:谜题设计者要的不是保密,而是"有规律可循的乐趣"。ROT13 在早期网络社区隐藏剧透也是同构的逻辑——防的是无意瞥见,不是蓄意破解。安全强度从来是相对于用途的陈述,这条温和的注脚为第 7 章的敌手模型做了最早的铺垫:脱离对手谈强度,等于脱离靶子谈射程。
下一节先按下替换门派,补看另一条古老路线——不换字母、只换位置的换位密码,它与替换的结合将引出乘积密码的思想。