国密算法概述:SM2、SM3、SM4 简介
做TLS握手集成国密算法时,很多朋友第一反应是「把RSA换成SM2不就完了?」。嗯,没那么简单。国密不是单个算法的替换,而是一整套密码体系。今天我们先捋清楚这三个核心算法各管哪块、怎么配合,后面讲握手流程才不容易绕晕。
SM2:椭圆曲线到底好在哪?
SM2 基于椭圆曲线密码学(ECC),我当年第一次看 ECC 的数学推导也头疼。但实际用起来你不需要懂所有证明,只需要记住几个关键点。
SM2 的曲线参数是国标规定的,固定一套。与 RSA 相比,同等安全强度下 SM2 的密钥长度短得多。举个例子:SM2 用 256 位密钥就能达到 RSA 3072 位的安全等级。这意味着什么?握手时的证书更小,计算量更少,移动端尤其友好。
| 特性 | SM2(ECC) | RSA |
|---|---|---|
| 密钥长度(同等安全) | 256 位 | 3072 位 |
| 签名速度 | 快(约 2~5ms) | 较慢(约 10~20ms) |
| 验签速度 | 较慢(约 3~8ms) | 快(约 0.5~1ms) |
| 密钥生成 | 极快 | 慢(需要大素数筛选) |
SM3:不是普通的哈希
哈希算法大家熟,但 SM3 和 SHA-256 长得像,又不完全一样。SM3 输出 256 位摘要,算法结构上更接近 SHA-256 的改良版。你以为随便换掉就行?不行。国密标准要求 TLS 握手里的哈希必须用 SM3,不能偷懒用 SHA-256 替代。
我个人习惯把 SM3 看成「加了一些防护的 SHA-256」。比如它的消息扩展轮数更多,抗碰撞能力理论上更强。实际项目中我没遇到过 SM3 碰撞问题,但合规性是大前提——你要是过国密局检测,哈希必须用 SM3。
SM4:轻量对称加密
SM4 是分组密码,分组长度 128 位,密钥长度也是 128 位。结构上是 Feistel 网络,轮数 32 轮。说实话,它和 AES 的套路很像,但轮函数细节不同。性能上,SM4 软件实现略慢于 AES-NI 硬件加速下的 AES,但在普通 ARM 芯片上差距不明显。
TLS 1.3 国密版中,记录层加密用的是 SM4-GCM 模式。嗯,这里有个要点:SM4-GCM 需要单独实现,有些开源的 SM4 只做了 ECB/CBC 模式。我之前接手过一个项目,只用 SM4-CBC 做加密,结果握手协商时套件不匹配,折腾了我两天才找到问题。
| 模式 | 用途 | 是否需要 IV | 认证加密 |
|---|---|---|---|
| SM4-ECB | 基本不推荐 | 否 | 否 |
| SM4-CBC | 兼容旧系统 | 是(随机) | 否 |
| SM4-GCM | TLS 记录层标准 | 是(12 字节) | 是(AEAD) |
| SM4-CCM | 物联网场景 | 是 | 是(AEAD) |
三个算法怎么配合?
举个例子:客户端发起 TLS 握手,用 SM2 证书做身份认证,用 SM2 密钥交换协议(TLS 中通常是 SM2 签名的 ECDHE)协商出临时密钥,然后用 SM3 做握手消息的哈希校验,最后用 SM4-GCM 加密传输数据。
你看,一个环节都不能少。下面这张图概括了三者在握手中的位置:
算法参数速查
最后给个小表,方便开发时核对参数。你想想看,如果 SM2 签名长度、SM3 摘要长度搞混了,会导致什么?协议解析错位。我就犯过这种低级错误,debug 了一下午。
| 算法 | 密钥/输出长度 | 签名/密文长度 | 国密标准号 |
|---|---|---|---|
| SM2 | 私钥 256 位,公钥 65 字节(未压缩) | 签名 64 字节(r∥s) | GB/T 32918 |
| SM3 | 输出 256 位(32 字节) | — | GB/T 32905 |
| SM4 | 密钥 128 位,分组 128 位 | 与明文等长(GCM 加 Tag 16 字节) | GB/T 32907 |
好,三大算法的基础概念就这些。说实话,搞懂它们各自的定位和参数,后面看 TLS 握手流程就会轻松很多。你只要记住:SM2 管认证和密钥协商、SM3 管完整性、SM4 管加密。三个缺一个都组成不了完整的国密握手。