国密标准与SM4算法概述
说起国密SM4,我得先跟你聊聊这个背景。
国家密码管理局在2006年发布了SM4算法,当时叫SMS4。到了2012年,它正式成为国家标准——GB/T 32907-2016。
说白了,这就是咱们中国自己的分组密码标准。跟AES一个级别,但实现逻辑完全不同。
我个人习惯把SM4叫做“32轮的轻量级选手”。
它为啥重要?在物联网、金融芯片、政府数据系统里,你绕不开它。
嗯,这里要注意:SM4是必选算法,不是备选。
算法参数一览
先看张表,基本参数一目了然:
| 参数项 | SM4数值 |
|---|---|
| 分组长度 | 128 bits(16字节) |
| 密钥长度 | 128 bits(16字节) |
| 轮数 | 32轮 |
| 结构类型 | Feistel 网络 |
| 轮函数 | 非线性τ + 线性变换L |
| 密钥扩展 | 基于32轮非线性迭代 |
核心点:SM4是Feistel结构,加密和解密用同一套逻辑。轮密钥顺序反过来就行。这在硬件实现上太友好了。
算法原理——我拆开来讲
SM4加密一次处理128位数据,也就是4个32位的字。
为什么是32位?因为现代CPU的寄存器宽度就是32或64位,对齐了效率高。
加密流程
- 输入128位明文,拆成4个32位字:X0, X1, X2, X3
- 进行32轮迭代,每轮用1个轮密钥
- 第32轮结束后,把最后4个32位字倒序组合,输出128位密文
我做个避坑指南:
我曾经见过有人直接把最后一轮输出当作密文,忘了把X32~X35倒序。结果数据死活解不回来。这个倒序步骤,千万别省。
轮函数F
这是SM4最核心的部分。每轮输入是 (Xi, Xi+1, Xi+2, Xi+3),输出是下一个32位字 Xi+4:
公式大概长这样:
X_{i+4} = X_i ⊕ T(X_{i+1} ⊕ X_{i+2} ⊕ X_{i+3} ⊕ rk_i)
其中T是一个复合变换,分两步走:
- 非线性变换τ:把输入的32位拆成4个字节,每个字节过一遍S盒。SM4的S盒是固定的8×8查找表,值跟AES的S盒不一样。
- 线性变换L:对τ输出的32位做循环移位异或操作。
一个小经验:S盒查表时,建议用静态const数组预加载,别每次都算。速度差一个数量级。我当年做TF卡加密时,S盒死记硬背写死在代码里,IO性能直接飙上去。
密钥扩展算法
加密密钥是128位,但我们有32轮,需要32个轮密钥。
怎么变出来的?也是Feistel迭代。
过程大概是这样:
- 将128位密钥拆成4个32位字:MK0, MK1, MK2, MK3
- 先跟4个固定参数FK做异或,得到初始状态值
- 然后迭代32轮,每轮生成一个轮密钥rki
- 生成过程中线性变换L变成了L',这个L'和加密里的L有一字之差
你想想看:为什么密钥扩展和加密共用S盒?
因为这样可以减少电路面积。硬件工程师最喜欢这种设计。软件上也能复用代码。
SM4的核心逻辑结构图
下面这张SVG图,把SM4的整体框架给你捋清楚:
从图中可以清楚看到:左侧加密流程和右侧密钥扩展各走各的迭代,但共享同一个S盒和相似的τ函数。密钥扩展生成的32个rki,顺序喂给加密流程的每一轮。解密时只要把这些轮密钥倒过来用就行。
加密与解密的关系
前文提到了,SM4的解密和加密完全一样。
唯一的区别:解密时轮密钥顺序反过来。
- 加密用:rk0, rk1, rk2, ..., rk31
- 解密用:rk31, rk30, ..., rk0
这个特性让我在项目中省了不少事。做过硬件加速的同学都知道,加解密共用一套逻辑,面积直接省一半。
注意:SM4不是对称算法里唯一这么做的,但能同时满足安全和轻量级的并不多。不要因为它实现简单就轻视它。32轮迭代的安全强度,在目前计算能力下是完全够用的。
算法对比——为什么选SM4
| 对比项 | SM4 | AES-128 |
|---|---|---|
| 分组长度 | 128 bit | 128 bit |
| 密钥长度 | 128 bit | 128 bit |
| 轮数 | 32轮 | 10轮 |
| 结构 | Feistel | SPN |
| 安全性 | 国密认证等级 | 国际主流标准 |
| 合规场景 | 国内金融/政务必选 | 国际通用 |
说白了,如果你的产品要过国密局的合规检测,别想别的,上SM4。
AES再强,在国密合规场景里不认账。我遇到过客户非要两个都支持,结果硬件面积和代码复杂度都翻倍。除非你有海外市场,否则一把梭SM4就够了。
我的一点实践感受
最后聊点经验。
SM4代码实现其实不难,就几百行C代码。但你真的用起来,有几个点容易掉坑里:
- 字节序问题:大部分嵌入式平台是小端,SM4标准按大端定义。转换时一个不小心,加解密结果就对不上。
- 轮密钥缓释:别每加密一块都重新算轮密钥。把rk[32]存起来,性能提升肉眼可见。
- 填充模式:SM4本身是分组密码,消息长度不一定是16的倍数。PKCS7填充是最常见的,但你得确认你的SDK支持哪种填充方式。
记住SM4是基础,但却是一切合规的起点。后面章节我们会扎到集成细节里去,把轮函数、S盒、密钥扩展一行一行敲出来。本章先把脑图搭好,后面才好操作。