解析一张 SSL 证书时,结果里会列出两串很长的十六进制字符,分别标着「SHA-1 指纹」和「SHA-256 指纹」。它们看起来像哈希值,也确实就是哈希值——是对整张证书计算出来的摘要。指纹的用途很明确:确认「两张证书是不是同一张」。但要注意,它不能证明证书可信。
指纹是怎么算出来的
指纹是对整张证书的二进制内容(DER 编码)计算哈希得到的结果。
证书在文件里可能是 PEM 文本格式(Base64 加 BEGIN/END 行),也可能直接是 DER 二进制格式。但计算指纹时,会先把内容还原成 DER 二进制,再对它算哈希。
所以只要证书内容有一个字节的差异,指纹就会完全不同。这些差异可能包括:有效期变了、SAN 列表加了一个域名、序列号不同、签名算法不同。
SHA-1 指纹是 20 字节,用十六进制表示是 40 个字符。SHA-256 指纹是 32 字节,十六进制表示是 64 个字符。有些工具会把它们按两位一组用冒号分隔显示,便于阅读和比对。
用途一:比对两张证书
最直接的用途是判断「从两个渠道拿到的证书是不是同一张」。
比如运维同学从服务器上导出了一张证书,从 CDN 控制台下载了另一张,怀疑它们是否一致。计算两边的指纹,一致就说明是同一张,不一致说明有差异。
这个方法比逐字段比对更可靠,因为逐字段比对容易漏掉细节——比如 SAN 列表里多了一个域名,人工比对时可能没注意到,但指纹会立刻反映出来。
用途二:核对安装是否正确
有些服务会公布证书的指纹,用来让用户确认自己安装的是正确的证书。
例如在配置 VPN、邮件客户端、内部服务时,服务方可能提供一个指纹值,用户安装完证书后计算指纹并比对。这样可以避免中间人攻击——如果攻击者替换了证书,指纹就会不同。
在一些需要手工导入证书的场景(比如企业内网的自签名证书),指纹核对是一个必要的步骤。
指纹不是签名
这里需要明确一个关键区别:指纹不是签名。
指纹只能说明「这张证书是这一张」,它不能说明「这张证书是可信的」。
原因在于,任何人都可以给任意一张证书算指纹。攻击者自己生成一张证书,也能算出它的指纹,甚至可以把这张假证书的指纹公布出来。如果用户只是比对「指纹是否一致」,而指纹的来源本身不可信,那么比对就失去了意义。
签名的机制不同。证书里的签名是由 CA 的私钥生成的,验证签名需要用 CA 的公钥。攻击者没有 CA 的私钥,无法伪造签名。所以签名能证明「这张证书确实是由某个 CA 签发的」,这是指纹做不到的。
在实践中,指纹用于「核对」,签名用于「信任」。两者的作用不能互换。
SHA-1 和 SHA-256 该看哪个
两个指纹都列出来了,日常应该用哪个?
答案是 SHA-256。
原因和前面讨论过的一样:SHA-1 已经被实际构造出碰撞。2017 年 Google 和 CWI 联合发布了 SHAttered 攻击,构造出两个内容不同但 SHA-1 相同的 PDF 文件。这意味着 SHA-1 指纹理论上可能无法唯一标识一张证书——攻击者可以构造两张证书让它们有相同的 SHA-1 指纹。
虽然针对证书的实际碰撞攻击需要更苛刻的条件,但既然 SHA-256 没有这个问题,就没有理由继续依赖 SHA-1。
SHA-1 指纹仍然会显示,主要出于兼容性考虑——一些老旧的系统、文档、工单模板可能只记录 SHA-1 指纹。在核对这类历史记录时可以参考,但新记录应该使用 SHA-256。
指纹还能做什么
除了上面两个用途,指纹在运维里还有一些辅助作用。
排查证书更新是否生效。更新证书后,指纹应该变化。如果发现指纹没变,说明新的证书没有真正生效(可能配置文件路径不对、或者服务没重载)。
记录变更审计。在安全审计里记录每个时间点的证书指纹,可以清晰地看出证书何时被更换过。
区分同名证书。如果同一个域名有多张证书(比如测试环境和生产环境各一张),用指纹可以快速区分,比看有效期更可靠。
检查清单
- 指纹是对整张证书的 DER 二进制内容计算哈希得到的摘要
- 用途是比对两张证书是否相同、核对安装是否正确
- 指纹不是签名,不能证明证书可信,只用于核对
- 日常应使用 SHA-256 指纹,SHA-1 已被构造出碰撞
- SHA-1 指纹仅用于兼容老旧系统与历史记录
- 证书更新后指纹应当变化,可用于排查更新是否生效