一、多表代替密码:从“固定规则”到“动态变化”的密码革命
1. 定义与核心思想
多表代替密码(Polyalphabetic Substitution Cipher) 是古典密码学的巅峰之作,其核心思想是 “用多个替换表轮换加密”,彻底打破单表代替密码(如凯撒密码)的频率分析漏洞。
-
单表代替密码的弱点:
单表密码(如凯撒密码)的替换规则固定,导致明文字母的频率特征在密文中保留(例如英语中E最常见)。攻击者只需统计字母频率即可破解。 -
多表代替密码的革新:
通过 “周期性切换替换表”,同一个明文字母在不同位置会被加密为不同密文字母。例如:- 明文的“E”可能在第1位加密为“G”,第2位变为“K”,第3位转为“M”。
2. 典型实例:维吉尼亚密码
维吉尼亚密码(Vigenère Cipher) 是多表代替密码的代表作,由法国外交官布莱斯·德·维吉尼亚(Blaise de Vigenère)在16世纪提出(尽管其原型最早由意大利人贝拉索于1553年发明)。
-
技术原理:
维吉尼亚密码使用一个密钥字符串(如“KEY”),将其字母转换为数字(A=0, B=1, ..., Z=25),并周期性地应用凯撒移位。每个明文字母与密钥对应的数字相加(mod 26),生成密文。 -
加密公式:
Ci=(Mi+Kimod n)mod 26Ci=(Mi+Kimodn)mod26
(CiCi:密文字母;MiMi:明文字母;KK:密钥字母序列;nn:密钥长度) -
解密公式:
Mi=(Ci−Kimod n+26)mod 26Mi=(Ci−Kimodn+26)mod26
二、维吉尼亚密码:动态加密的“钥匙串”
1. 例子:图书馆的“动态书号”
假设你是图书馆管理员,需要用维吉尼亚密码保护书籍编号。密钥为“KEY”(K=10, E=4, Y=24),明文为“HELLO”:
-
密钥扩展:
将密钥“KEY”重复至与明文等长:K E Y K E → [10, 4, 24, 10, 4]。 -
加密过程:
- H(7) + K(10) = 17 → R
- E(4) + E(4) = 8 → I
- L(11) + Y(24) = 35 mod 26 = 9 → J
- L(11) + K(10) = 21 → V
- O(14) + E(4) = 18 → S
密文结果:RIJVS
-
解密过程:
- R(17) - K(10) = 7 → H
- I(8) - E(4) = 4 → E
- J(9) - Y(24) = -15 + 26 = 11 → L
- V(21) - K(10) = 11 → L
- S(18) - E(4) = 14 → O
还原明文:HELLO
2. 算法演示(java代码)
public class VigenereCipher {
/**
* 加密函数:使用维吉尼亚密码对明文进行加密
*
* @param plaintext 明文(支持大小写和非字母字符)
* @param key 加密密钥(仅支持大写字母)
* @return 加密后的密文(全大写)
*/
public static String vigenereEncrypt(String plaintext, String key) {
// 将密钥转换为数字数组(A=0, B=1, ..., Z=25)
int[] keyShifts = new int[key.length()];
for (int i = 0; i < key.length(); i++) {
keyShifts[i] = Character.toUpperCase(key.charAt(i)) - 'A';
}
StringBuilder ciphertext = new StringBuilder();
for (int i = 0; i < plaintext.length(); i++) {
char c = Character.toUpperCase(plaintext.charAt(i));
if (Character.isLetter(c)) {
// 取当前密钥偏移量(循环使用密钥)
int shift = keyShifts[i % keyShifts.length];
// 加密逻辑:(明文字符 - 'A' + 密钥偏移量) % 26 + 'A'
char encryptedChar = (char) (((c - 'A' + shift) % 26) + 'A');
ciphertext.append(encryptedChar);
} else {
// 非字母字符直接保留
ciphertext.append(c);
}
}
return ciphertext.toString();
}
/**
* 解密函数:使用维吉尼亚密码对密文进行解密
*
* @param ciphertext 密文(全大写)
* @param key 解密密钥(必须与加密密钥相同)
* @return 解密后的明文(全大写)
*/
public static String vigenereDecrypt(String ciphertext, String key) {
// 将密钥转换为数字数组
int[] keyShifts = new int[key.length()];
for (int i = 0; i < key.length(); i++) {
keyShifts[i] = Character.toUpperCase(key.charAt(i)) - 'A';
}
StringBuilder plaintext = new StringBuilder();
for (int i = 0; i < ciphertext.length(); i++) {
char c = ciphertext.charAt(i);
if (Character.isLetter(c)) {
// 取当前密钥偏移量(循环使用密钥)
int shift = keyShifts[i % keyShifts.length];
// 解密逻辑:(密文字符 - 'A' - 密钥偏移量 + 26) % 26 + 'A'
char decryptedChar = (char) (((c - 'A' - shift + 26) % 26) + 'A');
plaintext.append(decryptedChar);
} else {
// 非字母字符直接保留
plaintext.append(c);
}
}
return plaintext.toString();
}
public static void main(String[] args) {
String plaintext = "HELLO";
String key = "KEY";
// 加密
String ciphertext = vigenereEncrypt(plaintext, key);
System.out.println("加密结果: " + ciphertext); // 输出: RIJVS
// 解密
String decryptedText = vigenereDecrypt(ciphertext, key);
System.out.println("解密结果: " + decryptedText); // 输出: HELLO
}
}
三、历史与现代启示:从“不可破译”到“可被破解”
1. 历史背景
- 发明者争议:维吉尼亚密码虽以维吉尼亚命名,但最早由意大利人贝拉索在1553年提出,后因维吉尼亚的推广而得名。
- “不可破译”的传说:19世纪前,维吉尼亚密码因其动态替换规则被认为是“不可破译”的,甚至被称为“le chiffre indéchiffrable”(法语:不可破译的密码)。
2. 安全性分析
-
优点:
- 打乱字母频率分布,抗单字母频率分析。
- 密钥周期越长,安全性越高。
-
缺点:
- 密钥重复使用:若密钥较短,攻击者可通过卡西斯基测试(Kasiski Examination)或重合指数法(Index of Coincidence)猜测密钥长度,再分组破解。
- 密钥管理:密钥需安全共享,且不能重复使用。
四、从维吉尼亚到现代密码学:动态思想的传承
1. 多表代替密码的现代演化
- 一次一密(One-Time Pad):密钥长度等于明文且随机,理论上无条件安全,但密钥分发困难。
- AES(高级加密标准):现代对称加密算法,通过多轮动态变换(如SubBytes、ShiftRows)实现类似多表代替的混淆效果。
2. 生活中的“动态密码”类比
- 手机指纹锁:每次解锁的验证方式(指纹+时间戳)动态变化,类似多表密码的“密钥轮换”。
- 银行交易验证码:动态口令(如Google Authenticator)每30秒更新,防止密钥重复使用。
五、结语:古典密码的智慧与未来
多表代替密码(尤其是维吉尼亚密码)是密码学从静态到动态的转折点。它教会我们:“变化的规则”比“固定的规则”更难破解。尽管现代密码学已进入量子计算和同态加密时代,但维吉尼亚密码的动态思想依然闪耀——正如我们今天用动态验证码和端到端加密保护数字世界,古典密码的智慧仍在指引未来。