加密算法选型:AES、SM4 为国密算法,密钥长度与性能权衡
说到 TDE 加密,第一步就是选算法。市面上那么多算法,为什么我重点拎出 AES 和 SM4?
说白了就两个原因:一是合规,二是通用。AES 是国际标准,性能经过几十年验证;SM4 是国家密码管理局推行的国密算法,国内政企项目绕不开。我在好几个金融客户的 TDE 改造中都碰过选型决策——选错了后面改起来,那叫一个痛苦。
算法核心对比:AES vs SM4
先把最关键的参数摆出来。下面这张表是我整理项目时常用的,你可以直接贴在 wiki 上。
| 对比维度 | AES (Rijndael) | SM4 (原 SMS4) |
|---|---|---|
| 标准来源 | FIPS PUB 197(美国) | GM/T 0002-2012(中国) |
| 分组与密钥长度 | 128 位分组;密钥 128/192/256 位 | 128 位分组;密钥 128 位 |
| 轮数 | 10/12/14 轮(对应密钥长度) | 32 轮 |
| 结构类型 | Substitution-Permutation Network (SPN) | Feistel 网络 |
| 软件实现性能 | 极高(AES-NI 指令集加速) | 中等(无原生指令加速) |
| 硬件实现面积 | 中等 | 较小(适合嵌入式) |
| 密钥扩展复杂度 | 简单(反向时需耗时 key schedule) | 简单(解密时需消耗额外轮密钥) |
密钥长度怎么选?
AES 提供三种密钥长度:128、192、256。你会不会觉得越长越安全?嗯,理论上是的,但实际要考虑侧面。
- AES-128:安全强度足够,几乎所有场景够用。我见过有些老系统还在用 128 位,没出过事。
- AES-192:很少用,不上不下,做中间过渡可以。
- AES-256:安全边际最高,但性能开销约是 128 位的 1.4~1.6 倍。我曾在一个券商核心交易系统里测试过,256 位加密后 TPS 下降了 12%,128 位只降了 5%,最后业务方选了 128。
SM4 只有 128 位密钥,没得选。是不是很遗憾?其实国密专家认为 128 位足够对抗未来十年的计算力了,你想想看,对称密钥 128 位的暴力破解需要 2^128 次尝试,就算量子计算机出来目前也只能把强度砍到 2^64——依然不可行。
结论:如果你不是为防“存储密码100年后仍能被解”的极端场景,选 AES-128 或 SM4 就行。AES-256 只在需要符合特定合规(如某些政府机密级)时才硬上。
性能权衡:那点性能差距重要吗?
重要,但不致命。我在之前做某银行网银系统的 TDE 时,对比过几组数据:
| 算法模式 | 加解密吞吐 (MiB/s) | CPU 使用率增量 | 备注 |
|---|---|---|---|
| AES-128-CBC | 820 | +3.2% | 启用 AES-NI |
| AES-256-CBC | 540 | +5.8% | 启用 AES-NI |
| SM4-CBC | 210 | +8.5% | 纯软件实现 |
| SM4-CTR (并行优化) | 290 | +6.9% | 纯软件 + 线程并行 |
你看,SM4 只有 AES-128 的四分之一不到。但你要注意,表里 SM4 是纯软件,没有硬件加速。而 AES 有 CPU 里的 AES-NI 指令集,这个差距是结构性的。我建议:如果项目跑在国产 CPU(如鲲鹏、飞腾)上,它们大多也已经支持 SM4 硬件加速了,实测能到 500~700 MiB/s,基本可以忽略性能担忧。
避坑:我曾经在一台老旧的 Intel Xeon E5 上部署 SM4,没做任何优化,结果加密一个小型 MySQL 库,IO 就飙到 95%,业务直接超时。后来改用硬件安全模块(HSM)卸载加密才解决。所以,如果服务器不支持 SM4 硬件加速,你又必须用 SM4,建议考虑 HSM 或软硬件协同方案。
画张决策图帮你理清思路
下面这张图是我做 TDE 方案设计时常用的选型流程,从业务需求到最终算法选择,一目了然。
实战建议:到底怎么选?
我个人的经验是,把决策点拆成三块:
- 看政策红线——如果项目涉及密评或等保三级以上,国密是刚需,直接上 SM4 没什么好纠结的。记得提前调研 HSM 或 CPU 加速支持。
- 看性能底线——拿你的业务最大吞吐量去压测。我习惯用 openssl speed 跑一轮,把 AES-128、AES-256、SM4 三个数字记下来,看 CPU 占用是否超过告警线。如果 SM4 纯软实现下 CPU 增量超过 10%,就要考虑硬件卸载了。
- 看运维成本——用 AES 可以复用操作系统和中间件自带的加密库,SM4 可能需要额外装驱动或补丁包。我在一个项目里踩过坑:SM4 的 OpenSSL 引擎版本不兼容导致 k8s 启动失败,排查了整整一个下午。
小技巧:如果是新项目,我建议一开始就把加密算法做成可配置的。比如在配置文件中写 cipher_algorithm=AES-128-CBC,这样以后换国密只用改一行配置和重启服务,不用动代码。这也是“无侵入式”的一部分。
关于密钥扩展与解密的隐藏成本
你可能觉得选好算法和密钥长度就完事了。其实还有一个容易被忽略的点:解密时的密钥扩展开销。
AES 的 key schedule 在加密方向很简单,但解密时需要用逆轮密钥,需要把整个扩展链算出来。SM4 的 Feistel 结构则是对称的,加密和解密流程几乎一样,只是轮密钥反向使用。所以如果你用 SM4,解密性能和加密基本一致;AES 如果每次解密都重新跑 key schedule,加密方向和解密方向会差 10%~20%。
我在一个高并发读取场景中(比如分布式数据库页面解密),就特意把 AES 的轮密钥缓存到内存里,避免每次解密都重复计算。这个优化让整体解密延迟降低了 15 微秒,虽然不大,但在百万 QPS 下就是质变。
一句话总结
选 AES-128 还是 SM4?先看合规再看性能。AES 有硬件加速优势,SM4 有政策护城河。只要做好性能压测和硬件权衡,两者都能在生产环境稳定运行。最后别忘了检查密钥扩展的隐藏成本——十几年前的教训,我帮你提前避了。