杂凑算法 SM3 介绍
说起哈希算法,大家肯定不陌生。MD5、SHA-1 这些老面孔在不少系统里都用过,但国密标准里指定的是 SM3。我刚开始接触的时候心想:“不就是又一个哈希吗,能有多大差别?” 等我在一个电子认证项目中真正用它替代 SHA-256 时,才发现坑不少。今天就带你从头捋一遍 SM3,顺带聊聊我踩过的那些雷。
SM3 是什么
SM3 是中国国家密码管理局发布的杂凑算法,输出 256 位(32 字节)摘要,安全性与 SHA-256 相当。它在结构上继承了 Merkle-Damgård 框架,但每一轮的处理细节做了独特设计。说白了,它就是在我们熟悉的 MD 结构上换了自家配方。
核心特点:
- 消息分组长度:512 位(64 字节)
- 摘要长度:256 位(32 字节)
- 压缩函数:64 轮迭代
- 基于 32 位字运算,适合 32 位 CPU 高效实现
算法流程总览
SM3 的处理流程并不复杂,就三步:
- 消息填充——补位到 512 位的整数倍
- 迭代压缩——把每组 512 位数据扔进压缩函数,更新 256 位链接变量
- 输出摘要——最后链接变量的值就是摘要
下面我画了一张流程图,能帮你一眼看清全貌。
消息填充——细节决定成败
填充规则跟 SHA-256 很像,但有一个容易踩坑的点。我直接说规则:
- 先在消息末尾补一个
0x80(二进制 1000 0000) - 然后补
0x00,直到长度满足len(M) ≡ 448 mod 512 - 最后附加 64 位的原始消息长度(大端序)
注意: 长度字段用的是比特长度,而不是字节长度!
我曾经在实现时粗心写了字节数,结果每条消息摘要都错位,排查了整整一下午。就是因为忘记把“字节数 × 8”转成比特数。
// C 语言风格的填充示例(仅示意)
void sm3_pad(unsigned char *msg, int len) {
msg[len] = 0x80;
int zero_len = ( (448 / 8) - (len + 1) % 64 + 64 ) % 64;
// 补 0x00
for (int i = 0; i < zero_len; i++)
msg[len + 1 + i] = 0x00;
// 附加 64 位长度(大端序)
uint64_t bit_len = len * 8;
for (int i = 7; i >= 0; i--)
msg[ ... ] = (bit_len >> (8 * i)) & 0xFF;
}
迭代压缩——SM3 的“心脏”
这部分最值得细看。每 512 位分组进入压缩函数后,经历两大步骤:
- 消息扩展:将 16 个 32 位字扩展成 132 个字(W0~W67 + W'0~W'63)
- 64 轮压缩:每轮使用两个扩展字,更新 8 个链接变量(A~H)
我自己的习惯是先把 SHA-256 的轮函数源码摆出来,再对比 SM3,你会发现 SM3 的布尔函数 GG/FF 设计得更有“国密味”。具体公式这里不列了,但有个重点:
SM3 的轮运算中,每轮要同时使用 Wj 和 W'j,相当于在 SHA-256 基础上多了一道“校验”逻辑,这也是它抗碰撞能力更强的原因之一。
与 SHA-256 的直观对比
我用一张表格帮你快速抓住差异:
| 对比项 | SM3 | SHA-256 |
|---|---|---|
| 输出长度 | 256 位 | 256 位 |
| 分组大小 | 512 位 | 512 位 |
| 轮数 | 64 | 64 |
| 每轮使用字 | Wj + W'j | 仅 Wj |
| 布尔函数 | FF、GG(含循环移位) | Ch、Maj、Σ0、Σ1 |
| 国密合规 | 是 | 否 |
实际性能上,纯软实现 SM3 比 SHA-256 慢 5%~10% 左右,但硬件加速后差距基本抹平。如果你在国密合规场景下,选 SM3 就是唯一解。
应用场景与踩坑记录
SM3 最常见的用法是:
- 数字证书签名前的摘要计算(SM2 签名算法内部就是用 SM3)
- 密钥派生函数(如 TLS 1.3 国密套件中的 KDF)
- 消息完整性校验(HMAC-SM3)
避坑: 我曾经在一个项目中直接用 OpenSSL 的 EVP 接口调 SM3,结果输出长度拿到 256 字节……后来才发现是调用时没设置正确的摘要长度参数。SM3 输出固定 32 字节,千万别被某些旧驱动的缓冲区大小坑了。
另外,SM3 的初始值 IV 也很关键——它是固定的 8 个 32 位字。我建议你在实现时直接写死,不要通过计算得到,否则容易引入隐性 bug。当时我手贱想用 MD5 的 IV 生成方式自动算,结果报错惨不忍睹……老老实实贴常量才是正道。
好了,这一节我们就把 SM3 的来龙去脉讲清楚了。从填充到压缩,从轮函数到对比,核心点在表格和流程图里都能找到。后面几章我们会拿 SM3 和其他国密算法(SM2、SM4)配合密钥分层架构搭一个完整的方案,到时候 SM3 会频繁出现。