应用层加密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, ChaCha20RSA, ECC, SM2
主要用途大量数据加密密钥交换、数字签名
安全瓶颈密钥泄漏即全盘崩溃私钥泄漏则身份被冒充

混合加密:把两者结合起来

你可能会问,既然非对称加密这么好用,为什么不全用非对称?答案很简单——太慢了。RSA 加密一段 1024 字节的数据,大概需要几毫秒;而 AES 加密同样大小的数据只需要几微秒。差了一千倍。

所以实际系统中几乎都采用 混合加密:

  1. 客户端生成一个随机的对称密钥(叫“会话密钥”)。
  2. 用服务器的公钥加密这个会话密钥(非对称加密)。
  3. 用会话密钥加密真正的业务数据(对称加密)。
  4. 服务器收到后,先用私钥解密得到会话密钥,再用会话密钥解密数据。

这就是 HTTPS 的底层机制。你每次访问的 https:// 页面,背后都在默默地做这套流程。

注意边界:非对称加密的密钥长度是性能杀手。我曾经在嵌入式设备上测试 RSA-4096 解密,一次耗时超过 100 毫秒,导致接口超时。最后改成 ECC P-384,降到 15 毫秒。选型时一定要压测。还有,公钥必须是可信的——中间人攻击可以伪造公钥。解决办法是用 CA 证书链验证公钥的合法性。

流程示意图:混合加密的完整链路

混合加密流程(对称+非对称) 客户端 生成随机会话密钥 K 服务器 拥有公私钥对 (PK, SK) ① 获取服务器公钥 PK ② 用 PK 加密 K 得到 Enc(PK, K) ③ 发送 Enc(PK, K) ④ 用 SK 解密得到 K 得到原始会话密钥 ⑤ 用 K 加密数据 D 得到 Enc(K, D) ⑥ 发送 Enc(K, D) ⑦ 用 K 解密得到 D 还原明文数据 关键安全点 会话密钥 K 生命周期仅一次连接,用完即销毁。公钥 PK 必须通过 CA 证书验证。

选型建议:什么时候用什么

  • 大量数据加密:用对称加密(AES-256-GCM)。比如文件上传、视频流、数据库字段加密。
  • 密钥交换:用非对称加密(ECDH 或 RSA-OAEP)。比如 TLS 握手阶段。
  • 数字签名:用非对称加密(ECDSA 或 RSA-PSS)。比如 JWT 签名、代码签名。
  • 身份认证:用公私钥对做挑战-响应。比如 SSH 登录。

避坑指南:我曾经遇到一个项目,开发人员图省事,直接用 RSA 加密了全部业务数据,结果每天早上高峰时段服务器 CPU 飙升到 100%。解决方法是改成混合加密——只加密 32 字节的会话密钥,其余大数据用 AES。你们在做架构时一定要提前估算加密量和性能。

小结一下

对称加密和非对称加密是应用层加密的两大基石。对称加密快但密钥分发难,非对称加密灵活但慢。实际工程中几乎都是混合使用。你不需要纠结“用哪个更好”,而是问“这个场景该让谁干哪部分活”。