SM2 椭圆曲线公钥密码算法
概述
SM2 是中国国家密码管理局于 2006 年发布的椭圆曲线公钥密码算法,2012 年作为密码行业标准公开发布(GM/T 0003 系列),2016 年升级为国家标准(GB/T 32918 系列)。该算法设计由中国科学院数据安全与通信保密研究中心主导,主要设计者为吕述望团队。
SM2 的定位是作为 RSA 和 ECDSA 的国产替代方案,具备数字签名、密钥交换和公钥加密三大核心功能。在国际标准化方面,SM2 已通过 ISO/IEC 14888-3:2018/Amd 1 和 ISO/IEC 11770-3:2018 被采纳为国际标准的一部分。
算法基本参数
| 参数 | SM2 | RSA-2048 | ECDSA (P-256) | 说明 |
|---|---|---|---|---|
| 标准编号 | GB/T 32918-2016 | PKCS#1 v2.2 | FIPS 186-4 | SM2 为国标 |
| 密钥长度 | 256 bit | 2048 bit | 256 bit | SM2 密钥极短 |
| 安全强度 | ~128 bit | ~112 bit | ~128 bit | SM2 与 P-256 相当 |
| 签名长度 | ~64 bit (r,s) | 2048 bit | ~512 bit | SM2 签名极短 |
| 功能 | 签名+加密+密钥交换 | 签名+加密 | 仅签名 | SM2 功能最全 |
| 曲线类型 | sm2p256v1 | — | secp256r1 | 不同曲线参数 |
关键对比:SM2 的 256-bit 密钥提供与 RSA 2048-bit 相当的安全强度,但密钥长度仅为后者的 1/8,签名长度仅为 1/32。这使得 SM2 在存储、传输和计算效率上具有显著优势。
椭圆曲线参数
SM2 定义了一条 256-bit 素数域上的椭圆曲线 $E: y^2 = x^3 + ax + b$,其中参数如下(十六进制表示):
| 参数 | 值 |
|---|---|
| 素数 $p$ | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF |
| 系数 $a$ | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC |
系数 $b | 28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93 |
| 基点 $G$ 的 x 坐标 | 32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7 |
| 基点 $G$ 的 y 坐标 | BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0 |
| 子群阶 $n$ | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123 |
⚠️ 重要提示:SM2 曲线(sm2p256v1)与 NIST P-256(secp256r1)使用完全不同的参数。$a, b, G, n$ 均不同,因此两者生成的密钥互不兼容。Python cryptography库的ec.SECP256R1()不支持 SM2,需要使用gmssl` 库。
密钥生成
SM2 密钥生成过程:
- 随机选择私钥 $d_A \in [1, n-1]$
- 计算公钥 $P_A = [d_A]G$(椭圆曲线标量乘法)
其中 $n$ 是基点 $G$ 的阶(一个 256-bit 素数),$G$ 是椭圆曲线上的基点。
数字签名算法
SM2 数字签名基于 ECDSA 的变体,但增加了用户 ID 绑定和 SM3 哈希,提供更强的安全保证。
签名过程
输入:私钥 $d_A$、用户 ID $ID_A$、消息 $M$
- 计算用户哈希:$\bar{Z}_A = H_{len(ID_A)}(ID_A \| a \| b \| x_G \| y_G \| x_A \| y_A)$
- 计算消息哈希:$e = H_v(\bar{Z}_A \| M)$,其中 $H_v$ 是 SM3(输出 256 bit)
- 随机选择 $k \in [1, n-1]$(必须使用 CSPRNG)
- 计算椭圆曲线点:$(x_1, y_1) = [k]G$
- 计算签名分量:
- 计算签名分量:
- 输出签名 $(r, s)$
验签过程
输入:公钥 $P_A$、用户 ID $ID_A$、消息 $M$、签名 $(r, s)$
- 验证 $r, s \in [1, n-1]$
- 计算 $\bar{Z}_A$(同签名过程)
- 计算 $e = SM3(\bar{Z}_A \| M)$
- 计算:$t = (r + s) \bmod n$,若 $t = 0$ 则验签失败
- 计算椭圆曲线点:$(x_1, y_1) = [s]G + [t]P_A$
- 计算:$R = (e + x_1) \bmod n$
- 验证通过当且仅当 $R = r$
密钥交换协议
SM2 密钥交换协议(GM/T 0003.3-2012 / GB/T 32918.3-2016)允许两方在不安全信道上协商共享密钥,同时提供相互身份认证。
协议流程
设 Alice 和 Bob 分别持有密钥对 $(d_A, P_A)$ 和 $(d_B, P_B)$:
Alice Bob
| |
| 1. 选择随机数 r_A ∈ [1, n-1] |
| 2. 计算 R_A = [r_A]G = (x_1, y_1) |
| |
|-------------- R_A ----------------------->|
| |
| 3. 选择随机数 r_B ∈ [1, n-1]|
| 4. 计算 R_B = [r_B]G |
| 5. 计算 U_B = [h·t_B] |
| (P_A + [x̄_A]·R_A) |
| |
|<------------- R_B, U_B ------------------|
| |
| 6. 计算 U_A = [h·t_A] |
| (P_B + [x̄_B]·R_B) |
| 7. 计算共享密钥 K = KDF(U_A, V_A) |
| |其中:
- $h$ 为辅因子(对于 sm2p256v1,$h = 1$)
- $t_A = (d_A + \bar{x}_A \cdot r_A) \bmod n$
- $\bar{x}_A = 2^{w} + (x_A \mathrel{\&} (2^{w} - 1))$,$w = \lceil \lceil \log_2 n \rceil / 2 \rceil - 1$
- $KDF$ 为密钥派生函数(使用 SM3)
安全特性
SM2 密钥交换相比标准 ECDH 具有以下增强:
- 相互认证:双方都参与了密钥的计算,防止中间人攻击
- 密钥确认:通过验证 $U_A = U_B$ 确保双方计算出相同的共享密钥
- 前向安全性:即使长期私钥泄露,过去的会话密钥仍然安全
公钥加密算法
SM2 公钥加密(GM/T 0003.4-2012 / GB/T 32918.4-2016)基于椭圆曲线的混合加密方案,结合了对称加密的高效性和公钥加密的密钥管理优势。
加密过程
输入:公钥 $P_B$、明文 $M$(长度为 $klen$ 字节)
- 随机选择 $k \in [1, n-1]$
- 计算:$C_1 = [k]G = (x_1, y_1)$
- 计算椭圆曲线点:$[h]P_B = (x_2, y_2)$
- 计算:$t = KDF(x_2 \| y_2, klen)$
- 计算:$C_2 = M \oplus t$
- 计算:$C_3 = SM3(x_2 \| M \| y_2)$
- 输出密文 $C = C_1 \| C_3 \| C_2$
解密过程
输入:私钥 $d_B$、密文 $C$
- 从 $C$ 提取 $C_1 = (x_1, y_1)$,验证 $C_1$ 在曲线上
- 计算:$[d_B]C_1 = (x_2, y_2)$
- 计算:$t = KDF(x_2 \| y_2, klen)$
- 从 $C$ 提取 $C_2$,计算:$M' = C_2 \oplus t$
- 计算:$u = SM3(x_2 \| M' \| y_2)$
- 从 $C$ 提取 $C_3$,验证 $u = C_3$,若不等则解密失败
- 输出明文 $M'$
安全性分析
已知攻击
| 攻击类型 | 复杂度 | 说明 |
|---|---|---|
| 暴力破解 | $O(2^{128})$ | 穷举 256-bit 私钥 |
| Pollard's rho | $O(2^{128})$ | ECDLP 最佳已知算法 |
| MOV 归约 | 不适用 | sm2p256v1 的嵌入度很大 |
| 异常曲线攻击 | 不适用 | 曲线参数经过验证 |
与 RSA 的安全性对比
| 维度 | SM2-256 | RSA-2048 | RSA-3072 |
|---|---|---|---|
| 安全强度 | 128 bit | 112 bit | 128 bit |
| 密钥长度 | 256 bit | 2048 bit | 3072 bit |
| 签名速度 | 快 | 慢 | 很慢 |
| 验签速度 | 快 | 快 | 快 |
| 量子安全 | ❌ | ❌ | ❌ |
标准体系
SM2 的标准体系分为两部分:
| 层级 | 标准编号 | 内容 |
|---|---|---|
| 行业标准 | GM/T 0003.1-2012 | 总则 |
| 行业标准 | GM/T 0003.2-2012 | 数字签名算法 |
| 行业标准 | GM/T 0003.3-2012 | 密钥交换协议 |
| 行业标准 | GM/T 0003.4-2012 | 公钥加密算法 |
| 行业标准 | GM/T 0003.5-2012 | 参数定义 |
| 国家标准 | GB/T 32918.1-2016 | 总则 |
| 国家标准 | GB/T 32918.2-2016 | 数字签名算法 |
| 国家标准 | GB/T 32918.3-2016 | 密钥交换协议 |
| 国家标准 | GB/T 32918.4-2016 | 公钥加密算法 |
| 国家标准 | GB/T 32918.5-2016 | 参数定义 |
参考来源
- GM/T 0003-2012 — SM2 椭圆曲线公钥密码算法
- GB/T 32918-2016 — SM2 椭圆曲线公钥密码算法
- ISO/IEC 14888-3:2018 — Digital signatures with appendix
- ISO/IEC 11770-3:2018 — Key management
- GM/T 0009-2023 — SM2 密码算法使用规范
相关实践
- 如需了解 SM2 在 TLS 部署中的完整流程,请参阅《SM2 国密算法实战:从密钥生成到 TLS 完整部署》
- 如需了解 SM2 证书的生成和管理,请参阅《企业内部 PKI 建设实战:从根 CA 到证书自动化管理》
- 如需了解国密 HTTPS 部署过程中的常见问题,请参阅《国密 HTTPS 踩坑实录:从开发到上线的 12 个坑》