数字签名Digital Signature)是用 私钥 为消息生成可验证证明、再用 公钥 验证消息来源和完整性的 公钥密码学 机制。

核心问题

数字签名解决的是“接收方如何确认这段数据确实由某个 私钥 持有者授权,并且传输或存储过程中没有被篡改”的问题。它关注真实性和完整性,不提供机密性。

核心机制

典型流程是:

  1. 对消息做规范化编码,避免同一含义有多种字节表示。
  2. 计算消息摘要。
  3. 私钥 对摘要或签名输入生成签名。
  4. 接收方用 公钥、消息和签名进行 验签

可抽象为:

常见算法包括 RSA-PSS、ECDSAEdDSAEd25519。签名算法通常需要把上下文、算法标识、时间戳或业务字段纳入签名输入,避免签名被挪用到另一个语义场景。

以 ECDSA P-256 为例,私钥 d 是一个 32 字节左右的大整数,公钥是曲线点:

Q = dG

这里 G 是公开基点,dG椭圆曲线标量乘法,不是普通数字乘法。签名由两个大整数组成:

signature = (r, s)

签名过程可以写成:

e = H(M)                         # 消息摘要
k = 每次签名的一次性数
R = kG = (x1, y1)
r = x1 mod n
s = k^-1 * (e + r*d) mod n

验签方没有 dk,但有公钥 Q。它通过 (r, s)、消息摘要和 Q 计算:

w  = s^-1 mod n
u1 = e*w mod n
u2 = r*w mod n
X  = u1G + u2Q

如果 X 的横坐标取模后等于 r,验签通过。合法签名能通过,是因为 Q = dG,代入后 u1G + u2Q 会化简回签名时的 kG。这解释了为什么“私钥能签名,公钥能验签”,但公钥不能反推出私钥。

工程用途

  • 证书体系:证书颁发机构用签名把身份和 公钥 绑定到 数字证书
  • 软件发布:包管理器、安装包、固件和容器镜像签名。
  • Git 与提交验证:证明提交或标签来自某个密钥持有者。
  • 区块链交易私钥 签名表达资产转移授权。
  • 离线授权:设备或客户端只内置 公钥,无法伪造平台 签发 的授权材料。

边界与常见坑

  • 签名不是加密:签名后的内容仍然可能是明文,旁观者可以读取。
  • 能验签不等于可信:还要判断 公钥 是否可信、数字证书 是否有效、密钥是否撤销。
  • 签名只覆盖被签名的字节:未纳入签名的字段仍可被篡改。
  • 规范化很重要:JSON 字段顺序、空白、编码和数字表示不同,可能导致验签失败或语义绕过。
  • 不要混用密钥用途:签名密钥、加密密钥、密钥交换密钥最好分离。
  • 随机数错误会泄露私钥:部分签名算法如 ECDSAnonce 质量非常敏感,重复使用一次性数 k 可能直接推导出私钥。

相关术语