SM4 分组密码算法原理详解:从设计思想到安全分析

算法原理 · 2026-06-01


title: "SM4 分组密码算法原理详解:从设计思想到安全分析" slug: "sm4-algorithm" excerpt: "SM4 是中国国家密码管理局发布的分组密码算法(GB/T 32907-2016),采用 32 轮非平衡 Feistel 结构,分组和密钥长度均为 128 比特。本文从算法结构、S 盒设计准则、合成置换 T、密钥扩展算法、差分/线性密码分析到与 AES 的全方位对比,系统讲解 SM4 的核心原理与设计取舍。" category: algorithm tags: - SM4 - 分组密码 - Feistel - S盒 - 国密

概述

SM4(原名 SMS4)是中国国家密码管理局于 2006 年发布的商业密码算法,2012 年公开发布,2016 年升级为国家标准 GB/T 32907-2016。该算法设计由中国科学院数据安全与通信保密研究中心(原国家密码管理局商用密码研究中心)主导,主要设计者为吕述望团队。

SM4 的定位很明确:作为 AES 的国产替代方案,用于金融、政务、关键信息基础设施等场景的对称加密。它的核心参数——128 比特分组、128 比特密钥、32 轮迭代——反映了一种与 AES 截然不同的设计哲学:不追求最少的轮数,而是通过更多的轮数和更简单的轮函数来实现可证明的安全性。

在国际标准化方面,SM4 已通过 IETF CFRG 发布为 informational draft(draft-ribose-cfrg-sm4-04),并逐步被纳入 ISO/IEC 标准体系。

算法基本参数

参数SM4AES-128说明
标准编号GB/T 32907-2016NIST FIPS 197SM4 于 2006 年公开算法
分组长度128 bit128 bit相同的分组大小
密钥长度128 bit128/192/256 bitSM4 仅支持 128-bit 密钥
轮数3210/12/14SM4 轮数远多于 AES
结构类型非平衡 FeistelSPN(替换-置换网络)根本性的结构差异
状态表示4 个 32-bit 字4×4 字节矩阵位宽不同
S 盒8→8 bit(256 字节)8→8 bit(256 字节)大小相同,构造方法不同
设计公开时间2006 年1998 年AES 早 8 年

算法结构:非平衡 Feistel 网络

为什么选择 Feistel 而非 SPN?

分组密码的两大主流结构是 SPN(Substitution-Permutation Network,如 AES)和 Feistel 网络(如 DES、Blowfish)。两者的核心区别在于:

  • SPN:每一轮都对整个状态同时做替换(S 盒)和置换(线性层)。扩散速度快(AES 只需 10 轮),但加密和解密的电路不同——解密需要逆 S 盒和逆 MixColumns。
  • Feistel:每一轮只更新状态的一半(将状态分为左右两半,只变换另一半)。扩散较慢,但加解密结构几乎相同——只需将轮密钥倒序使用。
SM4 选择了一种非平衡 Feistel变体:状态不是对半分割,而是分为 4 个 32-bit 字,每轮只更新其中一个字。这种设计的工程优势在于:

  • 加解密复用:加密和解密使用同一套硬件逻辑,仅轮密钥顺序相反
  • 硬件友好:轮函数只操作 32-bit 字,不需要处理完整的 128-bit 状态
  • 软件高效:32-bit 字操作与 32/64 位 CPU 天然对齐

加密流程

SM4 的加密过程可以描述为:

CODE
输入: 明文 P = (X0, X1, X2, X3)    // 4 个 32-bit 字,共 128 bit

对于 i = 0, 1, ..., 31:
    X_{i+4} = X0 ⊕ T(X1 ⊕ X2 ⊕ X3 ⊕ rk_i)
    // 状态左移: (X0, X1, X2, X3) ← (X1, X2, X3, X_{i+4})

输出: 密文 C = (X35, X34, X33, X32)  // 注意最终逆序

用流程图表示:

解密:为什么只需倒序轮密钥?

Feistel 网络的一个关键性质是:解密不需要"逆轮函数",只需将轮密钥倒序使用。这是因为每一轮的变换可以表示为:

CODE
X_{i+4} = X0 ⊕ T(X1 ⊕ X2 ⊕ X3 ⊕ rk_i)

在解密时,已知 (X1, X2, X3, X4),要恢复 X0

CODE
X0 = X4 ⊕ T(X1 ⊕ X2 ⊕ X3 ⊕ rk_i)

