2. SM2/SM3 算法简介:国密体系、应用场景与国际对比

说实话,我刚开始接触国密算法那会儿,第一反应是:又一套新标准?后来参与了一个政务系统的密码改造项目,才真正意识到国密不是“折腾”你,而是信息安全自主可控的基石。

这节咱们聊聊国密算法体系的整体轮廓、SM2 和 SM3 到底用在哪儿,以及它们跟 RSA、ECC、SHA-256 这些国际算法的差异。我会结合自己踩过的坑来讲,希望能帮你少走弯路。

2.1 国密算法体系一览

国密算法是国家密码管理局发布的一套商用密码标准。目前最核心的几个算法分别是:

  • SM1:对称加密算法,硬件实现,不公开算法细节,主要用于芯片级加密。
  • SM2:椭圆曲线公钥密码算法,包括加密、签名、密钥交换。
  • SM3:密码杂凑算法,输出 256 位摘要。
  • SM4:对称分组密码算法,密钥长度 128 位,类似 AES。
  • SM9:基于标识的密码算法,不需要证书。

咱们这门课重点讲 SM2 和 SM3,因为它们是公钥密码和哈希层面的关键组件。我个人的习惯是把算法分类画成一张图,方便对照。

国密算法体系核心结构 GM/T 国密标准 SM1(对称) SM2(公钥) SM3(杂凑) SM4(对称) 加密 签名 密钥交换 256位摘要 注:SM9(标识密码)不在本次课程重点范围,未绘制 本课程聚焦 SM2 公钥密码 与 SM3 杂凑算法
小提示: 实际项目中 SM2 经常与 SM3 配合使用——比如签名时先用 SM3 计算哈希,再用 SM2 私钥签名。我在做电子签章 SDK 时,就踩过哈希顺序不对的坑。

2.2 SM2 算法:椭圆曲线公钥密码的中国方案

SM2 基于椭圆曲线密码学(ECC),跟我之前用过几年的 ECDSA、ECDH 是同一套数学基础。但 SM2 不是简单复制,它有一套完整的国标:GM/T 0003-2012。里面定义了签名、加密、密钥交换三个功能。

跟 ECC 相比,SM2 核心区别在于:

  • 曲线参数不同:SM2 使用一条 256 位的素数域椭圆曲线,参数由国密局指定。我个人觉得这条曲线的设计比较保守,安全性有保证。
  • 签名算法细节不同:SM2 签名先计算 e = HASH(M),然后生成随机数 k,计算椭圆曲线点,最后得到 (r, s)。跟 ECDSA 最大的区别是:SM2 在签名中加入了用户 ID 和曲线参数,能抵抗某种类型的攻击。
  • 加密方式不同:SM2 加密采用“KDF + 异或”的混合加密,不是直接对消息做椭圆曲线运算。

我记得有一次项目中,客户要求同时支持 SM2 和 ECDSA 签名验证。我直接用同一份哈希值去验证两个算法的签名,结果就是死活不通过。后来才发现是两个算法对消息的预处理不同——比如 SM2 需要拼接 Z 值(用户标识和曲线参数散列)。

注意: 不要想当然地把 SM2 签名和 ECDSA 混用。它们的签名格式、哈希预处理都不一样。我曾经因为偷懒共用验证代码,被测试组追着修了一个礼拜。

2.3 SM3 算法:密码杂凑的国内标准

SM3 是一个输出 256 位摘要的哈希算法,标准号 GM/T 0004-2012。它的结构类似 SHA-256,也是 Merkle-Damgård 结构,消息分块处理,每块 512 位,迭代压缩。

但 SM3 的压缩函数内部设计了更多“混淆”操作,比如 16 轮循环左移、置换函数、异或扩散等。从安全性上看,SM3 比 SHA-256 在抗碰撞性上要强一点——当然这只是理论分析,实际中 SHA-256 也足够安全。

性能对比印象: 我在 X86 服务器上测过 SM3 vs SHA-256,纯软件实现时 SM3 大约慢 10%~20%(取决于 CPU 的 SIMD 优化)。如果用了国密指令集(比如飞腾 CPU),差距几乎可以忽略。

