验签Signature Verification)是用 公钥、消息和签名判断该签名是否由对应 私钥 生成,并且消息在签名后没有被篡改的过程。

核心问题

验签解决的是“这份数据是不是来自预期签发方或密钥持有者,并且内容是否还是签名时的内容”的问题。它是 数字签名 体系的验证侧,常和 签发 成对出现。

验签关注真实性和完整性,不负责隐藏内容,也不自动给出业务授权结论。

核心机制

验签通常需要这些输入:

  • 被签名的原始消息或规范化载荷。
  • 签名值。
  • 签名算法和参数。
  • 签发方 公钥 或可验证到可信根的 数字证书
  • 时间、用途、主体、撤销状态等业务约束。

可抽象为:

其中 pk 是公钥,M 是消息,\sigma 是签名。工程实现里,验签前后还要处理编码、摘要算法、证书链、密钥用途、有效期和错误处理。

设备或客户端验签时,通常内置的是“验签算法 + 公钥”,而不是私钥:

发布侧:
content -> hash
signature = Sign(私钥, hash)
输出 content + signature
 
设备侧:
content -> hash
ok = Verify(公钥, hash, signature)

验签算法本身是通用的。以 ECDSA 为例,同一个 verify 函数可以验证很多不同公钥对应的签名;传入哪把公钥,就等于告诉算法“检查这个签名是不是那把私钥对应的签名”。因此公钥不是多余数据,而是身份和信任锚。

常见嵌入式伪代码是:

ok = verify(LICENSE_PUBKEY, digest_of_license, signature);

其中 LICENSE_PUBKEY 是烧进设备的公钥常量,signature 是发布侧用私钥生成并随内容分发的签名。

工程用途

  • TLS 握手:验证服务器证书链和握手签名。
  • 软件更新:客户端验签安装包、固件、容器镜像或更新清单。
  • 令牌验证:服务验证 JWT 或临时凭据是否由认证系统签发。
  • 设备授权:设备或服务端验证设备证书、挑战响应或离线授权文件。
  • Git 与包管理器:验证提交、标签、发布包或依赖来源。

观察指标包括验签失败率、失败原因分布、证书过期、算法降级、未知密钥 ID、撤销检查失败和时间同步问题。

边界与常见坑

  • 验签成功不等于授权成功:还要检查签发方是否可信、主体是否匹配、权限是否足够、凭据是否过期或撤销。
  • 必须先解决公钥信任:用攻击者给的公钥验攻击者的签名当然会成功。
  • 只验证签名值不够:证书链、用途、域名、时间和撤销状态都可能是安全边界。
  • 算法混淆很危险:不能让输入随意指定 alg=none、弱算法或错误密钥类型。
  • 签名只保护签名输入:未纳入签名的字段、HTTP 头或配置项仍可能被篡改。
  • 错误处理要保守:解析失败、证书链失败、时间不可用或撤销查询失败不应被当作通过。

相关术语