这与加密的轮函数形式完全相同!解密过程为:

CODE
对于 i = 31, 30, ..., 0:
    X_i = X_{i+4} ⊕ T(X_{i+1} ⊕ X_{i+2} ⊕ X_{i+3} ⊕ rk_i)

这意味着硬件实现中,加密和解密可以共享同一个轮函数电路,只需要一个多路选择器来决定轮密钥的使用顺序。

S 盒设计:合成置换与代数透明度

S 盒的角色

S 盒(Substitution Box)是分组密码中唯一的非线性组件。如果去掉 S 盒,整个加密就退化为一个线性变换——攻击者只需收集少量明文-密文对,就能通过高斯消元法求出密钥。

S 盒的安全指标:

指标含义AES S 盒SM4 S 盒
差分均匀度 δ抵抗差分攻击的能力,越小越好44
线性逼近度 λ抵抗线性攻击的能力,越小越好1616
非线性度与所有线性函数的最小距离112112
代数次数代数表达式的最高次数77
不动点数S(x)=x 的输入个数00
两个 S 盒在这些核心指标上完全一致——这不是巧合,因为 8-bit S 盒的差分均匀度 4 已经是理论最优值(对于偶数输入位宽,最小差分均匀度为 2^(n/2) = 4)。

AES S 盒的代数构造

AES 的 S 盒构造过程完全公开,分为两步:

CODE
步骤 1: 在 GF(2^8) 上求乘法逆元
        将输入字节视为 GF(2^8) 中的元素(不可约多项式 x^8+x^4+x^3+x+1)
        输出 = a^(-1)(0 映射到 0)

步骤 2: GF(2) 上的仿射变换
        输出 = M · 输入 ⊕ 0x63
        M 是一个 8×8 的二进制矩阵

这种"先求逆、后仿射"的结构被称为 Wide Trail Strategy 的一部分,其优势在于:

  • 差分均匀度有数学证明(上界为 4)
  • 代数结构清晰,便于分析抵抗代数攻击(XSL attack)的能力
  • 满足 nothing-up-my-sleeve 原则——构造过程完全透明

SM4 S 盒:合成置换方法

SM4 的 S 盒设计方法未完全公开。标准文档(GB/T 32907-2016)直接给出了完整的 256 字节查找表,但未说明构造过程。学术界通过逆向分析发现:

CODE
SM4_SBOX(x) = A2 · AES_SBOX(A1 · x ⊕ c1) ⊕ c2

即 SM4 的 S 盒可以表示为:输入仿射变换 → AES S 盒(GF(2^8) 求逆 + 仿射)→ 输出仿射变换。这种方法在学术上称为 composite field(合成域)或 tower field 构造。

这种设计选择的含义:

  • 安全性继承:SM4 S 盒的安全指标与 AES S 盒相同,因为它本质上是 AES S 盒的仿射等价变换
  • 实现复用:在支持 AES-NI 的 x86 处理器上,可以利用 AESENCLAST 指令高效计算 SM4 的 S 盒
  • 透明度争议:构造过程不完全公开,不满足严格的 nothing-up-my-sleeve 原则——虽然最终结果的安全指标可验证,但"为什么选这两个仿射变换"的问题没有完全回答
nothing-up-my-sleeve 原则:密码算法的设计过程必须完全透明,使用的常数必须有可验证的来源(如自然对数的小数部分),以防止设计者在参数中植入后门。

轮函数 T 变换:非线性 + 线性两步走

SM4 的轮函数核心是 T 变换,它是一个合成变换 T = L ◦ τ(先做非线性 τ,再做线性 L)。

第一步:非线性变换 τ

CODE
输入: 32-bit 字 A = (a3, a2, a1, a0)  // 4 个字节

输出: B = (SBOX[a3], SBOX[a2], SBOX[a1], SBOX[a0])

即将 32-bit 字的 4 个字节分别独立查 S 盒。这是 SM4 中唯一的非线性操作。

第二步:线性变换 L

CODE
输入: 32-bit 字 B

输出: C = B ⊕ ROL(B,2) ⊕ ROL(B,10) ⊕ ROL(B,18) ⊕ ROL(B,24)

其中 ROL(B,n) 表示 32-bit 循环左移 n 位。

L 变换的设计目标是扩散——让 τ 输出的一位变化影响尽可能多的输出位。5 路循环移位异或的选择经过精心挑选,使得 L 变换的分支数(Branch Number)达到较优值。

