那些年我们踩过的坑——SignedData

admin 2026-06-03 04:09:40 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文系统对比了GB/T35275与GM/T0010标准中SM2签名数据SignedData格式的关键差异,包括版本号、字段命名、内容封装结构和签名计算规则等方面的不一致性。通过真实案例指出这些差异可能导致跨系统解析失败,并给出明确标准选择、自适应解析、统一签名计算等避坑指南,帮助开发者避免互操作性问题。 综合评分: 88 文章分类: 技术标准,密码学,安全开发


cover_image

那些年我们踩过的坑——SignedData

原创

利刃信安 利刃信安

利刃信安

2026年6月1日 11:11 北京

在小说阅读器读本章

去阅读

那些年我们踩过的坑——SignedData

摘要:在密码应用开发中,SM2 算法签名消息的封装格式一直是个“雷区”。国家标准 GB/T 35275 与行业标准 GM/T 0010 对 SignedData 的定义存在多处关键差异:版本号不同、字段命名迥异、内容封装结构不一致、签名计算过程的描述详略悬殊。本文结合真实踩坑经历,系统梳理了这些差异,并给出了避坑指南,帮助开发者避免“同一种签名,两套解析”的尴尬局面。


一、故事的起因:两个标准,一个签名

某天,你兴奋地拿到了一个 SM2 签名数据包,按照 GB/T 35275 文档编写了解析代码,顺利通过自测。然而,当这个数据包被送到另一个系统验证时,对方却报出“格式错误”“签名验证失败”。你翻遍代码,怀疑人生——最后发现,对方用的是 GM/T 0010 标准。

这种情况在密码行业并不罕见。GB/T 35275(国家标准)和 GM/T 0010(密码行业标准)虽然都定义了 SM2 密码算法的加密签名消息格式,但两者的 SignedData 部分存在诸多“微妙”差异。这些差异就像地雷,一不小心就会炸翻你的生产环境。


二、第一个坑:版本号——1 还是 2?

打开两个标准,先看 SignerInfo 的版本号:

| 标准 | SignerInfo 版本号 | 备注 | | — | — | — | | GB/T 35275-2026 | 2 | 从 2017 版的 1 改为 2 | | GM/T 0010-2023 | 1 | 保持原有值 |

这意味着什么?如果你按 GB/T 35275 生成签名,SignerInfo.version 字段值为 2;而按 GM/T 0010 解析的代码可能只接受值为 1。结果就是解析失败,或者被强制转换为 1 导致后续校验混乱。

真实案例:某 CA 系统升级后,签名数据被下游应用拒收,排查两天才发现版本号不一致。最终被迫在两端同时支持两种版本号,并通过协商机制决定使用哪个标准。


三、第二个坑:字段名称和结构差异

你以为只是版本号不同?太天真了。看看 SignedData 的核心结构:

| 字段 | GB/T 35275-2026 | GM/T 0010-2023 | | — | — | — | | 内容封装 | encapContentInfo | contentInfo | | 签名算法标识 | signatureAlgorithm | digestEncryptionAlgorithm | | 签名值 | signature | encryptedDigest | | 待签名属性 | signedAttrs | authenticatedAttributes | | 未签名属性 | unsignedAttrs | unauthenticatedAttributes |

更致命的是,encapContentInfo 和 contentInfo 的结构完全不同:

  • • GB/T 35275EncapsulatedContentInfo 包含 eContentType 和 eContent(显式 OCTET STRING)。
  • • GM/T 0010ContentInfo 包含 contentType 和 content(ANY,由 contentType 决定)。

某次对接中,开发人员直接复用了一个 GM/T 0010 的解析库去解析 GB/T 35275 数据,结果在 eContent 字段上崩溃——因为 GM/T 0010 根本不知道 eContent 是什么。


四、第三个坑:签名计算过程的“罗生门”

签名计算是 SignedData 的核心。两个标准都允许 signedAttrs(或 authenticatedAttributes)存在或不存在,但细节天差地别:

GB/T 35275 的明确要求

