应用层加密SDK集成与密钥生命周期管理 - 第2节
对称加密:一把钥匙开一把锁
我们从一个最直白的场景开始。你有一个保险箱,你和你老婆各有一把完全一样的钥匙。你往里面放东西,锁上;她拿东西,用同一把钥匙开。这就是对称加密——加密和解密用同一把密钥。
我早年做支付接口的时候,对接过一家银行的报文加密。当时对方甩过来一个文档,写着“使用 3DES 加密”。我心里咯噔一下,3DES 早就被 NIST 标记为弱算法了。后来我硬是跟他们沟通了一个月,才升级到 AES-256。嗯,这个坑我替你们踩过了。
对称加密的核心公式很简单:
- 加密:C = E(K, M) —— 密钥 K 加密明文 M 得到密文 C
- 解密:M = D(K, C) —— 同一把密钥 K 解密密文 C 还原明文 M
目前工业界最常用的对称算法是 AES(Advanced Encryption Standard)。AES 有三种密钥长度:128 位、192 位、256 位。我个人习惯能用 256 就不用 128,虽然性能差个两三成,但安全裕度大很多。尤其是合规审计时,256 位基本不会有人挑刺。
重点:对称加密最大的优点是 快。硬件加速后,AES-256 在移动端也能做到微秒级加密。但它有一个天然缺陷——密钥分发。你把密钥发给对方时,如果通道不安全,密钥就被偷了。
AES 代码示例(Java 版)
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class AESUtil {
private static final String ALGORITHM = "AES/ECB/PKCS5Padding";
public static String encrypt(String plainText, String key) throws Exception {
SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, spec);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
public static String decrypt(String cipherText, String key) throws Exception {
SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, spec);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(decrypted);
}
}
提示:上面代码用了 ECB 模式,这在实际生产里不安全。真正上线时请用 AES/GCM/NoPadding,自带认证和初始向量(IV)。曾经有一个团队因为用了 ECB 模式,相同前缀的明文产生相同密文,被统计分析攻击搞崩了。
非对称加密:公钥锁,私钥开
现在换个场景。你有一个保险箱,但这个保险箱有两把不一样的钥匙。一把叫公钥,谁都可以复制;另一把叫私钥,只有你自己拿着。你用公钥锁上箱子,只有私钥能打开。反过来,你用私钥锁上箱子,任何人都能用公钥验证“这确实是你锁的”——这种叫数字签名。
非对称加密的思想是革命性的。它解决了对称加密最头疼的密钥分发问题。你想想看,假如你要跟全球 10 亿用户通信,对称加密你得维护 10 亿把不同的密钥,而用非对称加密,你只需要公开你的公钥就行。
常用的非对称算法:
- RSA:最经典,2048 位以上才安全。我以前维护过一个老系统,用的 RSA-1024,后来被安全扫描报告列为高危,全线加班升级到 4096 位。那滋味,谁经历过谁知道。
- ECC(椭圆曲线密码学):同等安全强度下密钥更短(256 位 ECC ≈ 3072 位 RSA),性能更好。移动端和 IoT 设备首选。
- SM2:国密标准,国内合规项目必须用。我去年接一个政务云项目,对方明确要求只能用 SM2,连签名曲线参数都是固定的。
对称 vs 非对称:一张表说清楚
| 对比维度 | 对称加密 | 非对称加密 |
|---|---|---|
| 密钥数量 | 只有一把密钥 | 公钥 + 私钥(一对) |
| 加密速度 | 非常快(硬件加速下可达 GB/s) | 慢(通常慢数百倍) |
| 密钥分发 | 困难,需安全通道 | 容易,公钥可公开 |
| 典型算法 | AES, SM4, ChaCha20 | RSA, ECC, SM2 |
| 主要用途 | 大量数据加密 | 密钥交换、数字签名 |
| 安全瓶颈 | 密钥泄漏即全盘崩溃 | 私钥泄漏则身份被冒充 |
混合加密:把两者结合起来
你可能会问,既然非对称加密这么好用,为什么不全用非对称?答案很简单——太慢了。RSA 加密一段 1024 字节的数据,大概需要几毫秒;而 AES 加密同样大小的数据只需要几微秒。差了一千倍。
所以实际系统中几乎都采用 混合加密:
- 客户端生成一个随机的对称密钥(叫“会话密钥”)。
- 用服务器的公钥加密这个会话密钥(非对称加密)。
- 用会话密钥加密真正的业务数据(对称加密)。
- 服务器收到后,先用私钥解密得到会话密钥,再用会话密钥解密数据。
这就是 HTTPS 的底层机制。你每次访问的 https:// 页面,背后都在默默地做这套流程。
注意边界:非对称加密的密钥长度是性能杀手。我曾经在嵌入式设备上测试 RSA-4096 解密,一次耗时超过 100 毫秒,导致接口超时。最后改成 ECC P-384,降到 15 毫秒。选型时一定要压测。还有,公钥必须是可信的——中间人攻击可以伪造公钥。解决办法是用 CA 证书链验证公钥的合法性。
流程示意图:混合加密的完整链路
选型建议:什么时候用什么
- 大量数据加密:用对称加密(AES-256-GCM)。比如文件上传、视频流、数据库字段加密。
- 密钥交换:用非对称加密(ECDH 或 RSA-OAEP)。比如 TLS 握手阶段。
- 数字签名:用非对称加密(ECDSA 或 RSA-PSS)。比如 JWT 签名、代码签名。
- 身份认证:用公私钥对做挑战-响应。比如 SSH 登录。
避坑指南:我曾经遇到一个项目,开发人员图省事,直接用 RSA 加密了全部业务数据,结果每天早上高峰时段服务器 CPU 飙升到 100%。解决方法是改成混合加密——只加密 32 字节的会话密钥,其余大数据用 AES。你们在做架构时一定要提前估算加密量和性能。
小结一下
对称加密和非对称加密是应用层加密的两大基石。对称加密快但密钥分发难,非对称加密灵活但慢。实际工程中几乎都是混合使用。你不需要纠结“用哪个更好”,而是问“这个场景该让谁干哪部分活”。