与 AES 线性层的对比

属性AES MixColumnsSM4 线性变换 L
数学基础GF(2^8) 矩阵乘法循环移位 + 异或
MDS 性质是(最大距离可分)
分支数5(理论最优)无简单度量
扩散速度2 轮完全扩散需要更多轮
实现复杂度需要 GF(2^8) 乘法仅移位和异或
AES 的 MixColumns 使用了一个 MDS 矩阵(Maximum Distance Separable,最大距离可分),保证任意非零输入经过该矩阵后,输出中至少有 5 个字节非零(分支数为 5,对于 4×4 矩阵是理论最优)。

SM4 的 L 变换不是 MDS,但通过 32 轮的累积效应,仍然达到了足够的扩散。这是一个以轮数换复杂度的设计取舍。

密钥扩展中的 T' 变换

SM4 的密钥扩展使用了一个类似的变换 T' = L' ◦ τ,其中 τ 使用同一个 S 盒,但线性变换 L' 不同:

CODE
L'(B) = B ⊕ ROL(B,13) ⊕ ROL(B,23)

注意 L' 使用 13 和 23 的移位(vs 加密用的 2、10、18、24)。这种差异确保了轮密钥与加密轮函数使用不同的线性变换,防止滑动攻击。

密钥扩展算法

SM4 的密钥扩展将 128-bit 主密钥扩展为 32 个 32-bit 轮密钥(共 1024 bit)。

算法步骤

固定常量

FK(系统参数)CK(轮常量)是标准规定的固定值:

CODE
FK = (0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC)

CK[i] = (ck_{i,0}, ck_{i,1}, ck_{i,2}, ck_{i,3})
其中 ck_{i,j} = (4i + j) × 7 (mod 256)

CK 的生成极其简单——线性公式 (4i+j)×7 mod 256,与 AES 的 Rcon(GF(2^8) 中 2 的幂次)形成鲜明对比。这种简单性在硬件实现中意味着 CK 可以即时计算,不需要存储。

与 AES 密钥扩展的对比

