国密算法基础:SM2、SM3、SM4 算法原理归纳总结

做政务国密改造,绕不开三个核心算法:SM2、SM3、SM4。说白了,它们就是中国版的 RSA、SHA-256 和 AES。我一开始接触的时候也懵,后来在某个省级政务平台迁移项目里硬啃了一个月,才算真正搞明白它们之间的关系。今天就跟你聊聊这三兄弟的底牌,顺便把我踩过的坑也抖出来。

1. SM4:对称加密,又快又稳

SM4 是对称分组密码算法,密钥长度 128 位,分组长度也是 128 位。嗯,跟 AES-128 对位竞争。它用的是 32 轮非平衡 Feistel 结构,加密和解密过程完全一样,只是轮密钥使用顺序相反。

我的习惯:每次在项目里验证 SM4 加解密结果,我都用标准测试向量先跑一遍。说白了,就是拿官方给的明文和密钥,算出来的密文必须跟官方一毛一样。这一步千万别跳过,我在某次集成就因为字节序没对齐,调了大半天。

SM4 密钥扩展与轮函数

它把 128 位密钥先拆成 4 个 32 位字,经过 32 轮迭代生成 32 个轮密钥。轮函数里最核心的操作是 S 盒替换 + 线性变换 L。L 变换其实就是 32 位字上的循环移位和异或。

// 伪代码示意 — SM4 一轮加密
// X0, X1, X2, X3 为一组 128 位输入
// rk 为当前轮密钥
temp = X1 ^ X2 ^ X3 ^ rk;
temp = S_box_substitution(temp);     // 非线性替换
temp = L_transform(temp);            // 线性变换
X0_new = X0 ^ temp;

特点总结:SM4 在软件实现上比 SM2 快得多,适合大批量数据加密。但注意,它不提供公钥体系,需要先通过 SM2 等方式协商密钥。

2. SM3:密码杂凑,摘要保真

SM3 生成 256 位杂凑值,也就是 32 字节摘要。它的结构基于 Merkle–Damgård,消息分组 512 位,最后填充。我特别喜欢它的一点:它的压缩函数设计得很紧凑,而且有 64 轮迭代,安全性上对标 SHA-256 甚至略强。

SM3 压缩流程

  1. 消息填充:先补 1 个 '1',再补 0,直到长度 mod 512 = 448,最后加 64 位长度。
  2. 初始化 8 个 32 位状态字 V0 ~ V7(有固定初值)。
  3. 每个 512 位分组经过 64 轮迭代,更新状态字。
  4. 最终 8 个状态字拼接成 256 位摘要。

我曾经遇到一个坑:SM3 的填充分组长度与 SM2 签名时的消息预处理不一样。SM3 自己内部填充是固定的,但 SM2 签名前会用 SM3 对消息 ZA || M 做杂凑,这个 ZA 包含用户身份和公钥信息。千万别把 SM3 的普通摘要直接丢给 SM2 签名,否则验签会失败。

3. SM2:非对称加密与数字签名

SM2 是基于椭圆曲线的公钥密码体制(国标 GB/T 32918)。它支持加密、数字签名、密钥交换。曲线参数是固定的 256 位素域曲线,私钥是随机整数,公钥是曲线上一个点。

我最初被 SM2 的加密长度吓到:密文比明文长很多,因为它要附带椭圆曲线上的点坐标。但在政务场景下,这反而是优势,因为一次加密一个对称密钥正好够用。

SM2 签名与验签流程

  1. 签名方:计算 e = SM3(ZA || M);生成随机数 k;计算椭圆曲线点 (x1, y1) = k*G;计算 r = (e + x1) mod n;计算 s = ((1+dA)^-1 * (k - r*dA)) mod n;输出签名 (r, s)。
  2. 验签方:同样计算 e;计算 t = (r + s) mod n;计算椭圆曲线点 (x1', y1') = s*G + t*PA;检查 r 是否等于 (e + x1') mod n。

关键点:SM2 签名中的随机数 k 必须每次独一无二。我在一个老旧项目里发现有人把 k 写死在代码里,结果签名被重放攻击。这算是政务系统里比较低级但致命的漏洞。

4. 三兄弟的协作关系(SVG 图)

在真实政务改造中,SM2、SM3、SM4 并非各自为战,而是形成一套组合拳。下面这张图展示了典型混合加密流程:

SM2 + SM3 + SM4 混合加密流程 明文数据 M SM4 加密 密文 C SM4 密钥 K SM2 公钥加密 加密密钥 K' SM3 摘要 SM2 签名 Sig 传输包 = C || K' || Sig 混合加密优势 SM4 加密大数据量 SM2 保护会话密钥

5. 三种算法对比一览

做项目选型的时候,我习惯列一个表格贴在墙上。这里我也给你整理了一份:

特性 SM2 SM3 SM4
算法类型 非对称(椭圆曲线) 杂凑(Hash) 对称(分组密码)
密钥/输出长度 私钥 256 bit,公钥 512 bit 摘要 256 bit 密钥 128 bit
主要用途 加密、签名、密钥交换 完整性校验、数字摘要 数据加密
性能比较 较慢(适合小数据) 中等 快(适合大数据)
安全性等级 等效 RSA-3072 等效 SHA-256 等效 AES-128
国标编号 GB/T 32918 GB/T 32905 GB/T 32907

6. 实际改造中的避坑指南

  • 字节序:SM2 和 SM4 的接口通常要求大端序,但有些硬件加密卡是小端。我曾在一次跟密码机对接时,因为字节序反了,加密解密对了,签名验签却一直失败,心里那个憋屈……后来用 memcpy 逐字节打印才定位到。
  • 随机数生成:SM2 签名和密钥生成都需要强随机数。政务环境下,建议使用硬件随机数发生器,别用 rand()。嗯,别问我为什么知道。
  • 密钥管理:SM4 密钥如果用 SM2 公钥加密传输,别忘了同时计算 SM3 摘要并签名。我曾经见过只传了加密的密钥,没签名,中间人可以直接替换密钥包。

核心心法:学国密算法不能光看数学公式,得把这三个算法当成“工具包”来理解。SM2 是门锁,SM3 是封条,SM4 是保险箱。政务系统里,门锁 + 封条 + 保险箱一起用,才能把数据锁得死死的。