国密算法概述:SM2 / SM3 / SM4 / SM9

搞国密套件,首先得把四个核心算法摸透。说实话,我刚接触国密那会儿也犯过迷糊——总觉得跟国际算法对着来就能跑通,结果第一次调 SM2 签名就把私钥格式搞错了,debug 了一整天。

今天咱们把 SM2、SM3、SM4、SM9 挨个捋一遍,重点说清楚它们各自干嘛用、怎么配合,顺便聊聊我在项目里踩过的坑。

SM2:非对称密码算法——国标版的 ECC

SM2 基于椭圆曲线,支持公钥加密、数字签名和密钥交换。它的曲线参数是国家标准的,跟国际上的 P-256 不一样,所以直接复用 OpenSSL 的 ECC 代码是跑不起来的。

我习惯把 SM2 当作「国密三件套」里的核心:TLS 握手阶段用它做证书签名验证,或者做 ECDHE 密钥交换。举个例子,在 openssl 里用 SM2 签名,需要先加载 SM2 私钥:

EVP_PKEY *pkey = EVP_PKEY_new();
SM2_KEY *sm2_key = SM2_KEY_new();
// 生成 SM2 密钥对
SM2_generate_key(sm2_key);
EVP_PKEY_assign_SM2(pkey, sm2_key);

我在项目中遇到过一个问题:SM2 签名结果是一个 r||s 拼接的 64 字节,而国际 ECDSA 通常用 DER 编码。对接网关时对方要求原样发送,结果长度多了一截,连调了一下午才定位到。嗯,这块要注意,最好在接口文档里写死格式。

SM3:密码杂凑算法——256 位,跟 SHA-256 平起平坐

SM3 输出 256 位杂凑值,算法结构跟 SHA-256 很像,但具体的压缩函数和消息扩展不同。你想想看,既然 SHA-256 已经够用,为什么还要用 SM3?说白了,合规需求。很多等保三级以上的系统硬性要求使用国密算法,SM3 就是替代 SHA-256 的那个。

我个人习惯在日志审计场景里用 SM3 做完整性校验。但要注意,SM3 在 OpenSSL 1.1.1 里需要手动配置 openssl.cnf 才能启用,我之前图省事直接调 EVP_sha256(),结果被测评机构打了回票。避坑指南:做国密适配时,务必拿 SM3 替换所有哈希调用,包括证书签名哈希、消息摘要、HMAC。

SM4:对称分组密码算法——128 位分组,128 位密钥

SM4 是对称加密,分组大小和密钥长度都是 128 位,算法流程跟 AES 类似,但 S 盒和密钥扩展完全不同。它的加解密速度相当快,我测过纯软件实现,大概能跑到 2~3 Gbps,足够应付大多数 TLS 流量。

表格对比一下 SM4 和 AES:

特性SM4AES
分组长度128 位128 位
密钥长度128 位128/192/256 位
轮数32 轮10/12/14 轮
密码模式ECB/CBC/CTR/GCM(需扩展)支持所有 NIST 模式
国家支持国标 GB/T 32907国际通用

我记得有一次,客户要求用 SM4-GCM 模式替代 AES-GCM,但 OpenSSL 默认不提供 SM4-GCM,需要自己集成。我当时的方案是用 EVP_CIPHER_fetch 加载自定义 provider,或者直接用 GmSSL。

SM9:标识密码算法——没有证书也能验

SM9 是基于标识的密码(IBC),好处是不需要数字证书,用户的标识(比如邮箱、手机号)直接作为公钥。这在 IoT 或者密钥分发场景下特别方便,省去了 PKI 的搭建成本。

但 SM9 的核心——密钥生成中心(KGC)——必须严格保护主密钥。我在一个政务项目中部署 SM9,客户觉得「不需要证书就省事了」,结果 KGC 主密钥泄露,整个系统的 SM9 签名全部作废。嗯,这里要敲黑板:SM9 的安全性完全依赖 KGC,主密钥必须用硬件加密机加物理隔离。

SM9 签名算法使用了双线性对,计算量大,性能大概是 SM2 的 1/3 左右。如果 TLS 握手用 SM9 做身份验证,建议只在低频连接场景使用。

算法定位总结:SM2 做公钥加密/签名,SM3 做哈希,SM4 做对称加密,SM9 做标识加密。TLS 国密套件通常组合为 SM2 签名+SM4 加密+SM3 摘要。

国密算法在 TLS 中的角色

下面这张图展示了典型的国密 TLS 握手流程中,四个算法各司其职:

国密TLS握手算法角色 TLS 客户端 SM2 签名 SM3 摘要 SM4 加密 SM2 验签 SM3 校验 SM4 解密 TLS 服务器 客户端用 SM2 签名 + SM3 摘要 + SM4 加密 → 服务器用 SM2 验签 + SM3 校验 + SM4 解密

从图上可以清晰看到:客户端首先用 SM2 签名自己的证书,SM3 对握手消息做摘要,最后用 SM4 加密应用数据。服务器端与之对应。注意 SM9 在这里没有出现——SM9 更多用于密钥交换或身份认证的替代方案,不在这张基本握手图里。

算法对比与选型建议

做国密替换时,怎么选算法?我直接给结论:

  • 签名/验签:优先 SM2,成熟度高,性能好。SM9 只在无证书场景用。
  • 密钥交换:SM2 的 ECDHE,或者使用 SM9 的密钥封装(KEM)。我建议前期先上 SM2 ECDHE,兼容性好。
  • 对称加密:SM4-CBC 或 SM4-GCM。GCM 记得确认供应商是否支持。
  • 哈希:SM3 全面替代 SHA-256。
国密算法选型权衡
算法类型密钥/输出长度性能(软件)适用场景
SM2公钥256 位曲线签名 ~2000次/秒数字签名、密钥交换、证书
SM3哈希256 位输出~2.5 Gbps完整性校验、HMAC、证书签名
SM4对称128 位密钥~3 Gbps数据加密、TLS 记录层
SM9标识密码256 位曲线签名 ~600次/秒无证书身份认证、IoT
避坑提醒:我曾遇到过一个系统,SM4 的 ECB 模式被测评机构判定为「安全强度不足」,因为国标里并未推荐 ECB。建议至少用 CBC 或 CTR 模式,最好用 GCM。
重要警告:不要自行实现国密算法!哪怕只是改一个 S 盒,也可能引入安全漏洞。我见过一个团队手写 SM3,结果 padding 逻辑写错导致哈希完全错误。请使用经过商密认证的 SDK,比如 GmSSL、铜锁、或 OpenSSL 国密分支。

好了,四个算法的基础就聊到这儿。弄懂它们各自的定位和坑位,后面咱们才能顺畅地拼出完整的国密 TLS 套件。