GM/T 0010-2023 SM2 密码算法加密签名消息语法规范:标准解读与合规实施
概述
GM/T 0010 系列标准规定了使用 SM2 密码算法进行加密和签名操作时,对操作结果的标准化封装格式。它相当于国密体系中的 PKCS#7/CMS(Cryptographic Message Syntax),是 SM2 加密数据、数字签名、消息认证码等操作的"容器格式"。
2023 年 12 月 4 日发布、2024 年 6 月 1 日实施的 GM/T 0010-2023 是对 2012 版(GM/T 0010-2012)的全面修订。新版标准与国家密码管理局同期发布的 25 项密码行业标准同步实施,与 GB/T 32918 系列(SM2 算法标准)和 GB/T 35275-2017(信息安全技术 SM2 密码算法加密签名消息语法规范)形成了更清晰的分工体系。
标准背景与定位
为什么需要消息语法规范?
SM2 算法本身定义了密钥生成、数字签名、密钥交换和公钥加密四个基本操作。但这些操作的结果(密文、签名、MAC 值)在实际应用中需要被封装成结构化数据,以便:
- 携带元数据:谁加密的?用了什么算法?证书序列号是多少?
- 支持复合操作:既签名又加密(先签名后加密 vs 先加密后签名)
- 跨平台互操作:不同厂商的密码设备/库使用统一的 ASN.1 编码
- 支持批量处理:一条消息中包含多个收件人或多个签名者
与 GB/T 35275-2017 的关系
GB/T 35275-2017《信息安全技术 SM2 密码算法加密签名消息语法规范》是国标层面的 SM2 消息语法标准,其技术内容与 GM/T 0010-2012 高度重合。两者的关系如下:
| 维度 | GM/T 0010-2023 | GB/T 35275-2017 |
|---|---|---|
| 发布部门 | 国家密码管理局(行业标准) | 国家标准委(国家标准) |
| 适用范围 | 密码行业内部、商用密码产品 | 全社会信息系统 |
| 修订时间 | 2023 年修订 | 2017 年初版 |
| 技术差异 | 2023 版增加了新的密文格式选项和 OID 体系 | 基本保持 2012 版 GM/T 0010 的技术框架 |
核心内容解读
1. ASN.1 数据结构
GM/T 0010-2023 定义了以下核心 ASN.1 结构:
#### ContentInfo(内容信息)
ContentInfo ::= SEQUENCE {
contentType ContentType,
content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
}
ContentType ::= OBJECT IDENTIFIER其中 contentType 可以是:
sm2EncryptedData(SM2 加密数据)sm2SignedData(SM2 签名数据)sm2DigestedData(SM2 摘要数据)sm2AuthenticatedData(SM2 认证数据)
#### SM2EncryptedData
SM2EncryptedData ::= SEQUENCE {
version INTEGER,
recipientInfos RecipientInfos,
encryptedContentInfo EncryptedContentInfo,
sm2Params SM2Params OPTIONAL
}关键字段说明:
- version:版本号,2023 版定义为 4(与 CMS 标准对齐)
- recipientInfos:接收者信息列表,每个接收者包含其 SM2 公钥加密的会话密钥
- encryptedContentInfo:加密内容信息,包含加密内容的 OID 和密文
- sm2Params:SM2 加密参数,包括密文格式标志(C1C2C3 vs C1C3C2)
SM2SignedData ::= SEQUENCE {
version INTEGER,
digestAlgorithms DigestAlgorithmIdentifiers,
signedContent SignedContent,
signerInfos SignerInfos,
certificates [0] IMPLICIT CertificateSet OPTIONAL,
crls [1] IMPLICIT RevocationInfoChoices OPTIONAL
}关键字段说明:
- digestAlgorithms:摘要算法标识,必须为 sm3WithSm2Digest
- signerInfos:签名者信息列表,每个签名者包含 SM2 签名值
- certificates:可选的证书集合,用于签名者身份验证
- crls:可选的 CRL 集合,用于证书吊销验证
2. 密文格式:C1||C2||C3 vs C1||C3||C2
这是 GM/T 0010-2023 最重要的修订之一。
SM2 公钥加密产生的密文由三部分组成:
- C1:随机点 R = kG(64 字节,X||Y 坐标)
- C2:密文数据 = M ⊕ Hash(T, A, Ra, Rb, B)(可变长度)
- C3:SM3 哈希值(32 字节)
ciphertextFormat 字段指示:SM2Params ::= SEQUENCE {
ciphertextFormat INTEGER {c1c2c3(0), c1c3c2(1)},
eccCurveId ECCCurveIdentifier DEFAULT sm2Curve
}工程影响:
- C1||C2||C3 是传统格式,兼容所有 2012 版实现
- C1||C3||C2 格式允许在解密时先验证完整性(C3),再解密(C2),减少侧信道攻击面
- 互操作时必须在 ASN.1 结构中显式声明使用的格式,不能假设默认值
3. OID 体系更新
GM/T 0010-2023 定义了完整的 OID 编号体系:
| 对象 | OID | 说明 |
|---|---|---|
| sm2Encrypt | 1.2.156.10197.1.301 | SM2 公钥加密算法 OID |
| sm2Sign | 1.2.156.10197.1.501 | SM2 数字签名算法 OID |
| sm3WithSm2 | 1.2.156.10197.1.501 | SM3 with SM2 签名算法 OID |
| sm2EncryptedData | 1.2.156.10197.1.401 | SM2 加密数据内容类型 OID |
| sm2SignedData | 1.2.156.10197.1.402 | SM2 签名数据内容类型 OID |
| sm2DigestedData | 1.2.156.10197.1.403 | SM2 摘要数据内容类型 OID |
| sm2AuthenticatedData | 1.2.156.10197.1.404 | SM2 认证数据内容类型 OID |
1.2.156.10197.1.x(国密算法 OID 分支)下,与 GB/T 32905(SM4 OID)和 GB/T 32907(SM3 OID)形成统一体系。4. 签名与加密的组合操作
GM/T 0010-2023 支持四种组合模式:
| 模式 | 描述 | 适用场景 |
|---|---|---|
| 仅签名 | SignerInfo + DigestAlgorithm | 文件签名、代码签名 |
| 仅加密 | SM2EncryptedData + RecipientInfo | 安全邮件、加密存储 |
| 先签名后加密 | SM2EncryptedData 包裹 SM2SignedData | 机密性 + 不可否认性 |
| 先加密后签名 | SM2SignedData 包裹 SM2EncryptedData | 可验证的加密传输 |
2023 版修订要点
重大变更汇总
- 密文格式可选化:新增 C1||C3||C2 格式选项,通过 sm2Params 显式声明
- 版本号统一:version 字段从 0 改为 4,与 CMS 标准 RFC 5652 对齐
- OID 体系扩展:新增 sm2AuthenticatedData 内容类型 OID
- 证书链验证增强:signedContent 中新增对多证书链的支持
- 时间戳集成:支持在 SignerInfo 中嵌入 RFC 3161 格式的时间戳
- SM2 椭圆曲线参数明确化:不再引用 GM/T 0009,直接使用标准定义的曲线参数
与 2012 版的兼容性
2023 版在 ASN.1 结构上与 2012 版保持了大部分兼容,但以下情况可能导致互操作失败:
- 密文格式不一致:2012 版强制 C1||C2||C3,2023 版可选 C1||C3||C2
- 版本号差异:2012 版 version=0,2023 版 version=4
- OID 变更:部分旧实现的 OID 映射表未更新到 2023 版
工程实施指南
Python 实现示例(使用 gmssl 库)
"""
GM/T 0010-2023 SM2 加密签名消息语法实现示例
环境要求:gmssl >= 3.2, python-gmssl 或自建 ASN.1 编解码器
注意:以下代码为概念演示,实际使用中应通过合法的 SM2 密钥生成流程获得密钥对。
"""
from gmssl import sm2, func
import asn1tools # pip install asn1tools
# 1. 生成 SM2 密钥对(使用 gmssl 库的正确方式)
priv_key_hex = func.random_num_hex(32) # 32 字节随机私钥(在合法范围内)
# 注意:实际生产环境中,公钥应由 SM2 密钥生成函数返回,而非随机字节
# 此处仅为展示 gmssl.CryptSM2 的调用方式
pub_key_hex = '04' + func.random_num_hex(64) # 演示用占位符,非有效 SM2 公钥
sm2_crypt = sm2.CryptSM2(
public_key=pub_key_hex,
private_key=priv_key_hex
)
# 2. SM2 加密(产生 C1||C2||C3 或 C1||C3||C2)
plaintext = b"Hello, GM/T 0010-2023!"
ciphertext = sm2_crypt.encrypt(plaintext)
print(f"Ciphertext length: {len(ciphertext)} bytes")
print(f"Ciphertext (hex): {ciphertext.hex()}")
# 3. 构建 ContentInfo 包装(简化示意)
# 实际工程中需要使用 ASN.1 编解码器构建完整的 SM2EncryptedData 结构
# 包括 version、recipientInfos、encryptedContentInfo、sm2Params 等字段常见实施陷阱
陷阱 1:密文格式硬编码
许多旧实现将 SM2 密文硬编码为 C1||C2||C3 格式。在 2023 版环境下,必须从 ASN.1 结构中读取 ciphertextFormat 字段,动态选择解析方式。
陷阱 2:忽略版本号检查
version=0 和 version=4 的 SM2EncryptedData 在字段布局上可能不同。解码时必须先检查版本号,再选择对应的解析逻辑。
陷阱 3:OID 映射过时
旧版库的 OID 表可能不包含 2023 版新增的 sm2AuthenticatedData(1.2.156.10197.1.404)OID。实施时应使用最新的 OID 映射表。
陷阱 4:证书链验证缺失
在 SM2SignedData 中,certificates 字段是可选的。但接收方如果没有独立的证书分发渠道,将无法验证签名者身份。建议在签名数据中始终附带签名者证书。
与密评的关系
GM/T 0010-2023 是密评中 SM2 加密和签名合规性检查的重要依据:
- GM/T 0054-2018 第 8.2.3 节要求使用 SM2 加密时,密文封装格式应符合 GM/T 0010 的规定
- GM/T 0034-2014 第 6.3 节规定证书签发时使用的签名消息格式应符合 GM/T 0010
- GB/T 39786-2021 三级及以上系统要求 SM2 签名消息必须包含时间戳信息
参考来源
- GM/T 0010-2023《SM2 密码算法加密签名消息语法规范》,国家密码管理局,2023-12-04 发布,2024-06-01 实施
- GB/T 35275-2017《信息安全技术 SM2 密码算法加密签名消息语法规范》,国家标准委,2017
- RFC 5652 Cryptographic Message Syntax (CMS),IETF,2009
- GM/T 0009-2023《SM2 密码算法使用规范》,国家密码管理局
- https://std.samr.gov.cn/hb/search/stdHBDetailed?id=1BF26B7A9FF7FD76E06397BE0A0A81D8
相关实践
- GM/T 0003-2012 SM2 密码算法标准深度解读 — SM2 算法标准本身
- SM2 国密算法实战:从密钥生成到 TLS 完整部署 — SM2 工程实践
- SM2 密钥 Shamir 门限分割实战 — SM2 高级应用
- 国密 PKI 证书自动化管理协议 — 证书签发中的 SM2 签名