裸签、Attach、Detach及其验签方式
一、裸签(Bare Signature)的验签过程
核心概念
裸签是最基础的签名形式,签名数据仅包含加密后的哈希摘要,与原始数据完全分离,验签时必须同时提供原始数据和签名值。
完整流程
- 签名阶段(发送方):
- 步骤 1:对原始数据(如文件、文本)计算哈希摘要(用 SHA-256 等算法,固定长度,不可逆)。
例:原始数据 “Hello”→ 哈希摘要a1b2c3...
(256 位)。 - 步骤 2:用发送方的私钥对哈希摘要加密,生成 “裸签值”(二进制或 Base64 编码)。
例:私钥加密后得到签名s4k5l6...
。 - 步骤 3:分别传输原始数据和裸签值(如通过两个文件、不同接口)。
- 步骤 1:对原始数据(如文件、文本)计算哈希摘要(用 SHA-256 等算法,固定长度,不可逆)。
- 验签阶段(接收方):
- 步骤 1:获取原始数据和裸签值。
- 步骤 2:用发送方的公钥对裸签值解密,得到 “签名时的哈希摘要”(即发送方计算的
a1b2c3...
)。 - 步骤 3:接收方自己对原始数据计算哈希摘要(同样用 SHA-256),得到 “验签时的哈希摘要”。
- 步骤 4:对比两个摘要:若一致,则验签通过(数据未篡改,签名有效);否则失败。
关键依赖
- 验签方必须提前获取发送方的公钥(需确保公钥未被篡改,通常通过证书信任链)。
- 原始数据与裸签值需通过独立渠道同步,若原始数据被替换,即使签名正确也会验签失败。
示例:本地文件校验
- 场景:用户 A 对本地文件
report.pdf
生成裸签sign.bin
,并将文件和签名通过 U 盘拷贝给用户 B。 - 验签:用户 B 用 A 的公钥解密
sign.bin
得到摘要,再对report.pdf
计算摘要,对比一致则确认文件未被篡改。
二、Attach 类型(附加签名)的验签过程
核心概念
Attach 类型将原始数据完整嵌入签名结构,最终生成一个 “原始数据 + 签名” 的复合文件,验签时仅需该复合文件即可。
完整流程
- 签名阶段(发送方):
- 步骤 1:对原始数据计算哈希摘要(同裸签)。
- 步骤 2:用私钥加密摘要生成签名值。
- 步骤 3:构建 “签名容器”,包含三部分:
- 原始数据(完整内容);
- 签名值(加密后的摘要);
- 元信息(哈希算法、签名算法等,如 “算法 = SHA-256+RSA”)。
- 步骤 4:传输该签名容器(一个独立文件或数据包)。
- 验签阶段(接收方):
- 步骤 1:解析签名容器,提取原始数据、签名值、元信息。
- 步骤 2:用发送方公钥解密签名值,得到 “签名时的哈希摘要”。
- 步骤 3:按元信息指定的算法,对提取的原始数据计算 “验签时的哈希摘要”。
- 步骤 4:对比两个摘要,一致则验签通过。
关键特点
- 数据自包含:无需额外获取原始数据,避免 “数据与签名分离” 的风险。
- 体积较大:签名容器大小 = 原始数据大小 + 签名值大小(通常几百字节)。
示例:S/MIME 邮件签名
- 场景:用户发送带签名的邮件,邮件客户端生成 Attach 类型签名容器,包含邮件正文、签名值和算法信息。
- 验签:接收方邮件客户端直接解析该容器,提取正文并验证签名,确认邮件未被篡改且来自合法发送方。
三、Detach 类型(分离签名)的验签过程
核心概念
Detach 类型是裸签的增强版:签名不包含原始数据,但包含原始数据的唯一引用信息(如哈希、文件名、位置标识),验签时需同时提供原始数据和签名容器。
完整流程
- 签名阶段(发送方):
- 步骤 1:对原始数据计算哈希摘要(同前)。
- 步骤 2:用私钥加密摘要生成签名值。
- 步骤 3:构建 “分离签名容器”,包含三部分:
- 原始数据的引用信息(如文件唯一 ID、数据哈希、存储路径 XPath/URL);
- 签名值;
- 元信息(算法、签名时间等)。
- 步骤 4:分别传输原始数据和分离签名容器。
- 验签阶段(接收方):
- 步骤 1:获取原始数据和分离签名容器,解析容器得到引用信息、签名值、元信息。
- 步骤 2:验证 “原始数据与引用信息的匹配性”(核心差异点):
- 例:若引用信息是原始数据的哈希,则计算接收的原始数据哈希,与引用信息对比,确保是签名对应的原始数据。
- 步骤 3:用公钥解密签名值,得到 “签名时的哈希摘要”。
- 步骤 4:对原始数据计算 “验签时的哈希摘要”,与解密后的摘要对比,一致则验签通过。
关键优势
- 防数据替换:通过引用信息验证原始数据的正确性,解决裸签中 “原始数据被替换但签名仍可能通过” 的漏洞。
- 灵活性高:原始数据可单独存储(如大型文件存服务器,签名存本地),不增加数据传输体积。
示例:XML 文档签名
- 场景:对 XML 文档中
<payment>
标签内容生成 Detach 签名,签名容器包含该标签的 XPath 路径(/root/transaction/payment
)作为引用信息。 - 验签:接收方先通过 XPath 定位到 XML 中的
<payment>
内容,验证其与签名容器中的引用信息匹配,再进行哈希对比,确保该部分内容未被篡改。
三种方式的核心流程对比
阶段 | 裸签 | Attach 类型 | Detach 类型 |
签名输出 | 仅签名值 | 原始数据 + 签名值 + 元信息 | 引用信息 + 签名值 + 元信息 |
验签输入 | 原始数据 + 签名值 | 签名容器(自包含) | 原始数据 + 分离签名容器 |
关键额外步骤 | 无 | 从容器提取原始数据 | 验证原始数据与引用信息匹配 |
数据关联性 | 依赖外部同步(弱) | 强(数据嵌入签名) | 中(引用信息辅助匹配) |
总结
- 裸签:极简形式,适合信任环境中已知数据不会被替换的场景(如本地校验)。
- Attach 类型:自包含性强,适合需要 “一次传输完成验证” 的场景(如邮件、合同)。
- Detach 类型:平衡安全性与灵活性,适合大文件或分布式系统(如 XML、大型数据集签名)。
为了让理解更完整,我们可以再补充一点细节:
- 裸签:提供「原始数据 + 加密签名值」,但两者是完全分离的,没有任何内置的关联信息(比如 “这个签名属于哪个数据”),需要依赖外部方式(如人工备注、文件名约定)确保配对正确。
- Attach:提供「原始数据 + 加密签名值的打包体」,两者物理绑定在一起(比如一个文件里同时包含原文和签名),不需要额外信息就能确定 “签名属于这个数据”。
- Detach:提供「原始数据 + 加密签名值 + 引用信息」,其中引用信息是关键纽带(通常包含在签名值的载体中,如独立的签名文件),用于明确 “这个签名对应哪个原始数据”,三者分离但通过引用信息逻辑绑定。
- 裸签:“数据和签名分离,无关联信息”
- Attach:“数据和签名打包,天然关联”
- Detach:“数据和签名分离,但有引用信息做关联”
实际应用中,Detach 类型因兼顾安全性和效率,在规范(如 W3C XML Signature、CMS)中应用最广泛,而 Attach 类型则在需要简化传输流程的场景中更受欢迎。