跳转到内容
HexaTransfer
返回博客
加密与安全

文件数字签名:证明真实性和来源

了解数字签名如何验证文件真实性并防止篡改。确保收件人知道谁发送了文件且文件未被更改。

数字签名是一种密码学证明,用于表明特定人员或实体创建了某文件,且该文件自创建以来未发生任何改动。技术层面上,你对文件进行 SHA-256 哈希,然后用私钥通过 RSA-PSS、ECDSA 或 Ed25519 对哈希值进行"签名"。任何持有你公钥的人都可以验证签名——若验证通过,他们就确认了是你创建了该文件,且文件与你签名时的内容逐字节一致。macOS 用签名验证应用更新,Git 用签名标记提交作者(git commit -S),PGP 用签名处理已签名邮件。签名解决了单纯加密无法解决的问题:证明是谁发送了什么。

签名与加密:各司其职

加密保护内容机密性,签名证明作者身份和完整性。两者相辅相成,而非相互替代。

  • 仅加密:收件方知道内容,但不知道是谁发送的。任何持有公钥的人都可以加密。
  • 仅签名:收件方知道是谁发送的、内容未被篡改,但内容对截获者可见。
  • 先签名后加密:完整的真实性、完整性和机密性保护。这是 PGP 的默认模式。

文件传输服务通常侧重于加密。签名在高信任场景中才会出现:软件分发、法律文件、合同、司法证据链。

签名的实际工作原理

以 Ed25519 签名为例,标准流程如下:

  1. 对消息进行哈希:h = SHA-512(消息)
  2. 计算确定性随机数:r = SHA-512(私钥前缀 || h)
  3. 计算签名点:R = r·G(G 为曲线基点)。
  4. 计算 s = r + SHA-512(R || 公钥 || h)·私钥 mod ℓ
  5. 签名为 (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 证明服务器身份,但没有内置机制证明发送方的身份。

对于高信任场景的传输,签名在上传前完成:

  1. 发送方用 Ed25519 或 PGP 签名文件,生成 file.extfile.ext.sig
  2. 两个文件均上传至任意传输服务(HexaTransfer、SwissTransfer、WeTransfer)。
  3. 收件方下载两个文件,用发送方的公钥验证签名。

这将真实性与传输机制解耦——即使传输服务被攻陷,只要发送方的私钥保持安全且收件方持有正确的公钥,签名的有效性就不受影响。

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。

通过端到端加密安全发送大文件

通过端到端加密免费传输最大10GB的文件。无需注册账户。文件在上传前在浏览器中加密,其他人无法读取。

发送文件