GM/T 0003-2012 SM2 密码算法标准深度解读:从规范框架到合规实施
概述
GM/T 0003-2012《SM2 密码算法》系列标准由国家密码管理局于 2012 年发布,是我国商用密码领域 SM2 算法的权威规范。该标准系列包含五个子标准,分别规定了 SM2 算法的总则、数字签名算法、密钥交换协议、公钥加密算法和参数定义。该系列标准后续被采纳为国家标准 GB/T 32918-2016,并通过 ISO/IEC 14888-3:2018/Amd 1 成为国际标准的一部分。
本文从标准原文出发,系统解读 GM/T 0003 系列的技术要求、参数定义和合规实施要点,为密码工程师、系统架构师和合规审计人员提供权威参考。
GM/T 0003 系列标准结构
GM/T 0003-2012 系列包含以下五个子标准:
| 子标准编号 | 标准名称 | 适用范围 | 对应国家标准 |
|---|---|---|---|
| GM/T 0003.1-2012 | SM2 密码算法 第1部分:总则 | 算法概述、总体框架、符号定义 | GB/T 32918.1-2016 |
| GM/T 0003.2-2012 | SM2 密码算法 第2部分:数字签名算法 | 签名生成与验证算法、消息摘要要求 | GB/T 32918.2-2016 |
| GM/T 0003.3-2012 | SM2 密码算法 第3部分:密钥交换协议 | 密钥交换流程、共享密钥计算、密钥派生 | GB/T 32918.3-2016 |
| GM/T 0003.4-2012 | SM2 密码算法 第4部分:公钥加密算法 | 加密与解密算法、密钥封装机制 | GB/T 32918.4-2016 |
| GM/T 0003.5-2012 | SM2 密码算法 第5部分:参数定义 | 推荐曲线参数、辅助函数定义 | GB/T 32918.5-2016 |
标准层级关系
GM/T 0003.1 (总则)
├── GM/T 0003.2 (数字签名)
├── GM/T 0003.3 (密钥交换)
├── GM/T 0003.4 (公钥加密)
└── GM/T 0003.5 (参数定义)GM/T 0003.1-2012:总则
3.1 算法总称与设计目标
标准定义 SM2 算法为"基于椭圆曲线的公钥密码算法",具备以下核心能力:
- 数字签名:对消息进行签名并验证签名的合法性
- 密钥交换:在通信双方之间安全地交换密钥素材
- 公钥加密:使用公钥加密数据,使用私钥解密数据
3.2 符号与术语定义
标准中使用的主要符号:
| 符号 | 含义 | 说明 |
|---|---|---|
| $E$ | 椭圆曲线 | 定义在有限域 $F_p$ 上的椭圆曲线 |
| $E(F_p)$ | 椭圆曲线上的点集 | 包含无穷远点 $\mathcal{O}$ |
| $G$ | 基点 | 椭圆曲线上的一个生成元 |
| $n$ | 基点的阶 | 满足 $nG = \mathcal{O}$ 的最小正整数 |
| $h$ | 余因子 | $h = \#E(F_p) / n$ |
| $d$ | 私钥 | 随机整数,$1 \leq d \leq n-1$ |
| $Q$ | 公钥 | 椭圆曲线上的点,$Q = dG$ |
| $Z_A$ | 用户标识摘要 | 对用户标识的哈希值 |
3.3 辅助函数
标准定义以下辅助函数:
消息哈希函数 $H_v(\cdot)$:
- 输出长度 $v$ 比特的哈希值
- SM2 签名算法使用 $H_{256}(\cdot)$,对应 SM3 哈希算法
- $KDF(Z, klen)$:从共享秘密 $Z$ 派生 $klen$ 比特的密钥
- 基于 SM3 哈希构造:$KDF(Z, klen) = H_1(Z) \| H_2(Z) \| \cdots \| H_h(Z)$
- 其中 $H_i(Z) = SM3(Z \| Counter_i)$,$Counter_i$ 为 32-bit 计数器
- 在公钥加密中使用,基于 SM3 构造
GM/T 0003.2-2012:数字签名算法
4.1 签名算法流程
SM2 签名算法分为签名生成和签名验证两步。
签名生成(用户 A 对消息 $M$ 签名):
1. 计算 $M' = Z_A \| M$
2. 计算 $e = H_{256}(M')$
3. 选择随机数 $k \in [1, n-1]$
4. 计算椭圆曲线点 $(x_1, y_1) = kG$
5. 计算 $r = (e + x_1) \mod n$
6. 若 $r = 0$ 或 $r + k = n$,返回步骤 3
7. 计算 $s = ((1 + d)^{-1}(k - rd)) \mod n$
8. 若 $s = 0$,返回步骤 3
9. 签名值为 $(r, s)$签名验证(用户 B 验证签名 $(r, s)$):
1. 验证 $r \in [1, n-1]$
2. 验证 $s \in [1, n-1]$
3. 计算 $M' = Z_A \| M$
4. 计算 $e = H_{256}(M')$
5. 计算 $t = (r + s) \mod n$
6. 若 $t = 0$,验证失败
7. 计算椭圆曲线点 $(x_1, y_1) = sG + tQ$
8. 计算 $R = (e + x_1) \mod n$
9. 验证 $R = r$4.2 用户标识哈希 $Z_A$
标准定义用户标识的计算方式:
$Z_A = H_{256}(ID_A \| a \| b \| x_G \| y_G \| x_A \| y_A)$
其中:
- $ID_A$:用户标识(默认值
1234567812345678) - $a, b$:椭圆曲线参数
- $x_G, y_G$:基点坐标
- $x_A, y_A$:用户 A 的公钥坐标
4.3 签名算法测试向量
GM/T 0003.1-2012 附录 A 提供了标准测试向量。以下为一个典型测试向量(十六进制表示):
私钥 d: 3945208F 7B2144B1 3F36E38A C6D39F95 88939369 2860B51A 42FB81EF 4DF3B908
公钥 Q:
x: 09F9DF31 1E5461A5 6F766C93 040B88F8 8E16F0F5 B255D388 0914D755 7D6D8981
y: 3CEF3270 65BC901 C417904A 09B96423 A35C1539 9B0F0024 6B14F600 4D7AAAA0
消息 M: "message digest"
随机数 k: 59276E27 D5066640 B345C220 F5FFC3B4 7EA8D666 E5C35883 90ABBBA9 92D86BA0
签名值:
r: F5A03B06 48D99879 072E8161 64265 AE76 F3A8713D 64C1572B 0BF4FC19 0E37CDA9
s: 7DECC5AB 08B06282 5DDD9E29 5F2E240A 3A66E677 D3369FAA 1E040E16 06F9E07E4.4 签名算法安全要点
标准强调了以下安全约束:
- 随机数 $k$ 必须密码学安全:需使用经核准的随机数发生器(GM/T 0005-2012)
- 签名值 $(r, s)$ 不能为 0:若计算结果为 0,需重新选择随机数
- 密钥长度约束:私钥 $d$ 必须满足 $1 \leq d \leq n-1$
- 哈希函数要求:必须使用 SM3 算法(GM/T 0004-2012)
GM/T 0003.3-2012:密钥交换协议
5.1 密钥交换流程
SM2 密钥交换协议允许两个实体在不安全信道上协商共享秘密。
初始化(双方预先确定):
- 系统参数:$E, G, n$
- 身份:$ID_A, ID_B$
- 密钥对:$(d_A, Q_A), (d_B, Q_B)$
- 可选:共享秘密长度 $keyLen$
用户 A:
1. 选择随机数 $r_A \in [1, n-1]$
2. 计算 $R_A = r_A G$
3. 发送 $R_A$ 和 $ID_A$ 给用户 B
用户 B:
4. 选择随机数 $r_B \in [1, n-1]$
5. 计算 $R_B = r_B G$
6. 计算 $x_B = \tilde{R}_B$(将 $R_B$ 的 x 坐标转换为整数)
7. 计算 $t_B = (d_B + x_B \cdot r_B) \mod n$
8. 验证 $R_A$ 是否在曲线上($n R_A \neq \mathcal{O}$)
9. 计算 $x_A = \tilde{R}_A$
10. 计算 $U_B = [h \cdot t_B](Q_A + [x_A]R_A)$
11. 若 $U_B = \mathcal{O}$,协议失败
12. 计算 $K_B = KDF(x_{U_B} \| y_{U_B} \| Z_A \| Z_B, keyLen)$
13. 计算 $S_B = H_1(x_{U_B} \| Z_A \| Z_B \| x_{R_A} \| y_{R_A} \| x_{R_B} \| y_{R_B})$
14. 发送 $R_B, S_B$ 给用户 A
用户 A:
15. 计算 $x_A = \tilde{R}_A$
16. 计算 $t_A = (d_A + x_A \cdot r_A) \mod n$
17. 验证 $R_B$ 合法性
18. 计算 $x_B = \tilde{R}_B$
19. 计算 $U_A = [h \cdot t_B](Q_B + [x_B]R_B)$
20. 计算 $K_A = KDF(x_{U_A} \| y_{U_A} \| Z_A \| Z_B, keyLen)$
21. 计算 $S_A = H_1(x_{U_A} \| Z_A \| Z_B \| x_{R_A} \| y_{R_A} \| x_{R_B} \| y_{R_B})$
22. 验证 $S_A = S_B$5.2 密钥派生细节
标准附录详细说明了 KDF 函数的构造:
KDF(Z, klen):
counter = 0x00000001
while klen > 0:
H = SM3(Z || counter)
copy min(32, klen) bytes from H to output
counter += 1
klen -= 32
return output5.3 密钥交换安全属性
标准明确 SM2 密钥交换满足以下安全属性:
| 安全属性 | 描述 | SM2 实现情况 |
|---|---|---|
| 前向保密 | 长期私钥泄露不导致历史会话密钥泄露 | ✅ 满足(基于临时密钥 $r_A, r_B$) |
| 密钥保密性 | 被动攻击者无法获取共享秘密 | ✅ 满足(基于 ECDLP) |
| 认证性 | 双方身份认证 | ⚠️ 需额外数字签名 |
| 隐式认证 | 共享秘密的身份绑定 | ✅ 满足 |
| 显式认证 | 通过 MAC 验证身份 | ✅ 满足($S_B$ 验证) |
GM/T 0003.4-2012:公钥加密算法
6.1 加密算法
加密(用户 B 加密消息 $M$ 给用户 A):
1. 选择随机数 $k \in [1, n-1]$
2. 计算 $(x_1, y_1) = kG$
3. 计算 $(x_2, y_2) = kQ_A$
4. 计算 $t = C_3 = KDF(x_2 \| y_2, len(M))$,若 $t$ 全为 0,返回步骤 1
5. 计算 $C_2 = M \oplus t$
6. 计算 $C_3 = SM3(x_2 \| M \| y_2)$
7. 密文为 $C = C_1 \| C_2 \| C_3$,其中 $C_1 = (x_1, y_1)$6.2 解密算法
解密(用户 A 使用私钥 $d_A$ 解密密文 $C$):
1. 从 $C$ 提取 $C_1 = (x_1, y_1)$,验证 $C_1$ 在曲线上
2. 计算 $(x_2, y_2) = d_A \cdot C_1$
3. 计算 $t = KDF(x_2 \| y_2, len(C_2))$,若 $t$ 全为 0,解密失败
4. 计算 $M' = C_2 \oplus t$
5. 计算 $u = SM3(x_2 \| M' \| y_2)$,若 $u \neq C_3$,解密失败
6. 返回 $M'$6.3 加密格式变体
标准定义三种密文格式:
| 格式 | 标识 | 说明 | ||
|---|---|---|---|---|
| 未压缩 | 04 | $C_1$ 包含完整坐标 $(x_1, y_1)$ | ||
| 压缩 | 02 或 03 | $C_1$ 仅包含 x 坐标和奇偶位 | ||
| C1C2C3 | — | $C_1 \ | C_2 \ | C_3$ 顺序拼接 |
| C1C3C2 | — | $C_1 \ | C_3 \ | C_2$ 顺序拼接 |
6.4 安全约束
- 随机数 $k$ 不能重复使用:每次加密必须生成新的 $k$
- KDF 输出长度:必须与消息长度匹配
- 点验证:解密时必须验证 $C_1$ 在曲线上
- MAC 验证:解密时必须验证 $C_3$ 的正确性
GM/T 0003.5-2012:参数定义
7.1 推荐曲线参数
标准推荐使用 256 比特素数域上的椭圆曲线 $E: y^2 = x^3 + ax + b$。
| 参数 | 符号 | 十六进制值 |
|---|---|---|
| 素数 $p$ | $p$ | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF |
| 曲线系数 $a$ | $a$ | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC |
| 曲线系数 $b$ | $b$ | 28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93 |
| 基点 x 坐标 | $x_G$ | 32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7 |
| 基点 y 坐标 | $y_G$ | BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0 |
| 子群阶 $n$ | $n$ | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123 |
7.2 参数验证
标准要求对曲线参数进行验证:
1. $p$ 必须为 256 比特素数
2. $a, b \in F_p$,且 $4a^3 + 27b^2 \neq 0$
3. $G$ 必须在曲线上:$y_G^2 = x_G^3 + a \cdot x_G + b \mod p$
4. $n$ 必须为素数
5. $n \cdot G = \mathcal{O}$(无穷远点)
6. $h = \#E(F_p) / n \leq 4$
7. 曲线不能是异常曲线($\#E(F_p) \neq p$)
8. 曲线不能是超奇异曲线7.3 SM2 与 NIST P-256 参数对比
| 参数 | SM2 (sm2p256v1) | NIST P-256 (secp256r1) | 差异 |
|---|---|---|---|
| $p$ | FFFFFFFE...FFFFFF | FFFFFFFF00000001... | 不同素数构造 |
| $a$ | FFFFFFFE...FFFFFFFC | FFFFFFFF00000001...FFFFFFFC | 形式相似但不同 |
| $b$ | 28E9FA9E...4D940E93 | 5AC635D8...3617DEA5 | 完全不同 |
| $n$ | FFFFFFFE...39D54123 | FFFFFFFF...14836F40 | 不同阶 |
| 设计状态 | 部分保密 | 公开 | SM2 部分参数来源保密 |
| 安全强度 | ~128 bit | ~128 bit | 相当 |
国家标准与国际标准映射
8.1 GB/T 32918-2016 国家标准
GB/T 32918 是 GM/T 0003 的国家标准化版本:
| GM/T 标准 | GB/T 标准 | 发布时间 | 状态 |
|---|---|---|---|
| GM/T 0003.1-2012 | GB/T 32918.1-2016 | 2016-10-01 | 现行有效 |
| GM/T 0003.2-2012 | GB/T 32918.2-2016 | 2016-10-01 | 现行有效 |
| GM/T 0003.3-2012 | GB/T 32918.3-2016 | 2016-10-01 | 现行有效 |
| GM/T 0003.4-2012 | GB/T 32918.4-2016 | 2016-10-01 | 现行有效 |
| GM/T 0003.5-2012 | GB/T 32918.5-2016 | 2016-10-01 | 现行有效 |
8.2 ISO/IEC 国际标准
SM2 算法已被 ISO/IEC 采纳:
| ISO/IEC 标准 | 内容 | SM2 对应部分 |
|---|---|---|
| ISO/IEC 14888-3:2018/Amd 1 | 数字签名 第3部分:基于离散对数的机制 | SM2 数字签名 |
| ISO/IEC 11770-3:2018 | 密钥管理 第3部分:基于非对称技术的机制 | SM2 密钥交换 |
| ISO/IEC 18033-3:2010/Amd 1 | 加密算法 第3部分:非对称加密 | SM2 加密 |
合规实施要点
9.1 算法正确性验证
标准符合性测试应包含:
- 签名算法测试:使用标准测试向量验证签名和验证算法
- 密钥交换测试:验证双方计算的共享秘密一致
- 加密/解密测试:验证 $Decrypt(Encrypt(M)) = M$
- 边界条件测试:测试消息长度为 0、1、最大值等边界情况
- 随机数测试:验证随机数发生器符合 GM/T 0005-2012
9.2 安全强度评估
SM2 算法的安全强度:
| 攻击类型 | 复杂度 | 说明 |
|---|---|---|
| 离散对数攻击 (Pollard's Rho) | $O(\sqrt{n}) \approx 2^{128}$ | 当前最有效的经典攻击 |
| MOV 攻击 | 不适用 | SM2 曲线参数选择避免了 MOV 攻击 |
| Smart 攻击 | 不适用 | SM2 曲线非超奇异 |
| 侧信道攻击 | 需防护 | 需实现恒定时间操作 |
9.3 合规检查清单
密码系统实施 GM/T 0003 时应检查:
- [ ] 使用标准推荐的 256 比特曲线参数
- [ ] 签名算法使用 SM3 哈希(GM/T 0004-2012)
- [ ] KDF 函数使用 SM3 构造
- [ ] 随机数发生器符合 GM/T 0005-2012
- [ ] 密钥生成使用密码学安全的随机数
- [ ] 验证所有输入点的合法性(在曲线上、不在无穷远点)
- [ ] 私钥存储安全(加密存储或硬件保护)
- [ ] 实现通过国家密码管理局的型号审查
参考来源
- GM/T 0003.1-2012 SM2 密码算法 第1部分:总则
- GM/T 0003.2-2012 SM2 密码算法 第2部分:数字签名算法
- GM/T 0003.3-2012 SM2 密码算法 第3部分:密钥交换协议
- GM/T 0003.4-2012 SM2 密码算法 第4部分:公钥加密算法
- GM/T 0003.5-2012 SM2 密码算法 第5部分:参数定义
- GB/T 32918.1-2016 SM2 密码算法 第1部分:总则
- ISO/IEC 14888-3:2018 - Digital signatures with appendix
- ISO/IEC 11770-3:2018 - Key management
- OSCCA - 商用密码标准清单
相关实践
- SM2 算法原理详解 - SM2 的数学原理与算法流程
- 国密 TLS 协议 - SM2 在国密 TLS 中的应用
- SM2 签名编码指南 - SM2 签名的 DER 编码实践
- GM/T 0028 密码模块安全要求 - 密码模块合规标准