3. SM3 密码杂凑算法:数字指纹的国产方案
密码杂凑算法,说白了就是给任意数据算出一个固定长度的“指纹”。这个指纹独一无二,数据改一点,指纹就天翻地覆。SM3 就是咱们国家自己的标准杂凑算法,在很多国密方案里,它都是身份认证的第一道关卡。
我个人习惯把 SM3 叫做“国标指纹机”。它输出的 256 位(32 字节)杂凑值,在身份认证场景里,就是用户的数字身份标识。你想想看,密码不能明文存,但存个指纹总没问题吧?
3.1 SM3 算法原理与流程
SM3 的结构其实和 SHA-256 很像,都是 Merkle-Damgård 结构。但细节上做了不少国产化调整。我拆成几个关键步骤来讲。
3.1.1 消息填充
任何长度的消息,先补位,再补长度。规则很简单:
- 末尾先加一个 1 比特
- 然后加一堆 0,直到长度模 512 等于 448
- 最后附加 64 位的原始消息长度(大端序)
嗯,这里要注意:填充后的消息长度一定是 512 的整数倍。这样就能按 512 位(64 字节)一组来处理了。
3.1.2 迭代压缩
SM3 的核心是 64 轮压缩函数。每一轮用不同的常数和消息字,把 256 位的中间状态搅得面目全非。我画个流程图你就明白了。
SM3 压缩函数核心流程:
初始向量 IV → 消息分组扩展(W0~W67, W'0~W'63)→ 64 轮迭代压缩 → 输出 256 位杂凑值
3.1.3 消息扩展
每一组 512 位的消息,会扩展成 132 个 32 位字:W0~W67 和 W'0~W'63。扩展算法用了异或、循环移位和置换,目的就是让消息位之间充分扩散。
我曾经在调试一个 SM3 实现时,发现扩展后的 W 值总是不对。查了半天,原来是循环移位写成了逻辑移位。嗯,这种细节坑过不少人。
3.2 SM3 与 SHA-256 的对比
很多人问我:SM3 和 SHA-256 到底有啥区别?我直接列个表,一目了然。
| 对比项 | SM3 | SHA-256 |
|---|---|---|
| 输出长度 | 256 位 | 256 位 |
| 分组大小 | 512 位 | 512 位 |
| 压缩轮数 | 64 轮 | 64 轮 |
| 消息扩展 | W0~W67 + W'0~W'63 | W0~W63 |
| 布尔函数 | GG, FF(含异或、与、或) | Ch, Maj(较简单) |
| 循环移位 | 多种移位组合 | 固定右移 |
| 安全性 | 与 SHA-256 相当,部分指标略优 | 国际标准,广泛验证 |
| 国标合规 | GB/T 32905-2016 | 无 |
我的经验:SM3 的布尔函数和移位设计更复杂,理论上抗碰撞能力略强于 SHA-256。但在实际工程中,两者的安全性差距可以忽略。选哪个,主要看合规要求。
3.3 SM3 在身份认证中的应用(数字指纹)
身份认证里,SM3 最常见的用法就是生成“数字指纹”。我举几个实际场景。
3.3.1 密码存储
明文存密码是找死。正确的做法是:
- 用户注册时,对密码做 SM3 杂凑,存杂凑值
- 用户登录时,同样做 SM3,比对杂凑值
- 为了防彩虹表,还要加盐(salt)
代码示例(伪代码):
// 注册
salt = random_bytes(16)
password_hash = SM3(salt + password)
store(username, salt, password_hash)
// 登录
salt, stored_hash = lookup(username)
input_hash = SM3(salt + input_password)
if input_hash == stored_hash:
login_success()
else:
login_fail()
避坑指南:我曾经见过一个项目,直接用 SM3(password) 不加盐。结果用户密码泄露后,攻击者用彩虹表一把全解出来了。记住:杂凑不等于安全存储,加盐是必须的。
3.3.2 消息完整性校验
在身份认证的挑战-响应协议里,SM3 用来保证消息没被篡改。流程是这样的:
- 服务端生成随机数 challenge 发给客户端
- 客户端计算 response = SM3(challenge + 共享密钥)
- 服务端用同样的方式验证 response
你想想看,攻击者就算截获了 challenge 和 response,也无法反推出共享密钥。因为 SM3 是单向的。
3.3.3 数字证书指纹
国密证书(SM2 证书)里,CA 会对证书内容做 SM3 杂凑,然后用 SM2 签名。验证时,接收方先算证书的 SM3 杂凑,再用 CA 公钥验签。这个杂凑值就是证书的数字指纹。
我记得有一次帮客户排查证书链验证失败的问题,发现是中间证书的 SM3 指纹算错了——他们用了 SHA-256 来算国密证书的指纹。嗯,这种混用的情况在过渡期很常见。
3.4 小结
SM3 作为国标杂凑算法,在身份认证里扮演着“数字指纹”的角色。它的原理不复杂,但工程实现时要注意填充、扩展和加盐这些细节。和 SHA-256 比,SM3 更复杂一点,安全性相当,但合规性上不可替代。