SM3 的应用场景非常广:数字签名、消息认证码、密钥派生、随机数生成等等。我参与过一个电子病历项目,用 SM3 做文件的完整性校验,配合 SM2 签名,既防篡改又防抵赖。

2.4 应用场景:哪里该用 SM2 和 SM3?

下面这张表是我在项目里总结的常见场景,你直接用就对了。

场景 使用算法 我的实战经验
电子合同签名 SM2 签名 + SM3 摘要 记得先计算合同原文的 SM3 值,再对哈希值签名。不要直接签原文。
安全通道握手 SM2 密钥交换 + SM3 密钥派生 我在实现 TLS 国密套件时,就是用的 ECDHE_SM2_SM3。
文件完整性校验 SM3 杂凑 与 SHA-256 用法完全相同,只是把算法名从 sha256sum 改成 sm3sum。
身份认证令牌 SM2 签名 后端用 SM2 私钥对用户 ID + 时间戳签名,前端用公钥验证。
密钥封装与加密传输 SM2 加密 实际项目中我很少直接用 SM2 加密大文件,通常用它加密对称密钥(SM4 密钥)。

2.5 与国际算法对比:SM2 vs RSA/ECC,SM3 vs SHA-256

很多人问我:国密到底比国际算法强在哪?弱在哪?我分别说说。

SM2 vs RSA

  • 密钥长度:RSA 需要 2048 位才能保证安全,SM2 只要 256 位。SM2 的签名、加密、密钥交换都更短。
  • 性能:SM2 签名和密钥交换比 RSA 快很多(尤其是私钥操作),但 SM2 验签略慢于 RSA 验签(因为椭圆曲线点乘)。
  • 兼容性:RSA 在旧系统里遍地都是,SM2 需要额外适配。我遇到过一个银行前置机只支持 RSA,改造时肝了一周移植 SM2。

SM2 vs ECC(国际椭圆曲线,如 P-256)

  • 数学基础相同,都是椭圆曲线离散对数问题。
  • 曲线参数不同:SM2 使用国标定义的曲线,P-256 由 NIST 定义。两者安全性等价,没有谁明显优于谁。
  • 协议细节不同:签名的消息预处理、编码方式有差异,不能互操作。

SM3 vs SHA-256

  • 结构高度相似:都是 512 位分组,256 位输出。
  • 安全强度:SM3 的轮函数更复杂,理论安全性略高。实际攻破两者都不可行。
  • 性能:纯软件实现 SM3 略慢,但在 ARM 和飞腾上已经做了指令优化,差距不大。
一句话总结: 如果你做的是纯内网系统或者政务项目,用国密完全没问题,而且能通过合规检查。如果是全球化产品,还是优先考虑国际算法,避免兼容性麻烦。我自己在海外云平台上部署过 SM2,结果调了一个月的 OpenSSL 补丁。

2.6 避坑指南:从我的血泪史里总结

  1. 不要混用 hash 预处理:SM2 签名时对消息的哈希计算,需要先拼接 Z 值(用户标识 + 曲线参数哈希)。我刚开始没拼接,导致签名验证失败,debug 了一整天。
  2. 密钥格式别搞错:SM2 公钥长度 64 字节(未压缩),私钥 32 字节。有些库用 PEM 格式,有些用 DER,转换时注意标识符 OID 是 1.2.156.10197.1.301。
  3. SM3 不要当随机数用:哈希不是伪随机函数,做密钥派生时一定要用专门的 KDF(SM2 里定义了一种)。我之前图省事直接用 SM3 做 KDF,被安全审计打了回来。
  4. 测试向量要验证:国标文档 GM/T 0003-2012 附录有详细的测试向量(明文、私钥、签名、加密结果)。建议你实现完成后先用这些向量跑一遍,确保没错。
一个小习惯: 我在代码里会用一个宏开关 #define SM2_DEBUG 来输出中间数据(比如随机数 k、椭圆曲线点坐标),调试完再关掉。超级有效。

好了,这一节的内容就到这儿。你先把国密体系的脉络理清,SM2 和 SM3 的核心差异记住,后面我们就要深入代码了。