概述
密码学 (Cryptography) 包含以下两部分:
- 密码编码学 (Cryptologhy): 研究密码体制 (Cryptosystem).
- 密码分析学 (Cryptanalysis): 研究/破译密码.
密码编码学
密码系统 (密钥体制) 通常由以下五部分组成:
- 消息空间: 所有可能明文的有限集, 通常用 \(\cal{M}\) 表示.
- 密文空间: 所有可能密文的有限集, 通常用 \(\cal{C}\) 表示.
- 密钥空间: 所有可能密钥的有限集, 通常用 \(\cal{K}\) 表示.
- 加密算法: 通常用 E 表示.
- 解密算法: 通常用 D 表示.
柯克霍夫斯原理 (Kerckhoffs's principle): 即使密码系统的任何细节已为人悉知, 只要密匙未泄漏, 它也应是安全的.
该原理看上去似乎有悖常理, 但请注意以下几点:
- 历史经验证明不公开的系统总是非常脆弱的.
- 加密算法难以保密.
- 检验算法是否足够健壮的办法是公开.
在一个可靠的密码体制中, 唯一需要保密的就是密钥.
因此在后面的讨论中, 加密算法 E 和解密算法 D 将假设已知.
密码分析学
破解密码体制的方法有多种, 以下列举几种:
- 经典密码分析 (Classical Cryptanalysis).
- 数学分析法: 研究加密方法的内部结构.
- 蛮力攻击法: 测试密钥空间中的所有密钥.
- 实施攻击 (Implementation Attack).
- 社会工程攻击 (Social Engineering Attack).
TLS
- 安全套接层 (Secure Sockets Layer, SSL).
- 安全传输层协议 (Transport Layer Security, TLS).
- Private Communications Technology, PCT.
SSL 1.0 -> SSL 2.0 -> PCT -> SSL 3.0 -> TLS 1.0
古典密码
替换密码 (Subsitiution cipher)
凯撒密码
对字母进行偏移(shift).
- \(E_n(x) = (x + n) \text{ mod } 26\).
- \(D_n(x) = (x - n) \text{ mod } 26\).
当偏移量 \(n = 3\) 时是凯撒密码 (Caesar cipher), 这也意味着凯撒密码不属于密码系统, 因为其没有密钥.
fn E(plaintext: &str, key: u8) -> String {
let key = key % 26;
plaintext
.chars()
.map(|c| {
if c.is_ascii_lowercase() {
((c as u8 - b'a' + key) % 26 + b'a') as char
} else if c.is_ascii_uppercase() {
((c as u8 - b'A' + key) % 26 + b'A') as char
} else {
c
}
})
.collect()
}
仿射密码 (Affine cipher)
密钥是一张映射表.
密钥空间大小 \(|\cal{K}| = 26!\).
std::string E(std::string_view plaintext, const std::map<char, char>& key) {
std::string ciphertext;
for (const auto ch : plaintext)
ciphertext.push_back(key.at(ch));
return ciphertext;
}
破解
攻击模式: 唯密文攻击 (ciphertext-only attack).
以英文为例, 这种加密方式不会改变原来语言的特征. 因此可以根据语言的特征进行破解, 如:
- 英文单词出现频率.
- 字母组合出现频率, 如 th/an/in/the 等.
可以看出虽然替换密码的密钥空间不小, 但依然十分的脆弱.
维吉尼亚密码 (Vigenère cipher)
密钥是一个词.
// 假设 A = 0
std::string E(const std::string& plaintext, const std::string& key) {
std::string ciphertext;
for (std::size_t i = 0; i < plaintext.size(); i++)
ciphertext.push_back(
((key[i % key.size()] - 'a') + (plaintext[i] - 'a')) % 26 + 'a');
return ciphertext;
}
破解
攻击模式: 唯密文攻击.
假设 k 长度为 n, 将密文 n 个字母一组进行统计分析.
假设每个分组中字母 h 的出现频率最高, 假设对应明文为 e (文字中出现频率最高的英文字母), 那么就可以算出 h 对应的明文 h - e = c.
若不知道 k 的长度, 可以进行假设 k 的范围并进行暴力测试.
转轮机 (Rotor machines)
- The Hebern machine: single rotor.
- The Enigma: 3-5 rotors.
假设转子数为 n, 密钥空间大小 \(|\cal{K}| = 26^n\).
// single rotor
std::string E(const std::string& plaintext, int key) {
std::string ciphertext;
for (const auto ch : plaintext)
ciphertext.push_back(((key++ % 26) + (ch - 'a')) % 26 + 'a');
return ciphertext;
}
// multiple rotors
std::string E(const std::string& plaintext, std::vector<int> key) {
std::string ciphertext(plaintext.size(), '\0');
for (std::size_t i = 0; i < plaintext.size(); i++) {
for (std::size_t j = 0; j < key.size(); j++) {
ciphertext[i] += (key[j]++ % 26) + (plaintext[i] - 'a');
}
ciphertext[i] = ciphertext[i] % 26 + 'a';
}
return ciphertext;
}
对称密码
英文: Symmetics ciphers.
特点是使用相同的密钥K.
一致性方程: \(D(k, E(k, m)) = m\).
异或(exclusive-OR, XOR)
\(A\) | \(B\) | \(A \oplus B\) |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
- 归零律: \(a \oplus a = 0\).
- 恒等律: \(a \oplus 0 = a\).
- 交换律: \(a \oplus b = b \oplus a\).
- 结合律: \(a \oplus b \oplus c = a \oplus (b \oplus c) = (a \oplus b) \oplus c\).
- 自反: \(a \oplus b \oplus a = b\).