国密 SM3 哈希:中国密码法背后的算法
什么是 SM3?
SM3 是中国国家密码管理局于 2010 年发布的国产密码哈希算法,2016 年正式成为国家标准 GB/T 32905-2016。它的核心功能和其他哈希算法一样:任意长的消息进去,出来一个固定 256 位(32 字节)的杂凑值。
但 SM3 的”身份”比它的技术细节更有故事。
我第一次接触 SM3 是在做一个政务系统的密码改造项目。需求文档上写着”所有哈希算法必须替换为国密算法”,我当时心想——哈希算法不就是 SHA-256 一把梭吗,换个算法能有什么区别?结果一研究才发现,这背后牵涉的东西比我预想的多得多:密码法合规、金融行业强制标准、甚至关系到系统能不能通过等保测评。
简单说,SM3 不是一个”技术上比 SHA-256 更好”的算法(二者在设计层面各有千秋),而是一个”你需要用它来满足中国监管要求”的算法。理解它,和了解等保 2.0、密评(商用密码应用安全性评估)一样,已经成了国内开发者绕不开的功课。
SM3 的工作原理
SM3 和 SHA-256 一样,属于 Merkle-Damgård 结构的哈希函数。整体流程可以拆成三步:消息填充、消息扩展、压缩迭代。
消息填充:和 SHA-256 几乎一样
SM3 的填充规则和 SHA-256 如出一辙——先补一个 1,再补一串 0,最后用 64 位记录原始消息长度,让总长度变成 512 的整数倍。
这就像食堂打饭的大爷——不管你拿的是小碗还是大盆,最后一律按统一的托盘规格放进去,方便后续流水线处理。
消息扩展:SM3 的第一个不同点
这是 SM3 和 SHA-256 拉开距离的地方。SHA-256 把每个 512 位消息块扩展成 64 个 32 位字(W0 到 W63),而 SM3 扩展出 132 个字——先扩展出 W0 到 W67(68 个字),再基于这 68 个字生成 W’0 到 W’63(64 个字),总共 132 个。
多了将近一倍的扩展字意味着什么?意味着每一轮压缩函数能搅和进更多的消息信息,扩散更充分。代价是计算量也上去了——SM3 在纯软件实现下通常比 SHA-256 慢 20% 到 30%。
压缩函数:64 轮,但配方不同
SM3 的压缩函数也是 64 轮,维持 8 个 32 位的工作变量。但它用的布尔函数和常量和 SHA-256 完全不同:
- SM3 使用 FF 和 GG 两个布尔函数,每个都在第 16 轮前后切换一次表达式,逻辑比 SHA-256 的 Ch 和 Maj 更复杂
- SM3 的每一轮都加入了上一步扩展出的 W 和 W’ 两个值,信息注入量比 SHA-256 大一倍
- 常量取自 SM3 自己的标准文档,不是 SHA-256 那种从素数平方根小数部分取值的”洋气”做法——SM3 的常量直接用十六进制写在国标里,少了点数学浪漫,但多了一份”拿来就能验”的直白
回合运算里还有一个 SM3 特有的设计:P0 和 P1 置换函数。P0 用在消息扩展里做比特混合,P1 用在压缩函数里打散中间变量。这两个置换函数和 SHA-256 的 Σ0、Σ1 在思路上类似——都是循环移位加 XOR——但移位的位数和组合方式不同,算是 SM3 设计团队自己的”调味配方”。
最终输出
64 轮压缩跑完后,8 个 32 位工作变量的值拼接起来,就是最终的 256 位哈希。和 SHA-256 一样输出 64 个十六进制字符。
核心特性
| 特性 | 说明 |
|---|---|
| 输出长度 | 256 位(32 字节,64 个十六进制字符) |
| 内部状态 | 512 位分组,8 个 32 位工作变量 |
| 轮数 | 64 轮 |
| 消息扩展 | 132 个字(W0-W67 + W’0-W’63),多于 SHA-256 的 64 个 |
| 结构 | Merkle-Damgård 构造 |
| 标准化 | GB/T 32905-2016(中国国家标准)、ISO/IEC 10118-3(国际标准,2020 年纳入) |
| 抗量子性 | 与 SHA-256 同级别——Grover 算法将 256 位安全性降至 128 位 |
值得一提的是,SM3 在 2020 年被纳入了 ISO/IEC 10118-3 国际哈希标准,成为继 SHA-2、SHA-3 之后又一个国际认可的哈希算法。这给 SM3 增添了一层”国际互认”的背书——不光是中国在用,国际标准体系里也有一席之地。
实际应用场景
1. 金融系统的强制刚需
这是 SM3 渗透率最高的领域。中国人民银行在 2010 年前后就发文要求金融 IC 卡、网上银行系统使用 SM3 做数据完整性保护。到了 2018 年,PBOC 进一步要求银行卡受理终端、支付标记化系统全面切换国密算法。
一个直观的例子:银联的在线支付系统中,交易报文里的 MAC(消息认证码)以前用 SHA-256,现在要求用基于 SM3 的 HMAC-SM3。你刷一次卡、扫一次码,后台系统可能已经跑了几十次 SM3 哈希。
我有一次对接某第三方支付渠道的接口,对方给过来的签名算法列表里足足有五种:RSA-SHA256、RSA-SM3、SM2-SM3、ECDSA-SHA256、SM2-HMAC-SM3。当时我对着这串列表愣了好一会儿——技术选型已经不是”哪个更好”的问题了,而是”对方强制要求哪一种”。
2. 电子政务与等保合规
政务信息系统在通过等保 2.0 三级测评时,密码应用安全性评估(密评)是必查项。如果你的系统涉及身份认证、数据传输完整性、数据存储完整性这三个维度中的任何一个,使用国密算法就成了硬性条件。
SM3 在政务场景中通常和 SM2(椭圆曲线公钥算法)、SM4(分组对称算法)配套使用,构成所谓的”国密三件套”。一个典型的政务数据交换流程是:SM2 做身份认证和密钥协商,SM4 做数据加密传输,SM3 做数据完整性校验。三者在 GB/T 39786-2021《信息安全技术 信息系统密码应用基本要求》中被一同列出,密评机构会逐项核对。
3. 数字证书与 PKI 体系
中国国内的 CA 机构正在大规模发行支持 SM2+SM3 的国密证书。你可以在国家政务服务平台、各省市的政务服务网、税务系统、社保平台里遇到这些证书——浏览器不信任它们(因为没有国际 CA 根证书链),但在安装了国密根证书的专用环境里,它们就是合法的身份凭证。
国密证书的签名算法标识通常是 SM2-WITH-SM3,意思是用 SM2 做签名、用 SM3 做消息摘要。这和 RSA-SHA256 的套路一模一样,只是把国际算法换成国密算法。
4. 区块链存证
国内不少司法存证区块链(如”天平链”、“长安链”)采用了国密算法栈。在这些链上,区块哈希用 SM3、交易签名用 SM2、链上数据加密用 SM4。
说实话,从纯技术角度看,用 SM3 还是 SHA-256 做区块链哈希,安全性上没有本质区别——都是 256 位输出、都是抗碰撞的、都是单向的。但合规部门需要看到”我们用的是国密”这句话,这在司法存证的场景里是一项有分量的举证——《密码法》第二十七条明文规定”使用密码保护网络与信息安全”,而国密算法天然满足这一条的法律解释。
常见误区
误区一:SM3 就是 SHA-256 改了几个常数
这话我听过不止一次,而且说的人往往带着一种”国密就是抄的”的不屑。但实际上,SM3 和 SHA-256 虽然结构框架相似(都是 Merkle-Damgård + 64 轮),但细节上的差异不小——消息扩展从 64 字变 132 字、布尔函数从两个变四个(FF 和 GG 各分两段)、新增了 P0 和 P1 置换。说有参考借鉴是可以的,说”改了几个常数”就太过了。两者的关系更像是同一个物种下的两个亚种,而不是复制粘贴。
误区二:做国内项目必须要用 SM3
不是所有场景都强制。目前明确要求使用国密算法的场景主要集中在三个领域:金融支付系统(央行发文)、电子政务外网(等保+密评)、以及涉密信息系统(《密码法》明确规定)。你做一个民营企业内部的 OA 系统或者一个面向海外用户的产品,完全可以继续用 SHA-256,监管上不存在障碍。
误区三:SM3 比 SHA-256 更安全
严格来说没有定论。SM3 在设计上更保守——消息扩展多了近一倍的字、布尔函数更复杂——这带来了更大的安全冗余,但也意味着更多的计算开销和更大的攻击面(逻辑越复杂,实现出错的可能性越大)。SHA-256 经过了二十多年的全球学术检验,SM3 的国际密码分析相对少一些,虽然目前没有发现有效的攻击路径,但”没有被充分检验”和”经过了充分检验但没攻破”是两种不同的安全状态。
SM3 vs SHA-256 vs SHA-3
| SM3 | SHA-256 | SHA-3 (Keccak) | |
|---|---|---|---|
| 输出长度 | 256 位 | 256 位 | 224/256/384/512 位 |
| 内部结构 | Merkle-Damgård | Merkle-Damgård | 海绵结构(Sponge) |
| 消息扩展 | 132 字 | 64 字 | 无(海绵吸收) |
| 轮数 | 64 | 64 | 24(SHA3-256) |
| 抗长度扩展 | 弱 | 弱 | 强 |
| 标准化 | GB/T 32905、ISO/IEC 10118-3 | FIPS PUB 180-4 | FIPS PUB 202 |
| 主要市场 | 中国(合规驱动) | 全球(事实标准) | 全球(备用/渐进迁移) |
SHA-3 的海绵结构是天生的”长度扩展攻击免疫体质”——不需要 HMAC 那一套外层内层的复杂构造。SM3 和 SHA-256 都继承了 Merkle-Damgård 的这个弱点,所以基于 SM3 的 HMAC 也是必须做的。好消息是,SM3 在国内项目中的使用场景几乎都标准地配了 HMAC-SM3,堵上了这个口子。
常见问题
Q: SM3 和 SHA-256 的哈希值能互操作吗?
不能。同一个输入,SM3 和 SHA-256 算出来的哈希值完全不同。你在工具里分别用 SM3 和 SHA-256 对 “hello” 做哈希,看到的会是两串毫无关联的十六进制字符。如果你的系统从 SHA-256 迁移到 SM3,所有存储的哈希值都需要重新计算。
Q: 《密码法》对使用 SM3 有什么具体要求?
《密码法》本身没有提到 SM3 这个具体的算法名,它只界定了”核心密码、普通密码、商用密码”三个层次,并对商用密码产品的销售和进出口做了管制。但《密码法》配套的行政规章和行业标准中,SM3 作为商用密码算法被反复引用。对开发者的实际影响是:如果你的系统需要通过密评(商用密码应用安全性评估),你使用的哈希算法必须在国家密码管理局公布的商用密码算法目录中——SM3 在目录里,SHA-256 不在。
Q: 前端(浏览器)能做 SM3 哈希吗?
原生 Web Crypto API 不支持 SM3,它只支持 SHA-1、SHA-256、SHA-384、SHA-512。在浏览器里做 SM3 需要用纯 JavaScript 实现的库,比如 sm-crypto 或 gm-crypto。不过要注意,纯 JS 实现的哈希性能不高——大文件哈希还是建议放在后端做。你用的这个工具箱就是在前端用 JavaScript 实现 SM3 的,处理几 KB 的小数据没问题,几百 MB 的别试,浏览器会卡到你怀疑人生。
Q: SM3 会被用于 SSL/TLS 证书吗?
技术上可以,国密证书用的就是 SM2+SM3 组合。但全球主流浏览器(Chrome、Firefox、Safari)目前都不信任国密根证书,也不支持 SM2/SM3/SM4 密码套件。在国内,专用的国密浏览器(如 360 安全浏览器的国密模式、奇安信可信浏览器)能够验证国密证书链,但面向公众的互联网服务目前还是 RSA/ECDSA + SHA-256 的天下。国密证书目前主要用于政务外网、金融专网等私有的 PKI 环境。
Q: 如果我做的是中美双边的产品,哈希算法怎么选?
两条腿走路。国内用户和国内监管接口用 SM3,国际用户和国际接口用 SHA-256。把哈希算法的选择做成配置项而不是硬编码,这样可以根据部署环境灵活切换。不过这增加了维护负担,需要仔细评估——不是所有项目都值得这种双栈投入。