自动续期跑了一年,私钥却从来没换过——谈证书轮换中最容易被跳过的一环
很多站点证书一直在正常续期,但私钥从部署第一天起就没换过。本文分析私钥长期不换带来的泄露窗口问题,给出强制换密钥、吊销旧证书和审计部署记录的具体做法。
本文目录

凌晨两点值班同事问了一个好问题:这台服务器的证书续了十几次了,私钥还是三年前那把吗?
答案通常是"是"。主流的 ACME 客户端默认行为是续期时生成新私钥,但不少人为了省事,用 --reuse-key 或者自己写的脚本把旧 key 固定下来——理由往往是"HPKP 钉过"(早已废弃)、"F5 上换 key 麻烦"、"反正证书会过期"。这些理由每一个都能理解,合在一起就是一个风险敞口。
私钥不换,风险在哪

证书有效期这两年被一再压缩,从三年到 398 天,到即将推进的 200 天甚至更短。缩短证书寿命的核心动机只有一个:限制私钥泄露后攻击者的可用窗口。如果你每次续期都复用同一把私钥,这个保护就名存实亡——证书换了十几轮,真正值钱的那把 key 已经在你的跳板机、配置管理仓库、历次运维的笔记里躺了三年。
另一个常被忽略的点:吊销机制几乎没人真靠得住。客户端默认不查 OCSP 就是常态。所以"key 泄露了就吊销"更像安慰剂,真正的防线是让泄露的那把 key 尽快随证书一起作废。
处置的三个具体动作

1. 确认续期流程确实在换密钥。 不要假设,去查。对比连续两期证书目录下的私钥哈希即可,比如:
sha256sum /etc/letsencrypt/archive/*/privkey*.pem | sort哈希全都相同,就是一直在复用。检查是不是哪个自动化脚本里写了 --reuse-key,或者签发工具配置了 reuse_private_keys。

2. 新密钥上线后,旧证书该吊销就吊销。 特别是你怀疑旧 key 可能接触过不该接触的地方(离职运维的笔记本、没加密的备份盘、CI 日志)。ACME 协议支持用证书私钥或授权账户发起吊销(见 RFC 8555 的 revocation 部分),流程本身不复杂,复杂的是很多人不知道旧证书留在那里也是资产。
3. 把"部署到哪了"记下来。 私钥轮换最怕的是漏换:CDN 上换了,源站还是旧 key;主域名换了,APK 里写死的备用接口还是旧证书。没有部署清单,换 key 就是拆弹时剪线全凭手感。
在 CertbotX 中实践

CertbotX 的 ACME 自动签发在每次到期前重新签发时会生成新私钥,不留"复用旧 key"的开关,轮换是默认行为而非可选项。签发后证书会按记录自动部署到 Agent、EdgeOne 或 CDN,每次部署的目标、时间和证书指纹都进部署记录,审计时可以直接核对"这把 key 现在在哪些地方服役"。对于上面第三点提到的漏换问题,这种集中式部署清单比运维自己维护的 wiki 表格可靠得多——毕竟 wiki 的更新频率通常和它的可信程度成反比。
一个容易误判的边界
换密钥和换证书是两回事。有些团队做了"每 90 天自动续期"就以为密钥管理完成了,实际上 CA 从不关心你有没有换 key,它只验证你对域名的控制权。安全性那一半,得自己补上。

另外,如果你的服务对私钥加载有特殊要求(硬件 HSM、外部 key 托管),"每次换 key"的成本会明显上升,这时合理的折中是把轮换周期固定下来(比如每年一次)并写进变更流程,而不是无限期拖延。完全不换和换得太勤导致流程跑挂,前者只是更隐蔽的坏。
---
参考核验: