加密算法基础:对称加密与非对称加密
加密算法的选择,是对象存储安全设计的起点。
我碰到过不少团队,上来就纠结“用 AES 还是 SM4”,或者“RSA 和 ECC 哪个更安全”。
其实,搞清楚这两类算法的核心差异,后面所有决策都顺了。
1. 对称加密
对称加密,说白了就是加密和解密用的是同一把密钥。
你想想看,就像你家大门钥匙,锁门和开门都是它。
在对象存储里,对称加密用于加密数据本身。
密钥管理是痛点——你得确保密钥在传输和存储过程中不被泄露。
1.1 AES(Advanced Encryption Standard)
AES 是目前全球用得最广的对称加密算法。
支持 128、192、256 位密钥长度。
我个人的经验是,对象存储场景中,AES-256 是标配,没有商量的余地。
- 分组密码,明文按 128 位一块处理。
- 加密轮数:AES-128 用 10 轮,AES-256 用 14 轮。
- Java 中直接用
Cipher.getInstance("AES/GCM/NoPadding")。
// AES-256-GCM 示例(Java)
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256);
SecretKey key = kg.generateKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] ciphertext = cipher.doFinal(plaintext);
我的习惯:除非你的业务强制要求国密,否则 AES-256-GCM 是最稳妥的选择。既安全又高效,硬件加速支持广泛。
1.2 SM4(国密对称算法)
SM4 是中国国家密码管理局发布的对称加密标准。
分组长度也是 128 位,密钥长度 128 位,加密轮数 32 轮。
我去年帮一家金融客户做等保改造,就遇到了必须用 SM4 的场景。
技术实现上其实和 AES 没有本质差别,但要注意两点:
- 大多数通用的加密库(如 OpenSSL、Bouncy Castle)已经支持 SM4。
- SM4 的密钥派生和模式(比如 ECB、CBC、GCM)需要单独配置。
// SM4-CBC 示例(使用 Bouncy Castle)
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] ciphertext = cipher.doFinal(plaintext);
关键对比:AES-256 和 SM4 哪家强?
安全性上,两者在合理使用下都不弱。性能上,现代 CPU 对 AES 有专用指令集(AES-NI),而 SM4 目前只能靠纯软件或专用密码卡。如果运行在国产化平台上,SM4 有生态优势。
2. 非对称加密
非对称加密,加密和解密用不同的密钥——公钥和私钥。
公钥可以公开,私钥必须保密。
在对象存储里,非对称加密主要用于密钥交换和数字签名。
比如客户端加密数据时,先随机生成一个对称密钥(数据加密密钥),然后用服务器公钥把这个对称密钥加密后上传。
2.1 RSA(Rivest–Shamir–Adleman)
RSA 是最经典的非对称算法,基于大整数因子分解的数学难题。
密钥长度通常为 2048 位或 4096 位。
- 加密速度慢,适合加密小数据(如对称密钥)。
- 签名验签也常用,比如证书数字签名。
我遇到过一个问题:RSA 4096 位加密 256 位对称密钥,每次耗时约 2-3 毫秒。看起来不多,但如果每秒并发几千次……嗯,CPU 可能会报警。
// RSA 加密公钥操作(Java)
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedKey = cipher.doFinal(symmetricKey);
坑:我曾经在生产环境遇到过 RSA 密钥对生成耗时过长,导致服务启动延迟了 40 秒。解决方案是提前生成好密钥对,存到安全的密钥管理服务(KMS)里,代码只负责加载。
2.2 ECC(Elliptic Curve Cryptography)
ECC 基于椭圆曲线离散对数难题,能用更短的密钥提供和 RSA 同等级别的安全强度。
256 位 ECC 密钥 ≈ 3072 位 RSA 密钥。
我现在的项目里,密钥交换已经全面改用 ECDH(椭圆曲线 Diffie-Hellman)。
速度快,带宽占用小,尤其适合移动端或 IoT 设备。
- 推荐曲线:P-256(secp256r1)、X25519(Curve25519)。
- SM2 是国密的非对称算法,本质也是 ECC。
// ECDH 密钥协商(Java)
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(256);
KeyPair kp = kpg.generateKeyPair();
// 交换公钥后,用 KeyAgreement 算出共享密钥
KeyAgreement ka = KeyAgreement.getInstance("ECDH");
ka.init(kp.getPrivate());
ka.doPhase(peerPublicKey, true);
byte[] sharedSecret = ka.generateSecret();
我的建议:新项目尽量用 ECC 替代 RSA。除非你要兼容老系统、或者签名证书强制要求 RSA。
3. 对称 vs 非对称:选型对比
| 维度 | 对称加密(AES / SM4) | 非对称加密(RSA / ECC) |
|---|---|---|
| 密钥数量 | 一个密钥,共享双方 | 一对密钥(公钥 + 私钥) |
| 加密速度 | 快(GB/s 级别) | 慢(MB/s 级别,甚至更慢) |
| 适用场景 | 加密数据本身 | 密钥分发、数字签名、身份认证 |
| 密钥长度 | 128 / 256 / 128(SM4) | 2048~4096(RSA) / 256~384(ECC) |
| 典型对象存储用法 | 每对象 / 每分片随机生成的数据密钥(DEK) | 用 KMS 公钥加密 DEK,上传到对象存储 |
你想想看,实际对象存储的加密方案都是“混合加密”:
用对称算法加密数据,用非对称算法加密对称密钥。
这样既保证了性能,又解决了密钥分发问题。
避坑指南:我曾经见过一个团队把 RSA 公钥硬编码在客户端代码里,结果公钥泄露后攻击者可以伪造加密请求。正确的做法是把公钥存储在可信的 KMS 或配置中心,并进行签名校验。
对称加密和非对称加密,没有谁取代谁。
它们各自有自己的生态位,结合起来才能构建一个可靠的对象存储加密方案。
记住一句话:用对称加密保护数据,用非对称加密保护对称密钥。