SM3算法概述

做密码学这么多年,我接触过不少哈希算法。但第一次看到SM3时,心里挺感慨的——终于有一套咱们自己的标准,不再什么都靠别人了。这一章咱们聊聊SM3从哪里来,它怎么被国家定下来的,再顺手跟SHA-256掰掰手腕。

SM3算法背景

SM3是国密系列里的哈希算法,全称叫SM3密码杂凑算法。2010年国家密码管理局正式发布,2016年升格为国家标准。它的核心任务就是给任意长度的数据“算指纹”——固定输出256位(32字节)的杂凑值。

为什么要有SM3?说白了就两个字:可控。之前很多系统用的SHA-1、SHA-256都是美国标准,万一哪天人家不让用了呢?我在做政务系统时,客户明确要求“必须用国密”,那时候SM3已经成熟,直接拿来用就行。这种需求现在越来越多。

  • 设计年份:2010年发布,2016年国标GB/T 32905-2016
  • 输出长度:256位(32字节)
  • 基础结构:Merkle-Damgård结构 + 压缩函数
  • 安全强度:与SHA-256相当,抗碰撞能力128位

国密标准体系

国密不是只有SM3一个算法。它是一个完整的密码家族。我列个表,大家能看得更清楚。

算法 类型 标准编号 典型用途
SM1 对称加密 内部标准 芯片级加密,不公开算法
SM2 公钥密码 GB/T 32918 数字签名、密钥交换
SM3 哈希算法 GB/T 32905 完整性校验、数字签名辅助
SM4 对称加密 GB/T 32907 数据加密(替代AES)
SM9 标识密码 GB/T 38636 基于标识的密码系统

这里要留意一点:SM3经常和SM2配合使用。数字签名时,先拿SM3把消息算成摘要,再用SM2签名。两者是绑定关系,不能用SHA-256代替SM3,否则就不算合规。

⚠️ 常见坑:我曾经遇到一个项目,把SM3和SM2混着用,但签名算法里的哈希长度没对齐,导致验签失败。后来排查才发现,SM3输出256位,SM2的签名参数必须和它完全匹配。细节决定成败——嗯,搞密码尤其如此。

与SHA-256对比

SHA-256是国际通用的哈希标准,SM3在很多方面都参考了它,但做了不少调整。我挑几个关键差异说说。

对比项 SM3 SHA-256
消息分组大小 512位(64字节) 512位(64字节)
字长 32位 32位
消息扩展 132字(W₀~W₆₇,W'₀~W'₆₃) 64字(W₀~W₆₃)
压缩函数轮数 64轮 64轮
初始值(IV) 固定常量(不同于SHA-256) 固定常量
布尔函数 4个(GG, GG', FF, FF') 3个(Ch, Maj, Σ)
移位/循环移位 多种移位组合 循环右移为主
性能(软件) 略慢于SHA-256(约慢5-10%) 较快

从安全上看,两者目前都没有实际有效的碰撞攻击。SM3在设计时修复了一些SHA-2家族的理论弱点(比如扩展函数的扩散性更好),但实战差距不大。我个人建议:国内合规场景无脑选SM3,国际互通场景才考虑SHA-256。

💡 一个真实体会:有一次我在做CA证书签名改造,要把原来SHA-256签名的证书全部换成SM3。本以为很简单,结果发现证书链上的中间CA也要换,根CA还得更新。最终花了两个月才彻底切完。所以,如果你是设计新系统,一开始就把SM3加上,后面省太多事了。

SM3整体流程(一张图看懂)

下面这张图展示了SM3从输入消息到输出杂凑值的完整流程。嗯,我故意把消息扩展和压缩函数分开画,方便大家理解分层。

SM3 算法整体流程 输入消息 M(二进制) 填充 + 长度编码 (使总长度 ≡ 448 mod 512) 分组:M₁, M₂, …, Mₙ 迭代处理(Merkle-Damgård 结构) 消息扩展:68个字 + 64个W' 压缩函数(64轮迭代 + 状态更新) 最后一块处理完毕否? 否 → 继续下一分组;是 → 输出 256位杂凑值 H(M) 箭头代表数据流向;压缩函数内的64轮迭代是安全性的核心所在

这张图里的“迭代处理”是重点。每个分组都会经过消息扩展和64轮压缩函数,最终得到256位的状态值。我个人经常把这比作“搅拌机”——每轮都加不同的调料,最后出来的就是独一无二的指纹。

避坑与建议

  • 不要自己实现SM3:算法细节多,移位操作容易出错。哪怕你读懂了标准,也别在生产环境手写。调用国家密码局认证的库或者OpenSSL(版本≥1.1.1)就行。
  • 注意大端小端:SM3处理时用的是大端序(Big-Endian),和x86 CPU的小端相反。我在做嵌入式移植时吃过这个亏——算出来的摘要老和标准库不一样。
  • 别和SHA-256混用:同一个系统里尽量统一用国密或用国际标准。混用会增加审计复杂度,而且一旦出了安全问题,两边你都得修。
📌 快速检测方法:用已知测试向量校验你的SM3实现。比如空消息的摘要应该是1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b。我每次换库版本都会先跑一遍这个向量。

好了,SM3的出身、标准、和SHA-256的对比都聊完了。说白了,它就是咱们国家的哈希“标配”,安全够用、生态在壮大。下一块咱们就要钻进它的内部看细节了——消息扩展和压缩函数的每一轮是怎么算的,我会掰开揉碎讲明白。