私钥一旦泄露,最稳妥的做法是立即撤销旧证书并生成全新的密钥对重新申请,不要试图沿用旧密钥 renewal。
先说结论:私钥泄露属于高危风险,必须撤销旧证书并使新证书生效,同时更换密钥对。
- 先判断:确认私钥泄露范围,评估是否已被滥用
- 优先做:调用 ACME 接口撤销旧证书,生成新私钥重新签发
- 再验证:检查新证书序列号已变更,旧证书在吊销列表中
命令速用版
如果你使用 Certbot 管理证书,可以参考以下命令流程。注意替换实际路径。
# 1. 撤销旧证书(需要旧私钥或账户密钥)
certbot revoke `--cert-path` /etc/letsencrypt/live/yourdomain.com/cert.pem `--key-path` /etc/letsencrypt/live/yourdomain.com/privkey.pem
# 2. 强制重新签发(自动生成新私钥)
certbot certonly `--force-renewal` -d yourdomain.com
# 3. 重载 Web 服务
systemctl reload nginx
核心原理
HTTPS 安全依赖于私钥的保密性。一旦私钥泄露,攻击者可以伪装成你的服务器拦截流量或签发伪造内容。虽然浏览器不一定实时检查吊销状态,但撤销证书是标准应急流程,能防止部分客户端信任旧证书。Let's Encrypt 允许通过 ACME 协议主动撤销证书,但必须证明你拥有该证书对应的私钥或账户权限。
分步处理
按照以下顺序操作,确保旧证书失效且新证书可用。
1. 备份现有配置
在操作前备份当前的证书目录和 Web 服务器配置,防止操作失误导致服务中断。
cp -r /etc/letsencrypt/live/yourdomain.com /root/backup_letsencrypt_$(date +%F)
2. 撤销旧证书
使用 Certbot 的 revoke 命令。如果你还能访问旧私钥,直接用私钥撤销;如果私钥已丢失但账户密钥还在,可用账户密钥撤销。公开资料中没有看到可靠的量化数据说明撤销生效的具体传播时间,通常建议立即执行。
3. 清理旧密钥文件
为防止误用,建议在生成新证书后,手动清理旧密钥存档(Certbot 默认会保留历史密钥)。
# 查看存档目录
ls /etc/letsencrypt/archive/yourdomain.com/
# 删除旧私钥(谨慎操作,确认新证书已生效)
rm /etc/letsencrypt/archive/yourdomain.com/privkey1.pem
4. 生成新密钥对并申请
不要复用旧密钥。运行签发命令时,必须添加 `--force-renewal` 参数,确保 Certbot 生成新的 private key。Let's Encrypt 对同一域名有每周签发次数限制,应急操作一般不会影响,但避免频繁重试。
5. 部署新证书
将新生成的 cert.pem 和 privkey.pem 路径配置到 Nginx 或 Apache 中,并 reload 服务。
怎么验证是否生效
确认新证书已生效且旧证书序列号不再使用。
# 查看新证书序列号
openssl x509 -in /etc/letsencrypt/live/yourdomain.com/cert.pem -noout -serial
对比撤销前后的序列号,确保不一致。你也可以使用在线 SSL 检测工具查看证书状态,确认没有报错。
常见坑与备选方案
- 未更换私钥:重新签发时如果复用旧私钥文件,风险依然存在,务必让工具生成新 key。
- 服务未重载:证书文件更新了但 Web 服务还在用旧内存副本,必须 reload 或 restart。
- 触发频率限制:短时间内多次失败申请可能触发 Let's Encrypt 速率限制,导致无法立即签发新证。
- 撤销失败备选:如果旧私钥已丢失无法撤销,应立即生成新证书替换旧证书。虽然旧证书无法主动吊销,但新证书生效后,旧证书因密钥不匹配将无法用于新的 TLS 握手(除非攻击者已截获流量)。
参考来源
- Let's Encrypt, "Revoking Certificates", https://letsencrypt.org/docs/revoking/
- Certbot Documentation, "Revoking certificates", https://eff-certbot.readthedocs.io/en/stable/using.html#revoking-certificates
- Let's Encrypt, "Rate Limits", https://letsencrypt.org/docs/rate-limits/