
1. 项目概述从“天书”到“游戏”古典密码的魅力与基石如果你对《达芬奇密码》里那些神秘的符号着迷或者玩过《刺客信条》里用密码筒传递信息的桥段甚至只是小时候和同桌传纸条时用过“字母移位”的暗号那么你已经在不经意间触碰到了“古典密码”的世界。这听起来像是个尘封在历史课本里的名词似乎只属于凯撒、玛丽女王或者二战时期的谍报人员。但事实上它远非故纸堆里的古董。古典密码是现代密码学的“源代码”是理解今天无处不在的加密技术从你手机锁屏到网上支付最直观、最有趣的起点。它用最朴素的方式回答了信息安全最核心的问题如何在不安全的信道上传递只有特定人才能读懂的信息我把这个系列称为“古典密码一”目的不是做枯燥的历史考据而是带你亲手“造轮子”。我们将抛开复杂的数学公式和晦涩的术语像几个世纪前的密码学家一样仅用纸、笔或者几行简单的代码去构建、拆解这些经典的加密方案。你会发现许多看似高深的安全思想其雏形就蕴藏在这些简单而精巧的设计中。无论是作为编程入门的趣味项目还是作为理解现代加密原理的思维训练亦或是单纯满足对“秘密”的好奇心这个系列都将提供一条清晰、可实操的路径。接下来我们就从最著名、也最基础的那一个开始——凯撒密码。它简单到你可能一眼就看穿但正是这种简单让它成为我们剖析密码学核心要素的完美标本。2. 核心原理拆解替换与移位的艺术古典密码虽然形式多样但其核心思想可以归结为两种最基本的操作替换和移位。理解这两种操作就拿到了解开大多数古典密码的钥匙。2.1 替换一对一的信息伪装替换顾名思义就是将明文原始信息中的每个字符按照某种固定的规则替换成另一个字符。这个规则就是“密钥”。凯撒密码是替换的一种特例——等距移位替换。更一般的替换密码其替换表可以是任意混乱的。例如我们可以定义这样一个替换表明文A B C D E F G ...密文X Q K L M P O ...这样“HELLO”加密后就可能变成“KMPPB”。这种密码被称为单表替换密码。它的安全性完全依赖于那张替换表密钥的保密性。一旦对手通过频率分析我们后面会详细讲或其他手段猜出或获取了替换表整个加密体系就崩溃了。注意单表替换密码有一个致命弱点它保留了原始语言的统计特征。在英文中字母‘E’的出现频率远高于‘Z’。在密文中出现频率最高的那个字母很可能就对应着明文中的‘E’。这是古典密码分析中最经典的攻击手段。2.2 移位结构化的位置变换移位也称为置换它不改变字符本身而是改变字符在文本中的位置。比如我们可以将明文写成矩阵然后按列或按某种路线读取从而生成密文。一个简单的例子是栅栏密码。假设明文是“IAMACUTECAT”我们将其按高低交错写成两行I A A U E A T M C T C T然后按行读取得到密文“IAAUEAT MCTCT”。解密时只需知道栅栏数这里是2就能恢复原状。移位密码破坏了明文的结构但如果没有结合替换明文词汇的轮廓可能依然模糊可见特别是去除空格后。更复杂的移位密码会定义更复杂的填充和读取路径。2.3 凯撒密码一个完美的教学案例凯撒密码完美地融合了这两种思想尽管以替换为主。它的操作极其简单将字母表中的每个字母向后或向前移动一个固定的位数。这个“固定的位数”就是密钥。加密过程确定密钥K例如K3。对于明文中的每个字母找到其在字母表中的位置。将位置加上K移位操作。如果加后超过字母表范围如Z后移3位则折返到字母表开头取模运算。输出新位置对应的字母替换操作。用数学公式表示加密过程C (P K) mod 26用数学公式表示解密过程P (C - K) mod 26其中C代表密文字母P代表明文字母K代表密钥mod 26表示对26取模因为英文字母有26个。例如密钥K3时明文 A(0) - (03) mod 26 3 - D明文 X(23) - (233) mod 26 26 mod 26 0 - A所以“ATTACK”加密后成为“DWWDFN”。实操心得在手动计算或编程实现时务必处理好大小写和非字母字符。一个健壮的实现应该保留非字母字符如空格、标点不变并且保持原始的大小写。这看似是细节但在实际应用中至关重要否则加密后的文本会失去可读性甚至被破坏结构。3. 从凯撒到维吉尼亚加密强度的演进如果密码学停留在凯撒密码那秘密将无处遁形。因为凯撒密码的密钥空间太小了只有25种可能的移位排除移位0。攻击者甚至不需要频率分析穷举所有25种可能即可破解。密码学家们很快开始了改进之路。3.1 仿射密码为凯撒增加“乘法”因子仿射密码可以看作是凯撒密码的升级版。它的加密公式变为C (a * P b) mod 26这里有两个密钥a和b。其中b就是凯撒密码中的移位量而a是一个乘数因子。要求为了使加密过程可逆即每个明文字母唯一对应一个密文字母且反之亦然a必须与26互质即最大公约数gcd(a, 26) 1。满足这个条件的a有1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25。共12个。这样一来密钥空间从凯撒的25个扩大到了12 * 26 312个。虽然仍然很小但已经无法用手工穷举了必须借助频率分析。解密公式为P a^(-1) * (C - b) mod 26其中a^(-1)是a在模26下的乘法逆元。3.2 维吉尼亚密码对抗频率分析的里程碑单表替换密码包括凯撒、仿射最大的敌人是频率分析。因为无论替换规则多复杂一个明文字母总是被替换成同一个密文字母。维吉尼亚密码的革命性在于它引入了多表替换的概念。核心思想使用一个关键词Keyword作为密钥而不是一个简单的数字。加密时根据关键词中每个字母的序号A0, B1...来决定对明文中对应字母使用哪个凯撒移位。加密过程确定关键词例如“KEY”。重复关键词使其长度与明文一致KEYKEYKEY...对于明文第i个字母找到关键词第i个字母对应的偏移量K_iK10, E4, Y24。使用偏移量K_i对明文第i个字母进行凯撒加密。例如用“KEY”加密“ATTACKATDAWN”明文 A T T A C K A T D A W N 密钥 K E Y K E Y K E Y K E Y 偏移10 4 24 10 4 24 10 4 24 10 4 24 密文 K X R K G O K X R K A L维吉尼亚密码的威力同一个明文字母如‘A’在不同位置可能被加密成不同的密文字母第一次遇到‘A’用K加密成K第二次用Y加密成Y。这彻底打乱了原始语言的字母频率统计特征使得简单的频率分析失效。在很长一段时间内它被认为是“不可破译”的。注意事项维吉尼亚密码的安全性严重依赖于关键词的长度和随机性。如果关键词很短且与明文相关如一个常见的单词那么它可能通过卡西斯基试验被破解。该试验通过寻找密文中重复出现的片段来推测关键词的长度。因此理想的关键词应该是一个长度与明文相当、完全随机的字符序列。这引出了“一次一密”的概念这是理论上绝对安全的密码但密钥分发和管理极其困难。4. 手工实现与编程模拟理解原理最好的方式就是动手实现。我们分别用手工和Python代码来实践凯撒和维吉尼亚密码。4.1 凯撒密码的Python实现def caesar_cipher(text, shift, modeencrypt): 实现凯撒密码的加密和解密。 :param text: 输入文本 :param shift: 移位量 (0-25) :param mode: encrypt 或 decrypt :return: 加密或解密后的文本 result [] shift shift % 26 if mode decrypt: shift -shift # 解密时反向移位 for char in text: if char.isupper(): # 对大写字母处理 shifted chr((ord(char) - ord(A) shift) % 26 ord(A)) result.append(shifted) elif char.islower(): # 对小写字母处理 shifted chr((ord(char) - ord(a) shift) % 26 ord(a)) result.append(shifted) else: # 非字母字符原样保留 result.append(char) return .join(result) # 示例 plaintext Hello, World! This is a test. key 5 ciphertext caesar_cipher(plaintext, key, encrypt) print(f密文: {ciphertext}) decrypted_text caesar_cipher(ciphertext, key, decrypt) print(f解密后: {decrypted_text})代码解析ord(char)获取字符的ASCII码。ord(char) - ord(A)将大写字母映射到0-25的范围。 shift进行移位。% 26实现折返模运算。 ord(A)映射回ASCII码的大写字母范围。对小写字母同理。保留非字母字符使文本结构完整。4.2 维吉尼亚密码的Python实现def vigenere_cipher(text, keyword, modeencrypt): 实现维吉尼亚密码的加密和解密。 :param text: 输入文本仅处理字母 :param keyword: 关键词仅字母 :param mode: encrypt 或 decrypt :return: 加密或解密后的文本 result [] keyword keyword.upper() key_index 0 for char in text: if char.isalpha(): # 计算当前密钥字母的偏移量 shift ord(keyword[key_index % len(keyword)]) - ord(A) if mode decrypt: shift -shift base ord(A) if char.isupper() else ord(a) shifted chr((ord(char) - base shift) % 26 base) result.append(shifted) key_index 1 # 仅当处理字母时密钥索引才前进 else: result.append(char) return .join(result) # 示例 plaintext Attack at dawn! keyword LEMON ciphertext vigenere_cipher(plaintext, keyword, encrypt) print(f密文: {ciphertext}) decrypted_text vigenere_cipher(ciphertext, keyword, decrypt) print(f解密后: {decrypted_text})关键点密钥keyword被循环使用以匹配明文长度。仅对字母字符进行加密保持标点和空格这是实际应用的常见要求。加解密的核心区别在于shift的正负。4.3 手工加密解密表维吉尼亚表在计算机出现之前密码员使用一种叫做“维吉尼亚方阵”的表格进行手工加解密。这是一个26x26的表格第一行为明文字母第一列为密钥字母交叉点即为密文字母。制作和使用这个表格本身就是理解多表替换的绝佳方式。你可以尝试用Excel或手画一个体验一下“古典”的加密工作流程。5. 古典密码的分析与破解实战设计密码是为了保护信息而分析密码则是为了理解其弱点。作为学习者我们既要会“加密”也要懂“破解”。这不仅能加深对原理的理解更是安全思维的训练——知道如何攻击才能更好地防御。5.1 凯撒密码的破解穷举与频率分析对于凯撒密码破解几乎是 trivial 的。方法一穷举攻击因为密钥只有25种可能1-25我们可以简单地尝试所有移位然后肉眼观察哪一段结果是有意义的英文。这个过程可以瞬间由计算机完成。方法二频率分析攻击即使不知道是凯撒密码单表替换密码都怕频率分析。步骤统计密文中各字母的出现频率。将频率排序与英文标准字母频率表E, T, A, O, I, N, S, H, R, D, L, C, U...进行匹配。假设密文中出现频率最高的字母对应明文中的‘E’据此推算偏移量。用推算出的密钥解密看是否产生有意义的文本。如果不通尝试频率第二高的字母对应‘E’或‘T’。例如一段密文经统计字母‘H’出现最多。假设‘H’对应‘E’则偏移量 key ord(H) - ord(E) 3。用密钥3解密验证即可。5.2 维吉尼亚密码的破解卡西斯基试验与重合指数法破解维吉尼亚密码的关键是确定关键词的长度。一旦长度m被确定那么密文就可以被分解成m组每组都是由同一个凯撒密钥加密的即第一组全由关键词第一个字母加密第二组全由关键词第二个字母加密...。这样每一组就退化成了一个单表替换密码可以用频率分析分别破解。第一步卡西斯基试验推测关键词长度在密文中寻找重复出现的、长度至少为3的字母序列。记录这些重复序列之间的间隔距离。计算这些间隔距离的最大公约数GCD。这个GCD很可能就是关键词的长度。原理密文中出现重复序列通常是因为明文中相同的单词或短语被关键词中相同的部分加密所致。它们之间的间隔很可能是关键词长度的整数倍。第二步弗里德曼重合指数法验证长度重合指数Index of Coincidence, IC是一个更数学化的方法用于衡量一段文本中字母分布的“不均匀性”。自然语言的IC值较高英文约0.065而完全随机文本的IC值接近0.0385。假设关键词长度为m。将密文按每m个字母分组第1 m1, 2m1...字母为第一组第2, m2, 2m2...为第二组以此类推。分别计算每一组的IC值。如果m猜对了那么每一组都是单表替换加密的文本其IC值应接近0.065。如果m猜错了分组会把不同密钥加密的字母混在一起文本更接近随机IC值会接近0.0385。第三步对每组进行频率分析确定长度m后我们就有了m组单表替换密文。对每一组独立进行频率分析如5.1所述即可猜出关键词的每一个字母最终拼接出完整关键词。实操心得在实际破解中卡西斯基试验和重合指数法通常结合使用。卡西斯基试验能给出几个可能的长度的候选比如6 12 18然后用重合指数法去验证哪一个最可能。这个过程现在可以用程序自动化但手工走一遍流程对于理解多表替换密码的脆弱性根源至关重要。你会发现维吉尼亚密码的强度完全依赖于关键词的长度和随机性。一个短且非随机的关键词在分析面前不堪一击。6. 古典密码的现代启示与局限学习古典密码绝不仅仅是为了怀旧。它们像化石一样清晰地展现了密码学进化脉络中的关键节点其蕴含的思想和暴露的弱点至今仍在深刻地影响着现代密码学。6.1 核心安全思想的萌芽密钥的秘密性凯撒密码表明算法的完全公开移位并不影响安全只要密钥移位量保密。这预演了现代密码学的柯克霍夫原则密码系统的安全性应依赖于密钥的保密而非算法的保密。混淆与扩散维吉尼亚密码通过多表替换实现了初步的“混淆”使密文和密钥之间的关系尽可能复杂。虽然古典密码中“扩散”使明文一位的变化影响密文多位的概念不明显但这种增加复杂度的思想是一脉相承的。计算安全 vs. 理论安全古典密码的破解从穷举凯撒到需要频率分析单表替换再到需要更复杂分析维吉尼亚体现了安全性的提升依赖于增加攻击者的计算成本。这与现代密码学追求“计算上不可行”破解的理念一致。而“一次一密”展示了信息论安全的终极形态但其不实用性也警示我们安全必须在理论强度和实际可用性之间取得平衡。6.2 古典密码为何被彻底淘汰尽管有上述思想贡献但古典密码在现代计算面前已毫无招架之力密钥空间过小即使像仿射密码有312个密钥在计算机面前也是瞬间可穷举。无法抵抗统计攻击单表替换保留统计特征维吉尼亚密码在确定周期后也退化为单表替换。现代密码如AES的设计目标之一就是让密文在统计上与随机序列无法区分。缺乏完整性验证古典密码只提供保密性无法防止密文在传输中被篡改。接收方无法验证收到的消息是否与发送方发出的完全一致。现代密码学通过哈希函数和消息认证码来解决这个问题。无法实现身份认证古典密码系统通常假设通信双方共享一个秘密密钥对称加密。这无法解决“你是谁”的问题。在现代网络环境中我们需要公钥密码学来实现数字签名和身份认证。6.3 在何处还能见到它们的身影虽然不再用于严肃的保密通信但古典密码并未消失趣味谜题与游戏逃脱密室、寻宝游戏、某些剧情游戏如《荒野大镖客2》中的藏宝图常使用古典密码作为谜题元素。教育启蒙是理解密码学概念最直观的教具。低强度混淆在某些无需高安全性的场合如简单的游戏存档保护、防止信息被一眼看穿而非防破解可能被简单使用。但必须清醒认识到这绝不等于安全。7. 常见问题与避坑指南在实际动手实现和玩转古典密码的过程中我踩过一些坑也总结了一些技巧。7.1 实现时的技术细节问题1加解密后大小写混乱或标点丢失。原因在编程实现时没有对非字母字符和大小写进行妥善处理。解决在加密循环中使用char.isupper()和char.islower()进行判断分别处理。对于非字母字符直接追加到结果中。这是保持文本格式正确的关键。问题2维吉尼亚密码解密结果不对。原因1关键词中包含非字母字符或加解密时没有统一关键词的大小写。解决在处理前将关键词统一转换为大写或小写。并确保关键词只由字母组成。原因2加密和解密时对非字母字符如空格是否跳过处理逻辑不一致。如果加密时遇到空格跳过了没有消耗密钥字母而解密时没有跳过就会导致密钥错位。解决确保加解密算法中只有处理字母字符时才消耗密钥索引。这是维吉尼亚密码实现中最常见的错误。问题3手工使用维吉尼亚表速度慢且易错。技巧可以记住一个快速心算规则将明文和密钥字母视为数字A0, B1...密文数字 (明文数字 密钥数字) mod 26。解密时明文数字 (密文数字 - 密钥数字) mod 26。负数时加26即可。这比查表快得多。7.2 分析与破解时的误区问题4频率分析对短文本失效。原因频率统计需要足够的样本量。如果密文太短比如只有十几个单词字母频率分布可能完全不符合标准分布导致分析失败。解决对于短密文优先尝试穷举凯撒或结合语言上下文、常见单词如“the”“and”“of”进行猜测。不要迷信频率分析。问题5卡西斯基试验找不到重复序列。原因可能关键词很长或者明文本身重复片段少或者重复片段恰好因为密钥不同而没有在密文中重复。解决尝试寻找长度为2的重复序列。或者直接使用重合指数法遍历可能的关键词长度比如从2到20计算分组后的平均IC值选取最高的几个作为候选长度。问题6破解出的“明文”看起来像乱码但部分单词可读。原因这可能遇到了“伪破解”。特别是在尝试不同关键词长度时可能会偶然得到一个分组其频率分布偶然与英语接近导致分析出一段似是而非的“关键词”。解决用你推测出的关键词去解密整个密文而不仅仅是看分组分析结果。真正的破解应该能产生通顺、有意义的全文。同时检查不同分组分析出的“密钥字母”是否能够组成一个有意义的单词或短语关键词本身可能有含义这也是一个辅助判断。7.3 安全认知的“坑”最大的坑认为古典密码“有用”。这是我必须强调的绝对不要将古典密码用于任何需要真正保密的场合。无论是凯撒、维吉尼亚还是更复杂的仿射、Playfair密码在现代计算机和算法面前都如同透明。它们只是玩具和教学工具。理解它们是为了理解现代加密技术为何要设计得如此复杂是为了培养一种基本的安全直觉。真正的应用请使用经过全球密码学家多年公开检验的现代标准算法如AES对称加密、RSA/ECC非对称加密等并遵循正确的使用模式。