属性AES-128 密钥扩展SM4 密钥扩展
非线性频率每 4 列一次 S 盒每轮一次 S 盒
常量来源Rcon = GF(2^8) 幂次CK = 线性公式
扩展复杂度低(大部分是 XOR 链)较高(每轮完整 T' 变换)
相关密钥安全AES-256 有已知弱点无已知弱点
密钥长度灵活性128/192/256 三档仅 128 bit
SM4 密钥扩展的一个特点是每轮都使用 S 盒,而 AES-128 的密钥扩展中,S 盒每 4 轮才使用一次。这意味着 SM4 的轮密钥之间的非线性关系更强,对相关密钥攻击的抵抗力可能更好。

安全分析

差分密码分析

差分密码分析是分组密码最强大的已知攻击方法之一。其核心思想是:利用明文对的差分(XOR 差)与密文对的差分之间的统计关系来恢复密钥。

对于 SM4:

  • S 盒的差分均匀度为 4:意味着对于任意非零输入差分 Δx,满足 S(x) ⊕ S(x⊕Δx) = Δy 的 x 最多有 4 个
  • 最佳差分特征:文献表明,SM4 的 32 轮完整版本的最佳差分特征概率远低于 2^{-128}
  • 安全轮数:目前最好的差分攻击覆盖约 22-24 轮,距离完整的 32 轮有充足的安全余量

线性密码分析

线性密码分析利用明文、密文和密钥之间的线性逼近来恢复密钥。

  • S 盒的线性逼近度为 16:这是 8-bit S 盒的最优值
  • 线性壳(Linear Hull):SM4 的线性分析需要考虑线性壳效应(多条路径的概率叠加)
  • 安全余量:目前最好的线性攻击覆盖约 22-24 轮,32 轮完整版本有足够余量

积分攻击(Square 攻击)

积分攻击(也称为 Square 攻击或 Saturation 攻击)对 AES 类 SPN 密码特别有效。

对 SM4 的积分攻击研究表明:

  • 由于 SM4 的 Feistel 结构,积分属性的传播比 SPN 更慢
  • 目前最好的积分攻击覆盖约 20 轮
  • 32 轮完整版本有充足的安全余量

不可能差分攻击

不可能差分攻击通过寻找概率为零的差分路径来排除错误的密钥候选。

  • 文献报道了 SM4 的 23 轮不可能差分攻击
  • 完整 32 轮的安全余量约为 9 轮

量子计算威胁

Grover 算法对对称密码的影响是将有效安全强度减半:

算法经典安全强度量子安全强度(Grover)
SM4 (128-bit key)128 bit64 bit
AES-128128 bit64 bit
AES-256256 bit128 bit
SM4 和 AES-128 在量子计算面前的安全边际相同——都从 128 bit 降到 64 bit。这意味着在"量子威胁"场景下,SM4 需要像 AES 一样通过增大密钥长度(如 SM4-256)或使用多重加密来应对。

目前 SM4 仅有 128-bit 密钥版本,尚无 SM4-256 的标准扩展。

PQC 迁移路径:为应对量子威胁,业界主要采用以下方案增强 SM4 的安全性:

  • 混合加密:SM4 + ML-KEM(FIPS 203)混合 KEM,在密钥交换阶段引入 PQC 保护
  • 增大密钥长度:使用 SM4-256(若标准化)将量子安全强度恢复到 128 bit
  • 多层加密:SM4 外层包裹 AES-256,确保至少有一层在量子场景下安全
  • 关注 NIST 和国密标准演进:SM4 的后量子增强方案正在研究中

SM4 vs AES:设计哲学对比

两条路线的取舍

AES 和 SM4 都是优秀的 128-bit 分组密码,但设计哲学截然不同:

CODE
AES 的设计哲学                    SM4 的设计哲学
    ──────────────                    ──────────────
    "用最少的轮数达到安全"            "用最简单的轮函数 + 更多轮数达到安全"
    
    ┌─────────────────┐              ┌─────────────────┐
    │ 复杂轮函数       │              │ 简单轮函数       │
    │ (4 步 SPN)      │              │ (异或+查表+移位) │
    │ 10 轮           │              │ 32 轮           │
    │ 快速扩散        │              │ 慢速扩散        │
    │ 解密需要逆电路   │              │ 加解密几乎相同   │
    └─────────────────┘              └─────────────────┘

硬件加速生态

这是 AES 目前最大的优势:

平台AES 加速SM4 加速差距
x86 (Intel/AMD)AES-NI(2010+)无原生指令~19×(量级估算,取决于工作负载)
ARM (鲲鹏/飞腾)Crypto ExtensionCrypto Extension~1.7×(量级估算)
Apple SiliconCrypto Engine无原生指令~21×(量级估算)
FPGA/ASIC专用电路专用电路持平
在 x86 平台上,AES-NI 的 AESENC 指令一条就能完成一整轮 AES 加密(SubBytes + ShiftRows + MixColumns + AddRoundKey),延迟约 4 个时钟周期。SM4 没有原生指令,需要用多条通用指令模拟。

SM4 在 x86 上的加速思路:

  • AES-NI 模拟:利用 AESENCLAST 指令(只做 SubBytes)来加速 SM4 的 S 盒查找
  • GFNI 指令集:Intel Ice Lake 引入的 GF(2^8) 仿射变换指令可以加速 SM4 S 盒的仿射层

实现面积(硬件)

在 ASIC/FPGA 实现中,SM4 的面积优势明显:

  • SM4 的加密和密钥扩展可以复用同一个 S 盒(加密用 L,扩展用 L')
  • AES 需要独立的 S 盒和逆 S 盒(解密时需要 InvSubBytes)
  • SM4 的轮函数不需要 GF(2^8) 乘法器,面积更小

标准化与合规

国内标准体系

标准编号名称说明
GB/T 32907-2016信息安全技术 SM4 分组密码算法算法主体标准
GM/T 0002-2012SM4 分组密码算法行业标准(旧版)
GB/T 37092-2018信息安全技术 密码模块安全要求涉及 SM4 实现检测

国际标准化

  • ISO/IEC 18033-3:2010:SM4 已被纳入国际标准(块密码算法集)
  • IETF draft-ribose-cfrg-sm4-04:CFRG 发布的 informational draft
  • TLS 国密标准:GM/T 0024(国密 SSL)和 RFC 8998(国密 TLS 1.3)中定义了 SM4 在 TLS 中的使用方式

合规要求

在以下场景中,SM4 是强制性或推荐性的加密算法:

  • 金融行业(央行要求)
  • 关键信息基础设施(等保三级以上)
  • 政务系统(电子政务密码应用要求)
  • 密评(商用密码应用安全评估)

参考来源

相关实践