证书机构私钥泄露:你需不需要管?
如果你是只用浏览器刷网页、逛购物站、看视频的普通人,这篇文章你可以放心划走——你的 Chrome / Firefox / Safari 当天就自动封锁了这批坏证书,全程无感。但如果你会跑命令、写脚本、用 Docker,或者你的小程序后端要连外部接口,往下看:你的工具链很可能还信着这些被攻破的证书。先花 10 秒对号入座,再决定要不要动手。
这件事跟你有关系吗(对号入座)
一句话:看你是哪类人。
| 你属于哪类 | 这件事对你有影响吗 | 你要做什么 |
|---|---|---|
| 只用浏览器上网的普通人 | 几乎没有。四大浏览器当天自动封锁,你无感 | 什么都不用做,保持浏览器更新即可 |
| 手机 App 用户 | 取决于 App 的证书校验机制,主流 App 走系统 / 浏览器信任链,基本没事 | 把常用 App 升到最新版 |
| 会跑命令 / 写脚本 / 用 Docker 的人 | 有。curl、Python certifi、Go、Node、Docker 镜像用的是各自的 CA 包,可能还信着 | 跑一次自查(见下文),更新对应 CA 包 |
| 连印度政府 / 银行 / 企业服务的用户 | 较高。eMudhra 是印度主流 CA,相关站点可能弹证书错误 | 更新 CA 包;遇报错先查是不是 emSign 根被剔 |
看清自己那一行,再决定要不要继续往下读——这篇的核心意义就是帮你 10 秒判断”关不关我事”,而不是被安全新闻吓一轮。
> 一条铁律:无论哪一类,都不要为了消除证书报错而关闭 TLS 验证(curl -k、verify=False)。那等于把门锁拆了,会让所有中间人攻击畅通无阻。正确做法是更新 CA 包,见下文。
这件事到底发生了什么
证书机构(CA)的职责,是给网站签发”我是真站”的 TLS 证书。中间 CA 是夹在根证书和网站证书中间的一环——浏览器信任根,也就信任它签发的下级。
2026-10-17 傍晚(UTC 18:05 左右),一名安全研究员向 Chrome 根项目报告:eMudhra 有 8 张中间 CA 的私钥已经不在自己手里了。他不是猜的——他用这些私钥各自签了一条消息(”We have a problem here – Wayne”)作为证据。
更离谱的是泄露原因:这些私钥生成时随机性严重不足。正常一个 P-384 椭圆曲线私钥应该是约 384 位的随机数(可能组合接近 10¹¹⁵ 种),而研究者 Scott Helme 从公开证书里直接还原出了私钥,数值小到是 4、56、115 这种个位数/百位数。也就是说,这几把”锁”的钥匙形同虚设。
eMudhra 自称累计签发过 6000 万张以上数字证书,其中这 8 张中间证书链到 emSign 系列根证书,还有 2 张是代码签名 CA——意味着伪造的代码签名也可能出现。
为什么浏览器没事,而你的命令行有事
浏览器厂商的反应速度很快:
| 客户端 | 封锁时间 | 你是否需要操作 |
|---|---|---|
| Chrome / Android | 10-17 当天,CRLSet 按 SPKI 哈希封锁,无需更新/重启 | 基本自动 |
| Firefox | 10-17 22:59 UTC 完成 OneCRL;并发布 158.0.1 / ESR 115.43.1 / NSS 3.131.1 | 升到最新版 |
| Safari / Apple | 10-19 | 系统更新 |
| Edge / Microsoft | 10-20 | 系统更新 |
| curl / Python requests / Go / Docker 镜像 / Node | 取决于各自 CA 包是否更新 | 需要你手动处理 |
关键差别:浏览器的封锁走的是”浏览器自己的封锁列表”(CRLSet / OneCRL),跟系统 CA 包无关,所以哪怕你系统没更新,浏览器也拦得住。但 curl、Python 的 certifi、Go 的 root bundle、Docker 里的基础镜像,它们用的是操作系统或语言自带的 CA 包——这些包如果还留着 emSign 的根,就会继续信任伪造证书。
一个有名的演示:研究员用泄露密钥给 q3k.google.com 签了张假证书,用这条命令仍能建立 TLS 连接(因为 curl 走的是系统/语言 CA 包,而不是浏览器的封锁列表):
curl https://q3k.google.com --resolve 'q3k.google.com:443:135.181.235.221'
这不代表你现在就被攻击,但说明:只要你的工具还信任那几张中间证书,处在网络中间的人就能用它读或篡改你的流量。
你该怎么做:自查 + 处理
第一步:30 秒自查
打开 <https://emudhra.we-have-a-problem.com>。它会按顺序用每个受影响证书的子域去连一次,如果你的浏览器/工具还信任,就会显示”trusts”;已被封锁则显示拒绝。
命令行自查(用你自己的 curl 测,看是否还信任):
curl -v https://emudhra.we-have-a-problem.com 2>&1 | grep -iE "verify|SSL certificate|subject"
如果输出里出现证书被拒绝(verify error / self signed 之类),说明你的 curl 已经不信任了,OK。如果顺畅连上没报错,说明你的 CA 包还信着,需要更新。
第二步:逐系统处理
macOS
- 系统 CA 包:系统等 Apple 的 10-19 那批更新通常已覆盖;可用上面的自查命令确认。
- Homebrew 装的语言运行时:升级对应包,
brew upgrade后 certifi / openssl 会跟新。
Linux(Debian / Ubuntu)
Debian 把 CA 放在 ca-certificates 包。手动剔除 emSign 根:
sudo dpkg-reconfigure ca-certificates
# 选 "Ask",取消勾选以下条目:
# mozilla/emSign_ECC_Root_CA_-_C3.crt
# mozilla/emSign_ECC_Root_CA_-_G3.crt
# mozilla/emSign_Root_CA_-_C1.crt
# mozilla/emSign_Root_CA_-_G1.crt
语言运行时(最容易被漏掉的)
- Python:
pip install --upgrade certifi(2026.10.19 版已移除),或更新 certifi。 - Go:升级到 1.27.3 / 1.26.10(已修);或用
golang.org/x/crypto的最新 root bundle。 - Rust:
webpki-roots升到 1.0.10。 - Node.js:等 ca-bundle 更新(截至报道时仍在 pending),临时可手动更新 npm 的 CA 包。
Docker 镜像
基础镜像(特别是老镜像)里可能带着旧 CA 包。重新 docker pull 基础镜像、重建,或 apt-get update && apt-get upgrade -y ca-certificates。
第三步:代码签名也受影响
8 张里 2 张是代码签名 CA。如果你的环境信任 emSign 代码签名体系下签的东西(比如某些 Windows 驱动 / 软件分发),在信任库更新前,应把这些签名视为不可信。
常见疑问(FAQ)
Q:我普通上网,要慌吗?
A:基本不用。四大浏览器当天就封锁了,你正常使用、保持浏览器更新即可。真正要慌的是”用命令行和代码发请求”的场景。
Q:什么是 SPKI 哈希封锁?
A:浏览器不是按”证书名字”封,而是按”公钥指纹”封。所以哪怕攻击者用 Sectigo 交叉签名造出另一张同名证书,公钥一样也会被拦。这是为什么 Chrome 这次能”无需更新就保护”。
Q:我已经更新了系统,为什么还要管 curl?
A:因为很多编程语言自带一份 CA 包(certifi、Go bundle、Node ca-bundle),它们不随系统更新走。系统干净 ≠ 你的 Python 脚本干净。
Q:能不能直接把证书验证关了省事?
A:绝对不要。curl -k 或 requests.verify=False 等于拆除 TLS 的全部意义,会让你对所有中间人攻击敞开。正确做法是更新 CA 包。该漏洞在 CVE-2026-111943 下追踪。
Q:eMudhra 这家还有救吗?
A:Chrome 根项目已表示正在评估是否继续保留 eMudhra 其余证书,后续会在 CCADB 公共列表公布。网站运营者若证书链到 emSign ECC Root CA - G3,应在 2026-10-27 之前换到别的 PKI 体系,否则 Chrome 会拦。
写在最后
这次事件最值得普通用户记住的一句:浏览器安全 ≠ 你的工具链安全。如果你是只用浏览器的普通人,今天这篇和你无关,关掉即可;但如果你开始跑命令、写脚本、用 Docker,就花五分钟跑一次自查——这比事后排查被中间人攥着流量要便宜得多。