文件数字签名:证明真实性和来源
了解数字签名如何验证文件真实性并防止篡改。确保收件人知道谁发送了文件且文件未被更改。
数字签名是一种密码学证明,用于表明特定人员或实体创建了某文件,且该文件自创建以来未发生任何改动。技术层面上,你对文件进行 SHA-256 哈希,然后用私钥通过 RSA-PSS、ECDSA 或 Ed25519 对哈希值进行"签名"。任何持有你公钥的人都可以验证签名——若验证通过,他们就确认了是你创建了该文件,且文件与你签名时的内容逐字节一致。macOS 用签名验证应用更新,Git 用签名标记提交作者(git commit -S),PGP 用签名处理已签名邮件。签名解决了单纯加密无法解决的问题:证明是谁发送了什么。
签名与加密:各司其职
加密保护内容机密性,签名证明作者身份和完整性。两者相辅相成,而非相互替代。
- 仅加密:收件方知道内容,但不知道是谁发送的。任何持有公钥的人都可以加密。
- 仅签名:收件方知道是谁发送的、内容未被篡改,但内容对截获者可见。
- 先签名后加密:完整的真实性、完整性和机密性保护。这是 PGP 的默认模式。
文件传输服务通常侧重于加密。签名在高信任场景中才会出现:软件分发、法律文件、合同、司法证据链。
签名的实际工作原理
以 Ed25519 签名为例,标准流程如下:
- 对消息进行哈希:
h = SHA-512(消息)。 - 计算确定性随机数:
r = SHA-512(私钥前缀 || h)。 - 计算签名点:
R = r·G(G 为曲线基点)。 - 计算
s = r + SHA-512(R || 公钥 || h)·私钥 mod ℓ。 - 签名为
(R, s),共 64 字节。
验证只需公钥、消息和签名。若数学验证通过,验证方就确认签名由持有对应私钥的人生成。
RSA-PSS(PKCS#1 v2.2)和 ECDSA 原理类似,但使用不同的底层数学。Ed25519 是新系统的优选,因为它具有确定性(签名不需要逐次独立的随机数,消除了一类常见错误)且运算速度更快。
三种主要签名算法对比
| 算法 | 密钥大小 | 签名大小 | 速度 | 说明 | |------|----------|----------|------|------| | RSA-PSS-2048 | 256 字节 | 256 字节 | 约 1000 次签名/秒 | 广泛支持,密钥生成慢 | | ECDSA P-256 | 32 字节 | 64 字节 | 约 3 万次签名/秒 | NIST 曲线,每次签名需安全随机数 | | Ed25519 | 32 字节 | 64 字节 | 约 5 万次签名/秒 | 确定性,现代首选 |
三者均在 NIST FIPS 186-5(2023)中获批。Ed25519 是新协议的优选:WireGuard、SSH(OpenSSH 8.0 起默认)、Signal、Git 提交签名和 Rust 的 Cargo 包签名均采用此算法。
代码签名:价值数千亿的应用场景
软件分发依赖签名。没有签名,用户无法区分正版安装程序和恶意软件:
- Apple Developer ID + 公证:macOS 自 Catalina(2019 年)起要求所有应用签名并公证,使用 RSA-2048 或 ECDSA P-256。
- Microsoft Authenticode:Windows 可执行文件使用 RSA-3072 或 ECDSA P-384 证书签名。
- Android APK v2/v3:对 APK 内容使用 Ed25519 签名。
- Debian apt、Red Hat dnf、npm、PyPI、Homebrew:均对软件包清单使用独立签名(通常为 GPG Ed25519 或 RSA)。
著名事件:2020 年,SolarWinds 的 Orion 更新在攻击者攻陷构建系统后使用了公司的合法证书进行签名。签名是有效的——它只是证明了代码来自一个已被攻陷的来源。签名保证的是签名者的身份,而不是签名者的判断力。
使用 PGP 为文件生成独立签名
GnuPG(gpg)在企业 PKI 体系之外仍是文件签名的主力工具。独立签名保持原文件不变,将签名放在独立的 .sig 文件中:
gpg --detach-sign --armor document.pdf
# 生成 document.pdf.sig
gpg --verify document.pdf.sig document.pdf
# gpg: Good signature from "Alice <alice@example.com>"
PGP 的弱点在于密钥分发:验证方如何确认签名密钥确实属于 Alice?选项包括密钥服务器、信任网络、keybase.io 或带外验证(在名片上公布密钥指纹)。
现代替代方案:Sigstore(Kubernetes、npm 使用)通过 OIDC 身份令牌实现无密钥签名,用透明度日志替代信任网络。minisign(Frank Denis 开发)提供简单的 Ed25519 签名,无需 PGP 的复杂性。
基于哈希的签名聚合
对于大量文件的集合,逐一签名效率低下。更好的方法:对每个文件哈希,构建 Merkle 树,对根节点签名。优点:
- 一个签名覆盖多个文件。
- 每个文件可以通过 log(n) 个兄弟哈希在根节点上验证。
- 被证书透明度日志、Git 以及软件供应链工具(如 in-toto)广泛使用。
通过这种方式,一个包含 10000 个文件的发布版本只需一个签名加一个 32 字节的根哈希,可对任何文件子集进行验证。
时间戳:证明"何时"
签名证明"是谁",但不证明"何时"。窃得你私钥的攻击者可以伪造签名的时间。可信时间戳机构(TSA)通过对你的签名做时间戳签名来解决这一问题,将其锚定在某一特定时刻。
相关标准:
- RFC 3161 时间戳——被 Microsoft Authenticode、Adobe PDF 签名使用。
- RFC 5544(含时间戳的 CMS)。
- Roughtime——Google 推出的更新协议,用于低延迟可验证时间。
法律文件签名(DocuSign、Adobe Sign、EU eIDAS 合格签名)依赖来自可信机构的 RFC 3161 时间戳来确定合同签署时间。
签名在文件传输中的位置
大多数面向消费者的文件传输服务不直接暴露签名——AES-GCM 认证标签在传输范围内证明完整性,TLS 证明服务器身份,但没有内置机制证明发送方的身份。
对于高信任场景的传输,签名在上传前完成:
- 发送方用 Ed25519 或 PGP 签名文件,生成
file.ext和file.ext.sig。 - 两个文件均上传至任意传输服务(HexaTransfer、SwissTransfer、WeTransfer)。
- 收件方下载两个文件,用发送方的公钥验证签名。
这将真实性与传输机制解耦——即使传输服务被攻陷,只要发送方的私钥保持安全且收件方持有正确的公钥,签名的有效性就不受影响。
EU eIDAS 合格签名
欧盟 eIDAS 法规(EU 910/2014,2024 年更新为 eIDAS 2.0)定义了三个签名层级:
- 电子签名——基础级别,包括扫描的手写签名。
- 高级电子签名(AES/AdES)——与签名者关联,可检测篡改。PGP 签名属于此类。
- 合格电子签名(QES)——在 AdES 基础上,加上来自信任服务提供商的合格证书,存储于合格签名创建设备(智能卡或 HSM)中。
QES 在所有欧盟成员国具有与手写签名相同的法律效力。提供商包括 DocuSign EU、Adobe Sign EU、Namirial 和 DTrust。美国在 ESIGN 法和 UETA 下的对应规范层级不那么正式,但功能上类似。
不需要签名的场景
并非每个文件都需要签名。以下情况可以省略:
- 收件方对整个传输渠道充分信任(Signal、当面 USB 传递)。
- 内容不涉及安全关键(会议照片、食谱、草稿文件)。
- 仅需完整性保证,且由 AES-GCM 或 TLS 已提供。
以下情况需要添加签名:
- 涉及法律或合同效力(合同、法庭证据、医疗记录)。
- 涉及供应链信任(软件发布、固件更新)。
- 文件将通过不可信中间方转发。
- 需要在原始传输结束后仍可追溯的审计记录。
在 hexatransfer.com 上试试 — 免费、无需注册、最多 10 GB。