3. SM4 算法概述:中国国密标准、发布背景、与 AES 的对应关系

聊完 AES,咱们来看看咱们自己的国密标准——SM4。

说实话,早些年我在做国内政企项目的时候,对国密算法还有点抵触。觉得没必要嘛,AES 全世界都在用,为什么还要搞一套?后来真正接触了 SM4 的规范文档,才发现这里面门道不少。嗯,今天我就带你捋一捋 SM4 到底是个什么来头。

3.1 发布背景:为什么要有自己的算法?

SM4 的前身叫 SMS4,早在 2006 年就被定为中国无线局域网标准 WAPI 的加密算法。2012 年,国家密码管理局正式将其发布为国家密码行业标准,编号 GM/T 0002-2012。

那问题就来了:既然 AES 用的好好的,为什么我们一定还要搞个 SM4 出来?

  • 自主可控:这是最核心的一点。AES 是美国 NIST 发布的标准,虽然现在是公开算法,但依赖它始终存在潜在的合规风险。特别是做政府、金融、军工项目,必须用国密。
  • 合规要求:《网络安全法》以及《密码法》明确要求,关键信息基础设施必须使用商用密码。说白了,项目要过等保,SM4 基本上是必选项。
  • 技术对等:SM4 的算法强度与 AES-128 相当,在安全层面完全可以平替。我记得有一次做海外项目,客户坚持要 AES,但国内总部要求必须用 SM4,最后我们做了双层加密——AES 在外层做兼容,SM4 在内层做人无我有的保护。
一个小知识:SM4 的官方文档叫《GMT 0002-2012 分组密码算法》,你可以在国家密码管理局官网免费下载到 PDF。我建议所有做国密开发的工程师,都把这份文档通读一遍,里面连 S 盒的构造方法都写得很清楚。

3.2 算法核心:SM4 到底长什么样?

SM4 的分组长度是 128 位,密钥长度也是 128 位。这一点跟 AES-128 完全一样。处理方式也是 Feistel 结构——你没看错,不是 SPN 结构。正是这一点让它在实现层面的复杂度比 AES 低一些。

SM4 的轮数固定为 32 轮。每轮只加密半个分组,通过轮函数 F 反复迭代。我记得刚学的时候觉得 32 轮怎么可能比 AES 的 10/12/14 轮快?后来发现 Feistel 结构的每轮运算量比 SPN 小,所以实际加密速度并不慢。

下面我用一个表格把 SM4 和 AES-128 的关键参数摆在一起,你一看就明白对应关系了:

参数 SM4 AES-128
算法族 Feistel 结构 SPN 结构
分组大小 128 位 128 位
密钥长度 128 位 128 位
轮数 32 轮 10 轮
S 盒大小 8×8 位 8×8 位
密钥扩展 32 轮密钥全部扩展 10 轮密钥扩展
加解密结构 加解密相同(密钥逆序) 加解密不同(InvCipher)

这里有个细节你可能感兴趣:SM4 的加解密完全共享同一套代码,只需要把轮密钥逆序使用就行。而 AES 的加解密结构不对称,解密必须实现独立的 InvCipher,或者用等价的等价逆密码。这一点,SM4 在嵌入式系统上确实省事很多。

我曾经在 STM32 上移植过 SM4 和 AES,SM4 的代码量大概少 30%,而且轮函数 F 只需要一个 S 盒。AES 加解密的 S 盒其实不同的,预处理又得额外开销。所以在资源受限的设备上,SM4 比 AES 更友好。

3.3 与 AES 的对应关系:一个维度一个维度来对比

说实话,这两个算法虽然是不同国家、不同机构设计的,但它们在很多层面有天然的对应关系。我当年做选型的时候,就是照着这些对应关系来建立决策矩阵的。