若 signedAttrs 存在,则待签名数据为 signedAttrs 的 DER 编码结果,且 signedAttrs 必须包含 messageDigest 属性,其值为 eContent 的 SM3 杂凑值。 若 signedAttrs 不存在,则待签名数据为 eContent 的内容(不包括 DER 标签和长度)。

GM/T 0010 的模糊描述

若 authenticatedAttributes 存在,该域中摘要的计算方法是对原文进行摘要计算结果。

这里的“原文”是什么?是对 content 的内容做摘要,还是对 authenticatedAttributes 自身做摘要?标准没有明确说 authenticatedAttributes 必须包含 messageDigest,也没有说明如何组织待签名数据。这导致不同厂商的实现五花八门:

  • • 厂商 A:将 authenticatedAttributes 的 DER 编码作为签名输入(与 GB/T 35275 一致)。
  • • 厂商 B:直接将 content 的摘要签名,再放入 authenticatedAttributes 中作为属性(但属性集合本身不参与签名)。
  • • 厂商 C:干脆忽略 authenticatedAttributes,永远使用无属性签名。

后果:同一个签名数据,在不同实现下验证结果可能完全相反。


五、第四个坑:隐式证书的“隐身术”

GM/T 0010-2023 在附录 B 中增加了隐式证书相关数据类型(imcSignedDataimcEnvelopedData 等),而 GB/T 35275-2026 完全不支持隐式证书。如果你以为两个标准完全兼容,直接拿 GM/T 0010 的隐式证书数据去给 GB/T 35275 解析,结果必然是“找不到 OID”或“格式错误”。


六、避坑指南

1. 明确你遵循的是哪个标准

  • • 如果是商用密码应用,通常遵循 GM/T 0010(行业标准更早普及)。
  • • 如果是金融、政务等强调国标兼容的场景,可能要求 GB/T 35275
  • • 最稳妥的方式:在协议或配置文件中明确标注使用的标准版本。

2. 自适应解析

建议实现一个兼容两层标准的解析器:

  • • 读取 SignerInfo.version:若为 1,按 GM/T 0010 解析;若为 2,按 GB/T 35275 解析。
  • • 通过 OID 判断内容封装类型(encapContentInfo vs contentInfo)。

3. 签名计算统一化

强烈建议统一采用带有 signedAttrs 且包含 messageDigest 的方式,因为这种方式最安全、最规范,且 GB/T 35275 已明确要求。GM/T 0010 虽未强制,但实际行业实践中大多数实现也遵循此方式。

4. 版本号协商

如果需跨系统互操作,可增加一个握手阶段,交换双方支持的 SignedData 版本号,然后按对应版本生成/解析。

5. 工具链统一

尽可能使用同一套密码库(如 GMSSL、OpenSSL 的 SM2 扩展),并在库层面做统一抽象。避免手动拼接 ASN.1 结构。


七、结语

“踩坑”的根源,在于标准演进过程中留下的历史包袱。GB/T 35275-2026 相比旧版改动较大(版本号从 1 改 2、增加了 AuthEnvelopedData 等),而 GM/T 0010-2023 保持了更多旧版结构。两者之间的差异并非不可调和,但需要开发者保持警惕。

记住:不要默认“所有 SM2 签名数据格式都一样”。下次再收到一个 SignedData,先问一句:“这是按哪个标准封装的?版本号是多少?”——这简单的一问,能帮你省下至少两个通宵。

愿天下没有难解析的签名数据。


附录:关键差异速查表

| 项目 | GB/T 35275-2026 | GM/T 0010-2023 | | — | — | — | | SignedData 版本 | 1 | 1 | | SignerInfo 版本 | 2 | 1 | | 内容封装 | encapContentInfo | contentInfo | | 签名算法标识 | signatureAlgorithm | digestEncryptionAlgorithm | | 签名值字段 | signature | encryptedDigest | | 签名属性字段 | signedAttrs | authenticatedAttributes | | 隐式证书支持 | 无 | 有(附录 B) | | 签名计算详细度 | 高(明确指定 DER 编码) | 低(描述模糊) |


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:利刃信安 利刃信安 利刃信安《那些年我们踩过的坑——SignedData》

评论:0   参与:  0