对称与非对称加密:什么时候用哪个
编码与加密发布于 2026-10-31
常见误解是把 RSA 当成「更强的 AES」。实际上两者的分工从设计之初就不同:
| 对称加密 | 非对称加密 | |
|---|---|---|
| 密钥 | 加解密用同一把 | 公钥加密、私钥解密(或反过来签名) |
| 速度 | 快(GB/s 级) | 慢(MB/s 级,差 1000 倍) |
| 能加密的数据量 | 任意 | 只能加密很短的数据(RSA-2048 约 190 字节) |
| 解决的核心问题 | 保密 | 密钥怎么安全地给对方 |
| 典型算法 | AES、ChaCha20、SM4 | RSA、ECC、SM2 |
一句话:对称加密负责搬东西,非对称加密负责递钥匙。
对称加密:模式比算法更容易选错
AES 本身是安全的,出事几乎都出在「模式」和「参数」上。
| 模式 | 要不要 IV | 是否防篡改 | 用不用 |
|---|---|---|---|
| ECB | 不要 | 否 | 不要用。相同明文块加密结果相同,图片加密后还能看出轮廓 |
| CBC | 要,随机 | 否,需另加 HMAC | 老系统兼容时用,必须配 HMAC |
| CTR | 要,随机 | 否,需另加 MAC | 同上 |
| GCM | 要,随机且不重复 | 是(自带认证) | 首选。加密 + 完整性一次搞定 |
三个必须记住的点:
- ECB 一定不要用。这不是风格问题 —— 它把数据切成固定块独立加密,明文里的重复结构会原样留在密文里。
- GCM 的 IV 绝对不能重复。同一把密钥下重复使用 IV,会直接泄露明文异或值,而且还能伪造认证标签。这也是为什么不能「固定一个 IV 图省事」。
- CBC 必须自己补 HMAC。只加密不认证,攻击者可以翻转密文位来可控地改变解密结果(padding oracle 攻击)。
需要一次性加密一段文本看效果,AES 加解密 支持 GCM / CBC / CTR 三种模式,可以直观看到 IV 和认证标签的作用。国密场景用 SM4,它是分组密码,用法和 AES 对应。
非对称加密:只做两件事
非对称算法真正的用途只有两个,都不是「加密文件」:
一、加密一小段密钥
TLS 握手就是这样:用 RSA(或 ECDHE)协商出一把临时的对称密钥,之后所有流量都用这把对称密钥加密。这样既拿到非对称的「无需预先共享密钥」,又拿到对称的速度。
二、签名
签名不是加密。它用私钥对数据的哈希做运算,任何人用公钥都能验证「这段数据确实由私钥持有者签发,且没被改动」。
| 加密 | 签名 | |
|---|---|---|
| 用谁的密钥 | 公钥加密,私钥解密 | 私钥签名,公钥验证 |
| 目的 | 保密 | 身份 + 完整性 |
| 谁能做 | 谁都能加密(公钥公开) | 只有私钥持有者能签 |
如果只想要「证明数据没被改」,用签名就够了,不需要加密。反过来,只加密不签名,对方无法确认数据来源。
三个典型误用
用 RSA 加密大文件
RSA-2048 一次只能加密约 190 字节(还要减去 padding)。想加密大文件只能「RSA 加密 AES 密钥 + AES 加密文件」,也就是混合加密。直接硬来的实现会把文件切块逐块 RSA,慢到不可用。
用 RSA 存密码
密码永远不该被加密,只能被哈希。加密是可逆的(有密钥就能还原),而密码系统设计要求「连自己都还原不出来」。
正确的密码存储是 bcrypt / scrypt / Argon2,详见密码该用 bcrypt 还是 SHA。
自己生成 IV 用时间戳或自增数
Date.now() 当 IV 看起来随机,实际可预测;自增数在重启后会重复。IV 必须用密码学安全的随机源(crypto.getRandomValues / SecureRandom)。
国密:SM2 与 SM4 的位置
| 算法 | 类型 | 对应关系 |
|---|---|---|
| SM2 | 非对称(椭圆曲线) | 类似 ECDSA / ECIES,256 位密钥强度约等于 RSA-3072 |
| SM3 | 哈希 | 类似 SHA-256,输出 256 位 |
| SM4 | 对称分组 | 类似 AES,128 位分组与密钥 |
国内金融、政务项目常要求全链路国密。站内的 SM2、SM4 可以做加解密、签名验签的联调验证;SM3 哈希在文本哈希里可选。
注意:SM2 的密文格式(C1C2C3 / C1C3C2)在不同实现间不一致,联调时要确认顺序,否则会「解出来是乱码」。
密钥长度与实际强度
| 对称 | 非对称 | 大致等效强度 |
|---|---|---|
| AES-128 | RSA-3072 / ECC-256 | 128 位 |
| AES-256 | RSA-15360 / ECC-512 | 256 位 |
「AES-256 比 AES-128 强一倍」这种说法在安全强度上不成立(都是「不可暴力破解」级别),AES-256 的实用价值主要在于抗量子攻击的余量。
对称密钥 128 位就够,非对称至少 RSA-2048(新系统建议 3072 或直接用 ECC)。
决策流程
需要保护数据内容吗?
├─ 是 → 数据量大不大?
│ ├─ 大 → AES-GCM 加密数据 + RSA/ECC 加密 AES 密钥(混合加密)
│ └─ 小 → 直接用 AES-GCM 就行,非对称没必要
└─ 否,只需要证明没被改 → 用签名(RSA/ECDSA/SM2)
密码和「需要慢」的场景不在这个流程里 —— 它们要的是哈希,不是加密。
最后提醒一句:不要自己实现加密协议。算法是公开的,出事的是拼接方式:IV 怎么来、密钥怎么管、错误信息会不会泄露信息。用成熟库的封装,把精力放在密钥管理上 —— 那才是真正难的部分。