国密算法实战指南:SM2、SM3、SM4 怎么选、怎么对接、怎么排查
国密不是可选项,是硬性合规
做政务、金融、国企项目的开发者迟早撞上同一句话:「系统需支持国密算法」。这不是技术偏好——等保 2.0 和商用密码评估(密评)把 SM 系列算法写进了验收标准,SHA-256 和 RSA 在这些场景不能替代 SM3 和 SM2。第一次对接时最容易犯的认知错误是拿国际算法类比硬套:「SM3 就是中国的 SHA-256 吧?」——设计上确实同构,但两端必须跑同一套算法才能对上:你用 SHA-256 算的摘要发给要求 SM3 的对端,永远校验失败。
三个算法各管一摊,选型一句话:
| 需求 | 算法 | 国际对应 |
|---|---|---|
| 数据加密(对称) | SM4 | AES |
| 哈希/摘要 | SM3 | SHA-256 |
| 签名/非对称加密 | SM2 | RSA/ECC |
配套的浏览器本地工具:SM4 加解密、SM3 哈希、SM2 加解密签名——联调时快速造测试数据、验证中间结果,全程不上传。
SM4:对接失败 90% 死在这三处
SM4 是 128 位分组密码,对接时「我加密的对端解不开」的排查顺序(按命中率排):
1. 密钥格式。SM4 密钥固定 16 字节,联调最常见的错位是:你用 UTF-8 字符串直接当密钥("1234567890abcdef" 被当 16 个字符),对端按 32 位 hex 解析成 16 字节——同一个字符串,两种解释,密文必然不同。确认双方约定:hex 还是 utf8 直填,长度按字节算不是按字符算。
2. 工作模式与 IV。ECB 无 IV、CBC 必须带 16 字节 IV 且两端一致。模式错配的典型症状是:解密不报错但明文是乱码(前 16 字节对、后面全错——IV 错位的高频指纹)。真实业务应避开 ECB(相同明文块产出相同密文块,泄漏结构特征),测试连通性时才用它。
3. 输出编码。密文用 hex 还是 base64 传输,三方(你、对端、文档)必须写死同一个约定。这个排最后不是因为少见,是因为一旦约定了就不容易错——前提是真的约定了。
一个健康的调试习惯:联调前双方先用固定明文 + 固定密钥各出一份期望密文,肉眼比对不一致再逐项对上面三处,比对着黑盒猜快十倍。
SM3:哈希的「对不上」只有一种原因
SM3 输出固定 256 位(64 个 hex 字符)。它没有密钥、没有模式、没有 IV——所以两端算出来不一样时,原因只有一个:输入不一样。而输入不一样的头号惯犯是不可见字符:
- 文档里复制出来的字符串带尾随换行或空格
- 一端做了 trim 另一端没做
- JSON 序列化的字段顺序或空格差异(对 JSON 做 SM3 摘要前必须约定规范化序列化)
- 编码差异:UTF-8 vs GBK 对中文输入产出完全不同的哈希
排查法:把双方的原始输入按字节打出来(hex dump)对比,而不是对比字符串看着像。哈希算法本身没有「兼容性问题」——它是确定性的,输入相同输出必然相同,所以 SM3 对不上 = 输入不同,没有第二种可能。
SM2:三件事别搞混
SM2 是椭圆曲线体系,一次对接里通常出现三种操作,别混:
- 加密/解密:公钥加密、私钥解密(给别人传敏感数据时用)
- 签名/验签:私钥签名、公钥验签(证明「这是我发的、没被改过」)
- 密钥协商:双方推导共享密钥(通信建连时用,工具里一般不涉及)
高频坑:验签失败的真正原因往往不在签名算法,而在被签名的原文——两端对「签名内容」的理解不一致(一端签的是原始报文,另一端验的是去掉换行的版本,或加了字段名前缀的版本)。排查顺序:先逐字节比对双方的待签原文,再看密钥对是否匹配。
密钥安全边界必须说清:测试密钥随便造(SM2 工具本地生成一对,加密→解密、签名→验签闭环验证流程),生产私钥永远不进任何网页、脚本参数或聊天工具——私钥管理属于密管系统/硬件加密机的职责,不属于联调工具。
SM2 密文顺序:C1C3C2 与 C1C2C3
加密联调里第二高发的坑是密文分段顺序。SM2 密文由三段拼接:
| 段 | 含义 | 长度(hex 字符,未压缩点) |
|---|---|---|
| C1 | 临时椭圆曲线点(x‖y,库侧常不带 04) | 128 |
| C3 | 杂凑校验值 | 64 |
| C2 | 明文异或后的密文 | 随明文变长 |
GB/T 32918.4-2016 推荐顺序是 C1‖C3‖C2;不少早期 SDK 与文档示例仍用 C1‖C2‖C3。两端顺序不一致时,解密几乎必然失败——症状像「密钥错了」,根因却是字段拼接。站内 SM2 工具 默认走 C1C3C2,并可一键切到 C1C2C3,用来当「已知正确的对端」做对照。
另外两处格式噪声也值得写进联调约定:
- 公钥:非压缩是
04+ 128 位坐标(共 130 hex);有的对端只给 128 位裸坐标——补上04即可。压缩公钥为02/03+ 64 位 x。 - 密文前缀:部分库会给整段密文再套一层
04;若对端密文以04开头且长度明显偏长,先剥掉再解。本站工具会自动处理这两种常见形态。
签名侧还要单独核对:ASN.1 DER 包装的签名 与 裸 r‖s(128 hex)不可混用;SM3 杂凑时的 userId(默认常为 1234567812345678)两端必须一致。
SM4 编码与 IV:把约定写成接口契约
SM4 排查表里的「输出编码」值得再展开一层。本站工具默认密文为 hex,也可切 Base64——和 AES 联调时一样,肉眼能分,但不能靠猜。CBC 下 IV 是 16 字节(32 hex),且不可省略;缺 IV 或 IV 与加密端不一致时,常见指纹是「解密不报错但明文乱码,且首块还像可读」。密钥同样只认 16 字节:带 0x、中间空格的 hex 串应先规范化再喂给库——否则会和「UTF-8 直填 16 个字符当密钥」再次撞车。
第一次联调仍建议:固定明文 + 固定密钥(+ 固定 IV)双方各出一份期望密文,先对齐编码与模式,再接入真实业务字段。
一张联调自查表
| 症状 | 先查 |
|---|---|
| SM4 密文对端解不开 | 密钥解释(hex/utf8)→ 模式与 IV → 输出编码(hex/Base64) |
| SM4 解密出乱码但首块正常 | IV 错位(CBC 的经典指纹) |
| SM4 CBC 直接报「需要 IV」 | 加密/解密端是否都传了 16 字节 IV |
| SM3 两端哈希不一致 | 不可见字符 / trim / 编码(输入必然不同) |
| SM2 解密失败、密钥看着对 | 密文顺序 C1C3C2 vs C1C2C3 → 多余 04 前缀 → 公钥格式 |
| SM2 验签失败 | 待签原文逐字节比对 → DER vs r‖s → userId → 密钥对匹配 |
| 全部对不上 | 先用固定明文+固定密钥交换期望密文基线 |
与国际算法并存的现实
多数系统在过渡期需要同时支持两套:配置里留算法开关(algorithm: SM4 | AES),按对接方的要求逐通道切换。工具层面两端都备齐:国密三件套之外,站内同样有 AES 加解密、RSA 工具和 SHA-256——同一份数据两套算法各算一遍比对,是过渡期排查的日常。
算法选型与合规语境的总览见姊妹篇《国密算法入门指南》;标准号对照(GM/T / GB/T / ISO)见《国密标准号速查》。
排查注记
SM4 三处排查按命中率排,且特意解释输出编码排最后「不是因为少见,是因为一旦约定了就不容易错」——排序依据是出错概率,不是重要性。SM3 一节把结论压到一句「对不上 = 输入不同,没有第二种可能」,因为哈希是确定性的、没有密钥模式 IV,头号惯犯是不可见字符,所以排查法是 hex dump 按字节对比、而不是对比字符串看着像。SM2 验签失败同样先怀疑原文而不是算法——两端对「签名内容」的理解不一致(换行、字段前缀)才是高频根因。
本文工具均来自 ToolVault——开发者工具均在浏览器本地运行,密钥与数据不出设备。
相关工具
相关文章
后量子迁移自查清单:从算法盘点到 hybrid TLS,2026 年该做完的 12 件事
后量子密码(PQC)迁移的实操自查框架:三张监管时刻表为什么让 2026 成为起点、算法盘点(CBOM)怎么做、按 HNDL 暴露度排优先级、X25519+ML-KEM 混合 TLS 怎么开,以及 crypto-agility 的工程落地。附 12 项可勾选 checklist。
Passkeys 完全指南:为什么服务器再也存不了你的密码副本
Passkey(WebAuthn/FIDO2)加深:注册与断言仪式、平台认证器与漫游密钥、同步通行密钥取舍、与密码/TOTP/JWT 的关系,以及 origin 绑定如何结构性抗钓鱼。服务器只存公钥;站内无独立 Passkey 工具页的说明。
ML-KEM 入门:Kyber 是怎么进到你的 TLS 握手里的
后量子密钥封装 ML-KEM(FIPS 203,前身 Kyber)的工程向解读:Kyber 到标准名的变迁、封装/解封装语义与 IND-CCA、三档参数尺寸、X25519+ML-KEM 与 TLS 1.3 HKDF 密钥调度的混合方式、ClientHello 膨胀中间盒坑、OpenSSL 3.5 / nginx 开法,以及浏览器侧实现边界。