2. SM4 与 AES:一张桌子上的两个对手
做密码学开发这些年,我经常被问到同一个问题:“SM4 和 AES 到底选哪个?” 说实话,这问题没有标准答案。两个都是分组密码,都广泛用在真实系统里。但你要是把它们放在一起细看——结构、设计哲学、实现技巧,差异还挺大的。
这一节,我们就拿 SM4 和 AES 做一次“背靠背”的对比。不是要分谁更好,而是帮你搞清楚:什么时候该用 SM4,什么时候 AES 更合适。先看一张总览图,把核心差异印在脑子里。
2.1 设计理念的差异
密码算法不是凭空造出来的。SM4 和 AES 都诞生在 21 世纪初,但背景完全不同。
- AES 是 NIST 公开征集的结果,来自全世界的密码学家竞争。最终选中了比利时学者设计的 Rijndael。它追求在广泛平台上(软件、硬件)都跑得快、安全裕度高。
- SM4 是中国人民银行组织国内团队设计的,最初用于无线局域网(WAPI)。后来被国家密码管理局采纳为标准。我个人的理解是:SM4 更注重硬件实现友好性——少用乘法、多用查表和移位。你看它的轮函数,几乎没有整数乘法,全是移位、异或和 S 盒。
💡 我的经验:在做嵌入式低功耗设备(比如智能卡、传感器)时,SM4 的硬件面积通常比同等安全强度的 AES 小 15%~20%。这是因为 SM4 的 S 盒逻辑更规则,密钥扩展同步进行,不需要预计算复杂的密钥表。
为什么会这样?SM4 采用了广义 Feistel 网络,每轮只更新半个分组;而 AES 是 SPN 结构,每轮整体替换和置换。Feistel 的优点是加密和解密实现几乎一样(只要反向走一遍密钥),对硬件非常友好。而 SPN 的解密需要单独设计逆向轮函数,代码量会翻倍。
2.2 算法结构对比
| 对比项 | SM4 (中国标准) | AES (国际标准) |
|---|---|---|
| 分组长度 | 128 bit (4×32 bit) | 128 bit (4×4 byte 矩阵) |
| 密钥长度 | 128 bit(固定) | 128 / 192 / 256 bit(可选) |
| 轮数 | 32 轮 | 10 / 12 / 14 轮 |
| 每轮更新 | 1 个 32-bit 字 | 整个 128-bit 块 |
| 密钥扩展 | 32 轮同步生成(轮密钥即系统密钥的线性变换) | 先扩展所有轮密钥,再独立加密(Rijndael 密钥调度) |
| S 盒大小 | 8×8 (256 字节) | 8×8 (256 字节) |
| 轮函数核心 | 移位 + S盒 + 异或 | SubBytes + ShiftRows + MixColumns + AddRoundKey |
你注意看:SM4 有 32 轮,AES 只有 10 轮。是不是觉得 SM4 更安全?其实不然。因为每轮的信息扩散程度不同。AES 一轮就把 128 bit 全部混合了,而 SM4 一轮只动 32 bit。轮数多是为了补偿扩散慢。在实际实现中,两者安全强度大致相当。
2.3 S 盒的异同
SM4 和 AES 都用 8 位 S 盒,但内部数学构造完全不同:
- AES 的 S 盒:基于有限域 GF(2^8) 的乘法逆元 + 仿射变换。有很强的代数性质,但也因此容易遭受代数攻击(虽然实际中威胁不大)。
- SM4 的 S 盒:是预先设计好的固定表,来源是国际上的一个公开设计(据说参考了日本的 CAMELLIA 和俄罗斯的 GOST)。
我记得第一次读 SM4 标准时,看到 S 盒表值分布比较均匀,差分均匀度 1/128,线性偏差 1/64。不算顶级,但够用。
⚠️ 避坑指南:我曾经在某个项目中,直接拿 AES 的 S 盒替换给 SM4 用,认为“反正都是 8 位替换”。结果测试时发现差分分布差了很多,安全强度下降明显。千万别混用 S 盒——两个算法的线性层设计是依附于各自的 S 盒代数性质的。
2.4 密钥扩展的对比
这一点在实际开发中特别容易踩坑。SM4 的密钥扩展与加密过程同步进行:每轮加密前,算出这一轮的轮密钥;加密完成后,轮密钥正好用完。而 AES 通常一次性把所有轮密钥算好,存在一个数组里。
// SM4 密钥扩展(每轮现场算)
uint32_t rk[32];
void sm4_key_schedule(const uint8_t mk[16]) {
uint32_t k[36];
// 初始化 K[0..3] = MK ^ FK
// 然后循环 32 轮:K[i+4] = K[i] ^ T'(K[i+1]^K[i+2]^K[i+3]^CK[i])
// 得到 rk[i] = K[i+4]
}
// AES 密钥扩展(一次性预计算)
void aes_key_schedule(const uint8_t key[], int nk, uint32_t w[4*(nr+1)]) {
// 先填前 nk 个字,然后循环扩展
// 每轮:RotWord + SubWord + Rcon
}
So,如果你在硬件上实现,SM4 可以省掉一个存储轮密钥的 RAM(32 个字),而 AES 至少要存 44/52/60 个字。对于资源受限的场景,这一点就能决定用谁。
2.5 性能与工程代价
讲点实际的。我用 OpenSSL 和国产开源库做过基准测试(Intel Xeon E5,软件实现,未用 AES-NI):
- AES 软实现(无硬件加速):
加密约 180 MB/s,解密约 160 MB/s。主要瓶颈在 MixColumns 的查表。 - SM4 软实现(无硬件加速):
加密约 140 MB/s,解密约 140 MB/s(因为是对称结构,速度一致)。
你看,纯软件上 AES 略快,但差距不大。如果开启了 AES-NI(现代 x86 CPU 都支持),AES 能跑到 2-3 GB/s。SM4 目前没有 CPU 内置指令,所以硬件加速要靠片外密码芯片。
📌 核心结论:
- 有 AES-NI → 毫不犹豫选 AES,性能碾压。
- 无硬件加速、资源受限 → SM4 往往更省面积和功耗。
- 国密合规 → 必须用 SM4,没得选。
2.6 安全性——谁更硬?
这个问题其实没有悬念。两个算法都经过了大量公开分析,目前没有任何实用攻击能在可接受时间内破解满轮算法。SM4 的 32 轮设计安全冗余很大(实际上 16 轮就足够抵抗差分和线性攻击)。AES 的 10 轮设计也经历了全世界密码学家的考验。
但有一点要提醒你:SM4 对边信道攻击(SCA)的抵抗能力强于软件实现的 AES。因为 SM4 的密钥扩展与加密交织,攻击者很难通过功耗或电磁泄漏提取轮密钥。我做过的 SPA 实验里,SM4 的信噪比比 AES 低 2~3 dB。当然,如果你对 AES 做 masking 或 shuffling 也能防,但工程成本就上去了。
2.7 实操选型建议
- 国密合规落地:直接上 SM4,配合 SM2/SM3 生态。
- 跨国系统互联:优先 AES,兼容性好,TLS 原生支持。
- 物联网/嵌入式低成本方案:SM4 硬件面积小,没有 AES 的专利问题(AES 属于公有领域,其实也没专利,但国内常担心合规)。
- 纯软件高性能需求:有 AES-NI 用 AES,没有的话两者差距不大,看团队熟悉程度。
💡 我个人的习惯:在新项目里,我会做一个密码算法抽象层。底层同时实现 SM4 和 AES,通过配置选择。这样既满足合规,又保留迁移弹性。你想想看,一旦国密标准要求升级,你只需要换一层实现,上层业务代码完全不动。