对称加密 vs 非对称加密:为什么两者都需要
1. 为什么要关心这个问题?
这是一个难题:你想给一个素未谋面的人发送加密消息,通过一个任何人都可以窃听的不受信任的网络。
如果你用 AES,你们俩需要相同的密钥。但你如何安全地共享这个密钥… 而不需要已经有一个安全通道?
这就是密钥分发问题,它困扰了密码学家几个世纪。解决方案——非对称加密——从根本上改变了安全通信的工作方式。但它带来的权衡意味着我们仍然需要两种方法。
2. 定义
对称加密: 双方使用相同的密钥进行加密和解密。
- 例子:AES、ChaCha20、3DES
- 类比:一把物理锁,双方都有相同的钥匙
非对称加密: 每一方都有一个密钥对——公钥(可共享)和私钥(保密)。
- 例子:RSA、ECC、ElGamal
- 类比:有投递口的邮箱——任何人都可以投递邮件(公钥),只有主人可以取出(私钥)
3. 根本区别
对称:相同的密钥,相同的问题
Alice Bob
│ │
│ 密钥: 🔑 │ 密钥: 🔑
│ │
├──── Encrypt(message, 🔑) ────────────►│
│ 密文 │
│ ├── Decrypt(密文, 🔑)
│ │ = 消息问题: Alice 和 Bob 是如何都得到密钥 🔑 的?
- 当面见面?无法扩展。
- 通过网络发送?Eve 会截获它。
- 使用另一个加密通道?你也需要那个通道的密钥。
非对称:不同的密钥,不同的角色
Alice Bob
│ │
│ 拥有: Bob 的公钥 📬 │ 拥有: 私钥 🔐
│ │ 公钥 📬
│ │
├──── Encrypt(message, 📬) ────────────►│
│ 密文 │
│ ├── Decrypt(密文, 🔐)
│ │ = 消息解决方案: Bob 公开发布他的公钥 📬。Eve 可以看到——没关系!只有 Bob 的私钥 🔐 能解密用 📬 加密的消息。
4. 性能:房间里的大象
非对称加密解决了密钥分发问题,但引入了巨大的性能损失。
| 操作 | 对称 (AES-256) | 非对称 (RSA-2048) |
|---|---|---|
| 加密速度 | ~1 GB/s | ~1 MB/s |
| 相对速度 | 1x | 慢约 1000 倍 |
| 等效安全性的密钥大小 | 256 位 | 2048 位 |
为什么非对称这么慢?
对称加密使用简单操作:异或、位移、替换表。
非对称加密使用复杂的数学运算:巨大数字的模幂运算(RSA)或椭圆曲线点乘法(ECC)。
# 对称:简单操作重复执行
for round in range(10):
state = substitute(state)
state = shift_rows(state)
state = mix_columns(state)
state = add_round_key(state, key)
# 非对称:繁重的数学运算
ciphertext = (message ** public_exponent) % modulus
# 其中 modulus 是一个 2048 位的数字!5. 真实系统:混合加密
现实世界的系统不在对称和非对称之间选择——它们同时使用两者。
混合方法
┌─────────────────────────────────────────────────────────┐
│ 1. 密钥交换(非对称) │
│ - 生成随机对称密钥(会话密钥) │
│ - 用接收者的公钥加密会话密钥 │
│ - 发送加密后的会话密钥 │
├─────────────────────────────────────────────────────────┤
│ 2. 数据传输(对称) │
│ - 用会话密钥加密实际数据(AES) │
│ - 对大量数据来说快得多 │
└─────────────────────────────────────────────────────────┘TLS 握手示例
客户端 服务器
│ │
│ ──── ClientHello ─────────────────────►│
│ │
│ ◄──── ServerHello + 证书 ──────────── │
│ (包含服务器公钥) │
│ │
│ ──── 密钥交换 ────────────────────────►│
│ (用服务器公钥加密) │
│ │
│ ◄════ 加密数据 (AES-GCM) ═════════════►│
│ (使用派生的会话密钥) │为什么这样有效:
- 非对称加密仅用于密钥交换一次(或几次)
- 对称加密处理大量数据传输
- 你得到了两全其美:安全的密钥分发 + 快速的数据加密
6. 密钥分发问题已解决
非对称密码学之前(1976年前)
要与 N 个人安全通信:
- 你需要 N 个不同的对称密钥
- 每个密钥必须安全交换(当面、可信信使)
- 密钥管理在网络中以 O(N²) 增长
10 人 = 需要 45 个密钥对
100 人 = 需要 4,950 个密钥对
1,000 人 = 需要 499,500 个密钥对非对称密码学之后
要与 N 个人安全通信:
- 每个人有一个密钥对
- 公钥可以公开分发
- 密钥管理以 O(N) 增长
10 人 = 10 个密钥对
100 人 = 100 个密钥对
1,000 人 = 1,000 个密钥对7. 何时使用哪种
在以下情况使用对称加密:
- 双方已经共享一个秘密
- 加密静态数据(文件、数据库)
- 需要高性能
- 你控制通信的两端
在以下情况使用非对称加密:
- 各方之前从未通信过
- 需要数字签名(不可否认性)
- 分发会话密钥
- 验证身份(证书)
在以下情况使用混合:
- 通过不受信任的网络进行安全通信
- 为他人加密大量数据
- 构建任何现实世界的安全通信系统
8. 常见误区
| 误区 | 现实 |
|---|---|
| ”非对称比对称更安全” | 它们有不同的用途;两者都可以是安全的 |
| ”什么都用 RSA 就行” | RSA 慢约 1000 倍且有大小限制 |
| ”256 位 AES = 256 位 RSA 安全性” | 不对!AES-256 ≈ RSA-15360 的安全级别 |
| ”公钥可以解密” | 公钥加密或验证;私钥解密或签名 |
安全级别对等表
| 对称 | RSA | ECC |
|---|---|---|
| 80 位 | 1024 位 | 160 位 |
| 128 位 | 3072 位 | 256 位 |
| 256 位 | 15360 位 | 512 位 |
这就是为什么 ECC 很受欢迎——它用更小的密钥达到与 RSA 相同的安全性。
9. 代码示例:混合加密
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
def hybrid_encrypt(plaintext: bytes, recipient_public_key) -> dict:
# 1. 生成随机 AES 密钥(对称)
aes_key = AESGCM.generate_key(bit_length=256)
# 2. 用 AES 加密数据(快)
nonce = os.urandom(12)
aesgcm = AESGCM(aes_key)
ciphertext = aesgcm.encrypt(nonce, plaintext, None)
# 3. 用 RSA 加密 AES 密钥(非对称)
encrypted_key = recipient_public_key.encrypt(
aes_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return {
'encrypted_key': encrypted_key,
'nonce': nonce,
'ciphertext': ciphertext
}
def hybrid_decrypt(encrypted_data: dict, private_key) -> bytes:
# 1. 用 RSA 解密 AES 密钥
aes_key = private_key.decrypt(
encrypted_data['encrypted_key'],
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 2. 用 AES 解密数据
aesgcm = AESGCM(aes_key)
plaintext = aesgcm.decrypt(
encrypted_data['nonce'],
encrypted_data['ciphertext'],
None
)
return plaintext10. 本章小结
三点要记住:
对称快,非对称解决密钥分发。 对批量数据使用对称,对密钥交换使用非对称。真实系统两者都用。
混合方法是标准。 TLS、PGP 以及几乎所有安全通信协议都使用非对称密码学来交换对称密钥。
不同类型的密钥大小不可比较。 AES-256 提供的安全性大致等于 RSA-15360 或 ECC-512。这就是为什么 ECC 越来越流行——更小的密钥,相同的安全性。
11. 下一步
我们多次提到哈希但没有完整解释它。哈希是加密吗?(剧透:不是。)
在下一篇文章中,我们将探讨:哈希函数实际上做什么,为什么它不是加密,以及存储密码的正确方式。
