对称密钥与非对称密钥:算法介绍与场景选择
这章我们来聊聊密钥的两种基本形态——对称和非对称。说实话,刚入行时我也觉得“不就是加密嘛,选一个强的就行”。后来项目做多了才发现,选错算法比选错密码还让人头疼。先搞清楚它们的区别,后面的实战才不会踩坑。
对称密钥:又快又简单,但有一个致命问题
对称加密,说白了就是加密和解密用同一个密钥。就像你家大门,一把钥匙既锁门又开门。优点是快,非常快。硬件加速后,几十GB的数据也就是眨眼的功夫。
常见的对称算法有这些:
| 算法 | 密钥长度 | 分组大小 | 状态 |
|---|---|---|---|
| AES | 128/192/256 bit | 128 bit | 推荐主力 |
| DES | 56 bit | 64 bit | 已淘汰 |
| 3DES | 112/168 bit | 64 bit | 建议迁移 |
| SM4 | 128 bit | 128 bit | 国标推荐 |
| ChaCha20 | 256 bit | 流加密 | 手机端常用 |
我在一个IoT项目里遇到过旧设备还在用DES加密固件升级包。你知道结果吗?测试团队用一台普通笔记本电脑,花了不到2个小时就破解了密钥。嗯,DES的56位密钥在现代硬件面前就是纸糊的。从那以后,我所有新系统都强制 AES-256。如果你在合规场景(比如国内金融、政务),SM4 是必选项。
非对称密钥:安全至上,但别指望它能处理大文件
非对称加密用一对钥匙——公钥和私钥。公钥可以公开,私钥自己保管。别人用你的公钥加密数据,只有你的私钥能解开。听起来完美,但是……速度慢。比对称加密慢几个数量级。你想想看,如果一段1GB的视频用RSA加密,服务器估计要卡到用户投诉。
主流非对称算法:
| 算法 | 典型密钥长度 | 安全强度 | 主要用途 |
|---|---|---|---|
| RSA | 2048 / 4096 bit | 中等 | 数字签名、密钥交换 |
| ECC (ECDSA, ECDH) | 256 bit(相当于RSA 3072) | 高 | 移动端、证书、区块链 |
| SM2 | 256 bit | 高 | 国密标准 |
| Ed25519 | 256 bit | 很高 | 现代签名 |
我曾经在一个支付项目中,把RSA 2048的签名替换成Ed25519。验签性能提升了差不多15倍,密钥存储空间也省了一大截。如果你对性能敏感,ECC家族是更明智的选择。但要注意,ECC的曲线参数不能自己随便定,用标准曲线就好——比如NIST P-256,或者国内就选SM2的推荐曲线。
对称 vs 非对称:到底该用谁?
不是二选一,而是混合使用。实际场景里,你几乎不会直接用非对称加密10MB的数据——太慢了。正确的思路是:用非对称加密一把临时的对称密钥,然后用这把对称密钥去加密真正的数据。这就是**混合加密**,HTTPS和TLS的底层原理。
举个Python例子你马上就能跑:
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import serialization, hashes
import os
# 1. 生成RSA密钥对(非对称)
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# 2. 生成随机的AES对称密钥
aes_key = os.urandom(32) # AES-256
# 3. 用RSA公钥加密AES密钥
encrypted_aes_key = public_key.encrypt(
aes_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 4. 用AES密钥加密实际数据
plaintext = b"你好,这是敏感信息"
nonce = os.urandom(12) # GCM模式需要的初始向量
cipher = Cipher(algorithms.AES(aes_key), modes.GCM(nonce))
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
# 现在你可以安全地传输:encrypted_aes_key + nonce + ciphertext + encryptor.tag
os.urandom(12) 生成nonce。
适用场景速查
下面这份清单我经常在方案评审时拿出来对照,分享给你:
- 大数据量加密(文件、视频、数据库) → 对称算法,AES-256-GCM 或 SM4-GCM
- 密钥分发、建立共享密钥 → 非对称算法,RSA 加密临时密钥,或用ECDH协商
- 数字签名(确认身份、防篡改) → 非对称算法的签名操作:RSA-SHA256、ECDSA、SM2、Ed25519
- 证书与PKI → 非对称密钥(X.509证书里的公钥和私钥),通常搭配ECC或RSA
- 实时通信(如端到端加密) → 混合模式:先ECDH交换会话密钥,再用AES加密消息
- 物联网低功耗设备 → ECC(密钥短,计算快),或者用对称密钥如果设备能安全存储预置密钥
一张图看懂对称与非对称的关系
我习惯在给团队讲课时先画这个流程:对称负责搬砖,非对称管钥匙分发。你看下面这张图:
从图上能看到,非对称只用于保护一个很小的对称密钥(256位),而大块数据走对称加密。这样既解决了密钥分发难题,又保证了加解密速度。几乎所有现代密码协议都是这个架构。
避坑清单
最后汇总几个我亲手踩过的坑,你读完后至少能避开80%的常见问题:
- 不要自己实现算法。 用标准库或稳定库(OpenSSL、cryptography、Bouncy Castle)。我见过同事自己写的AES实现,速度慢三倍还敢上线。
- 密钥长度别图省。 RSA至少2048位,ECC至少256位。曾经有项目用RSA 1024位被密码学团队评审直接打回。
- 非对称不能加密大块数据。 超过密钥长度会失败,浪费计算资源。正确做法是加密对称密钥的Hash或临时密钥。
- 随机数生成器要安全。 Python的
os.urandom可以,别用random模块。在低熵物联网设备上,我曾经吃过这个亏。 - 签名和加密是两回事。 用RSA既做加密又做签名时,记得使用不同的密钥对。否则存在数学攻击风险。
嗯,对称和非对称的算法选型,核心其实就这几个原则。你在项目中遇到具体场景,可以回头看看这张表和我写的那些坑,基本不会跑偏。