首先是安全等级对应。SM4 的密钥 128 位,AES-128 也是 128 位。从算法设计的角度来说,目前没有任何有效的公开攻击能打破 SM4 的全轮数版本。这一点,百度 2018 年发过一篇,对 SM4 做了全轮数分析,结论是安全的。所以至少在 2030 年之前,你不必担心 SM4 的数学强度问题。

其次是性能对应。在 x86 平台上,AES 有 AES-NI 指令集,加密吞吐量轻松达到几 Gbps。SM4 没专门的硬件指令——至少在目前主流的 x86 上没有。但 ARMv8.2-A 开始已经加入了 SM4 的硬件加速指令。我去年测试过的华为鲲鹏 920 平台上,SM4 的吞吐量完全跟 AES 打平。说白了,硬件决定了一切。

最后是生态对应。AES 的生态已经非常成熟,OpenSSL、libsodium、Bouncy Castle 全部有实现。SM4 的生态这几年也追上来了:OpenSSL 1.1.1 正式支持 SM2/SM3/SM4,GmSSL 项目在 GitHub 有超过 5000 星。我个人习惯是,如果是跨平台项目,直接上 OpenSSL 的 EVP 接口,AES 和 SM4 的切换就是改一行参数的事。

注意一个常见的坑:有的同学以为 SM4 的分组长度跟 AES 一样,所以模式和填充可以直接复用。其实 SM4 只支持 16 字节分组,一些 AES 特有的模式如 XTS、CCM 在 SM4 的官方标准里并没有明确规定。如果你要在项目里用 GCM 模式下的 SM4,建议先确认密码模块的完整实现,否则很容易出现兼容性问题。我曾经就有一次因为没注意这点,SM4-GCM 的 Tag 校验老是失败,最后查出来是底层库的 nonce 处理方式不同。

3.4 SM4 结构示意图

为了让你对 SM4 和 AES 的差异有直观感受,我画了一张对比图。左侧是 SM4 的 Feistel 结构,右侧是 AES 的 SPN 结构。两个算法共存于一个密钥长度和分组长度的相同起点上,但从那里出发,它们选择了完全不同的迭代方式。

SM4 与 AES 结构对比 SM4 (Feistel 结构) AES (SPN 结构) 共同参数:128位密钥 / 128位分组 Feistel 迭代 SPN 迭代 SM4 轮函数 F · 异或 → 非线性 τ → 线性 L · 单 S 盒循环置换 · 32 次完整迭代 加解密代码完全对称 AES 轮函数 · SubBytes → ShiftRows → MixColumns → AddRoundKey · 16 个 S 盒并行 · 10/12/14 轮迭代 加解密需要逆变换 输出:128位密文 SM4:硬件友好, 嵌入式平台表现优秀 代码量少,易于实现 AES:硬件加速强大 x86 生态完善 并行度更高

看到没,左边 SM4 的结构明显更「紧凑」——每轮只处理半个分组,但它重复了 32 次。右边 AES 每轮处理整个 128 位分组,但只重复 10 次。所以两者的 总计算量其实差不多,只是实现方式不同罢了。

3.5 实际选型中的考量

讲了这么多理论和结构,最后还是回到实际问题:你该怎么选?

我个人的经验是这样的:

  • 国内合规项目:没得选,直接 SM4。等保 2.0 明确要求国密算法,不上 SM4 根本过不了测评。
  • 海外面向全球产品:用 AES。AES-NI 带来的性能优势是客观存在的,而且全球 CA 和 TLS 生态全面支持。
  • 混合场景 / 网关设备:同时支持两者。我记得在一个物联网网关项目中,我们要求设备同时支持 SM4 和 AES-128,内部统一用 128 位密钥长度,这样主密钥管理可以复用同一套流程。
你想想看,其实 SM4 跟 AES 不是一个「谁更好」的问题。它们更像是两套平行的密码标准体系,各自在自己的生态里活得好好的。我们做工程选型,看清项目的合规边界和性能需求,哪个能满足条件就用哪个。千万别在合规项目里硬上 AES——那可是给自己找麻烦。