SM2 椭圆曲线公钥密码算法

算法原理 · 2026-06-01

概述

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 被采纳为国际标准的一部分。

算法基本参数

参数SM2RSA-2048ECDSA (P-256)说明
标准编号GB/T 32918-2016PKCS#1 v2.2FIPS 186-4SM2 为国标
密钥长度256 bit2048 bit256 bitSM2 密钥极短
安全强度~128 bit~112 bit~128 bitSM2 与 P-256 相当
签名长度~64 bit (r,s)2048 bit~512 bitSM2 签名极短
功能签名+加密+密钥交换签名+加密仅签名SM2 功能最全
曲线类型sm2p256v1secp256r1不同曲线参数
关键对比: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
系数 $b28E9FA9E 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
这些参数在 GM/T 0003.5-2012 和 GB/T 32918.5-2016 中严格定义。

⚠️ 重要提示: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$(椭圆曲线标量乘法)
$$sk = d_A \in_R [1, n-1]$$ $$pk = P_A = [d_A]G = (x_{P_A}, y_{P_A})$$

其中 $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)$
- 使用 SM3 哈希函数 - $H_{len(ID_A)}$ 是 ID 长度的编码函数(2 字节大端序)

  • 计算消息哈希:$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 = (e + x_1) \bmod n$$ 若 $r = 0$ 或 $r + k = n$,则重新选择 $k$

  • 计算签名分量:
$$s = ((1 + d_A)^{-1} \cdot (k - r \cdot d_A)) \bmod n$$ 若 $s = 0$,则重新选择 $k$

  • 输出签名 $(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)$:

其中:

  • $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)$
- 若 $[h]P_B = \mathcal{O}$(无穷远点),则加密失败
  • 计算:$t = KDF(x_2 \| y_2, klen)$
- 若 $t$ 全为零,则重新选择 $k$
  • 计算:$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)$
- 若 $t$ 全为零,则解密失败
  • 从 $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 的嵌入度很大
异常曲线攻击不适用曲线参数经过验证
目前对 SM2 最有效的攻击是 Pollard's rho 算法,时间复杂度为 $O(\sqrt{n}) \approx O(2^{128})$,与 SHA-256 的抗碰撞安全性相当。

与 RSA 的安全性对比

维度SM2-256RSA-2048RSA-3072
安全强度128 bit112 bit128 bit
密钥长度256 bit2048 bit3072 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参数定义

参考来源

相关实践