Skip to main content

ofd_core/model/
signature.rs

1//! 数字签名与签章结构(见 GB/T 33190—2016 第 18 章)。
2//!
3//! 签名相关部件分两层:
4//! - 签名列表 `Signatures.xml`([`Signatures`],见表 80):由 `DocBody/Signatures`
5//!   指向,登记包内所有签名,每个 [`SignatureRef`] 通过 `BaseLoc` 指向一份签名描述
6//!   文件;
7//! - 单个签名描述 `Signature.xml`([`Signature`] / `CT_Signature`,见表 81):包含
8//!   被保护文件摘要清单 [`SignedInfo`] 与签名值文件 `SignedValue` 的位置。
9//!
10//! 完整性校验依据 [`SignedInfo`] 的 [`References`]:逐个重新计算 `FileRef` 所指
11//! 文件的摘要并与 [`Reference::check_value`] 比对,验证签名覆盖的内容是否被篡改。
12//! 具体校验逻辑见 [`crate::verify`]。
13
14use serde::{Deserialize, Serialize};
15
16use crate::types::{StBox, StId, StLoc};
17
18/// 签名列表 `Signatures.xml` 的根节点(见表 80)。
19#[derive(Debug, Clone, Default, Deserialize, Serialize)]
20pub struct Signatures {
21    /// 当前文档中签名的最大标识,新增签名应在此基础上递增(可选)。
22    #[serde(rename = "MaxSignId")]
23    pub max_sign_id: Option<String>,
24    /// 签名描述入口列表,每个指向一份 `Signature.xml`(必选,可多个)。
25    #[serde(rename = "Signature", default)]
26    pub signatures: Vec<SignatureRef>,
27}
28
29/// 签名列表中的一条签名入口(见表 80)。
30///
31/// 这是签名列表对单个签名的*引用*;真正的签名描述是 [`Signature`]。
32#[derive(Debug, Clone, Default, Deserialize, Serialize)]
33pub struct SignatureRef {
34    /// 签名标识,文档内唯一(必选)。
35    #[serde(rename = "@ID")]
36    pub id: StId,
37    /// 签名类型:`Seal`(电子印章,默认)或 `Sign`(纯签名)(可选)。
38    #[serde(rename = "@Type")]
39    pub sig_type: Option<String>,
40    /// 指向签名描述文件 `Signature.xml`(必选)。
41    #[serde(rename = "@BaseLoc")]
42    pub base_loc: StLoc,
43}
44
45impl SignatureRef {
46    /// 签名类型,缺省按规范取 `Seal`。
47    pub fn type_or_default(&self) -> &str {
48        self.sig_type.as_deref().unwrap_or("Seal")
49    }
50}
51
52/// 单份签名描述 `Signature.xml` 的根节点(`CT_Signature`,见表 81)。
53#[derive(Debug, Clone, Deserialize, Serialize)]
54pub struct Signature {
55    /// 签名要保护的原文及摘要信息(必选)。
56    #[serde(rename = "SignedInfo")]
57    pub signed_info: SignedInfo,
58    /// 指向签名值文件(`SignedValue.dat`,承载 SM2 签名/SES 签章数据)(必选)。
59    #[serde(rename = "SignedValue")]
60    pub signed_value: StLoc,
61}
62
63/// `SignedInfo`:签名原文信息(见表 82)。
64#[derive(Debug, Clone, Deserialize, Serialize)]
65pub struct SignedInfo {
66    /// 创建签名时所用的签名引擎提供者信息(必选)。
67    #[serde(rename = "Provider")]
68    pub provider: Provider,
69    /// 签名方法,使用算法的 OID(如 SM2 为 `1.2.156.10197.1.501`)(可选)。
70    #[serde(rename = "SignatureMethod")]
71    pub signature_method: Option<String>,
72    /// 签名时间(可选)。
73    #[serde(rename = "SignatureDateTime")]
74    pub signature_date_time: Option<String>,
75    /// 包内文件摘要清单,签名所保护的内容(必选)。
76    #[serde(rename = "References")]
77    pub references: References,
78    /// 签章外观(电子印章在页面上的呈现位置),可多个(可选)。
79    #[serde(rename = "StampAnnot", default)]
80    pub stamp_annots: Vec<StampAnnot>,
81    /// 电子印章信息(可选)。
82    #[serde(rename = "Seal")]
83    pub seal: Option<Seal>,
84}
85
86/// `Provider`:签名引擎提供者(见表 83)。
87#[derive(Debug, Clone, Default, Deserialize, Serialize)]
88pub struct Provider {
89    /// 创建签名的引擎提供者名称(必选)。
90    #[serde(rename = "@ProviderName")]
91    pub provider_name: String,
92    /// 提供者版本(可选)。
93    #[serde(rename = "@Version")]
94    pub version: Option<String>,
95    /// 提供者厂商(可选)。
96    #[serde(rename = "@Company")]
97    pub company: Option<String>,
98}
99
100/// `References`:被保护文件的摘要清单(见表 84)。
101#[derive(Debug, Clone, Default, Deserialize, Serialize)]
102pub struct References {
103    /// 摘要(杂凑)算法的 OID,缺省由签名实现约定;国密 SM3 为
104    /// `1.2.156.10197.1.401`(可选)。
105    #[serde(rename = "@CheckMethod")]
106    pub check_method: Option<String>,
107    /// 摘要记录列表。
108    #[serde(rename = "Reference", default)]
109    pub references: Vec<Reference>,
110}
111
112/// `Reference`:单个被保护文件的摘要记录(见表 84)。
113#[derive(Debug, Clone, Default, Deserialize, Serialize)]
114pub struct Reference {
115    /// 指向包内被保护文件的路径(必选)。
116    #[serde(rename = "@FileRef")]
117    pub file_ref: StLoc,
118    /// 对应文件的摘要值,按 `CheckMethod` 计算后做 Base64 编码(必选)。
119    #[serde(rename = "CheckValue", default)]
120    pub check_value: String,
121}
122
123/// `StampAnnot`:签章在页面上的外观标注(见表 85)。
124#[derive(Debug, Clone, Default, Deserialize, Serialize)]
125pub struct StampAnnot {
126    /// 签章标识(可选)。
127    #[serde(rename = "@ID")]
128    pub id: Option<StId>,
129    /// 引用的页面标识(可选)。
130    #[serde(rename = "@PageRef")]
131    pub page_ref: Option<String>,
132    /// 签章在页面中的外观边界(可选)。
133    #[serde(rename = "@Boundary")]
134    pub boundary: Option<StBox>,
135    /// 签章的裁剪区域(可选)。
136    #[serde(rename = "@Clip")]
137    pub clip: Option<StBox>,
138}
139
140/// `Seal`:电子印章,指向独立的印章数据文件(见表 81)。
141#[derive(Debug, Clone, Default, Deserialize, Serialize)]
142pub struct Seal {
143    /// 指向电子印章文件(可选)。
144    #[serde(rename = "BaseLoc")]
145    pub base_loc: Option<StLoc>,
146}