Eight Bits of Trust: eMudhra's CA keys cracked in milliseconds

本文为原文前 6,000 字符的节选翻译,完整内容请查看原文。

Eight Bits of Trust: eMudhra’s CA keys cracked in milliseconds

eMudhra 的其中一个证书颁发机构私钥竟然就是数字 4。

Not a number that starts with 4, or the number 4 followed by a few hundred random digits, just, 4… Another one is 56, and another is 115. I know, because I recovered all of them from their public certificates on my laptop just now, and it took less than a second.

它不是以 4 开头的数字,也不是 4 后面跟着几百个随机数字,它就是 4…… 另一个私钥是 56,还有一个是 115。我知道这一点,因为我刚才在笔记本电脑上从它们的公钥证书中恢复了所有这些私钥,整个过程不到一秒钟。

On Saturday 17th October a security researcher reported to Apple, Google, Microsoft, Mozilla and eMudhra that the private keys for eight eMudhra intermediate certificates were compromised. Chrome pushed a CRLSet update blocking them that evening and Mozilla blocked them in Firefox via OneCRL a few hours later. On Tuesday 20th, Mozilla announced it publicly and shipped an NSS update removing the eMudhra root, and Chrome confirmed the root is going in Chrome Root Store v43.

10 月 17 日星期六,一位安全研究人员向苹果、谷歌、微软、Mozilla 和 eMudhra 报告称,八个 eMudhra 中间证书的私钥已被泄露。Chrome 当晚推送了 CRLSet 更新以阻止这些证书,Mozilla 也在几小时后通过 OneCRL 在 Firefox 中阻止了它们。10 月 20 日星期二,Mozilla 公开发布了这一消息,并发布了移除 eMudhra 根证书的 NSS 更新,Chrome 也确认该根证书将被从 Chrome 根证书库 v43 中移除。

The eight intermediates are six TLS issuing CAs (DV, OV and EV, two generations each) and two code-signing CAs, all created in April 2025. Every one of them was also cross-signed by Sectigo’s AAA Certificate Services root in May 2025.

这八个中间证书包括六个 TLS 颁发 CA(DV、OV 和 EV 类型,每种两代)以及两个代码签名 CA,它们均创建于 2025 年 4 月。每一个证书还在 2025 年 5 月被 Sectigo 的 AAA Certificate Services 根证书交叉签名。

That’s the “what”, but it’s the “how” that’s the interesting part, and it was summed up in one line on the thread by Ian Carroll:

以上是“发生了什么”,但“如何发生的”才是最有趣的部分,Ian Carroll 在讨论帖中用一句话总结了这一点:

These are elliptic-curve keys on the P-384 curve. The private key is just a number, d. The public key, the thing that goes in the certificate for the world to see, is d × G, where G is a fixed point on the curve that everyone uses and ”×” means adding G to itself d times using the curve’s special arithmetic.

这些是基于 P-384 曲线的椭圆曲线密钥。私钥只是一个数字 d。公钥(即证书中公开可见的部分)是 d × G,其中 G 是曲线上每个人都在使用的固定点,“×”表示使用曲线的特殊算术将 G 自身相加 d 次。

Going forwards is easy, but going backwards, from the public key to d, is considered to be impractical. That’s the entire security model, and it only holds if d is enormous. A P-384 private key should be a random 384-bit number, which gives you 2³⁸⁴ possibilities (or roughly 10¹¹⁵), so nobody is ever going to search that.

正向计算很容易,但反向计算(从公钥推导出 d)被认为是不可行的。这就是整个安全模型的基础,且仅在 d 非常巨大时才成立。一个 P-384 私钥应该是一个 384 位的随机数,这会产生 2³⁸⁴ 种可能性(大约 10¹¹⁵),因此没有人能够通过搜索找到它。

eMudhra’s keys look like this:

eMudhra 的密钥看起来是这样的:

A P-384 private key should look like this:

一个 P-384 私钥应该看起来是这样的:

That’s 47 bytes of zeros and then one byte, and all eight keys are like that. A single byte has 256 possible values, so the “search” is: compute 1 × G, 2 × G, 3 × G, and stop when it matches the certificate, which is at most 255 steps.

那是 47 个字节的零加上一个字节,所有八个密钥都是如此。单个字节有 256 种可能的值,所以“搜索”过程就是:计算 1 × G、2 × G、3 × G,直到匹配证书为止,最多只需 255 步。

So the whole thing, every certificate those CAs could ever issue, every client that trusted them, rested on eight bits.

因此,整个系统——这些 CA 可能颁发的每一份证书,以及每一个信任它们的客户端——都仅仅建立在八位(bit)的安全性之上。

Mozilla attached the affected certificates to their announcement, so I pulled all 16 (8 keys, each used in two issued certificates: once by eMudhra and once by Sectigo) and brute-forced them. Every single one fell over instantly, the six TLS values, and the two code-signing keys are just as weak:

Mozilla 在公告中附上了受影响的证书,所以我提取了全部 16 个证书(8 个密钥,每个密钥用于两个已颁发的证书:一个由 eMudhra 颁发,一个由 Sectigo 颁发)并进行了暴力破解。每一个证书都瞬间被破解,那六个 TLS 证书和两个代码签名密钥同样脆弱:

It’s interesting that nothing about these certificates looks wrong. A public key derived from d = 4 is a perfectly valid point on the curve, the encoding is fine, the curve is fine, every structural check passes. The only way to find out is to try.

有趣的是,这些证书看起来没有任何异常。由 d = 4 推导出的公钥是曲线上一个完全有效的点,编码没问题,曲线也没问题,所有的结构检查都能通过。唯一的发现方法就是去尝试破解。

Normally when a CA key is compromised, someone stole it! There’s a thief, there’s a moment it happened, and you can at least reason about who now has access to that key.

通常情况下,当 CA 密钥被泄露时,意味着有人偷了它!会有窃贼,会有发生的时间点,你至少可以推断出谁现在拥有该密钥的访问权限。

Here, nobody had to steal anything. The key was effectively public from the day the certificate existed. Anyone who looked at one of these certificates, at any point since April 2025, could have recovered the key in milliseconds on commodity hardware. That’s a 17 month window and there is no way to know whether someone did.

在这里,根本不需要偷窃。从证书存在的那一天起,密钥实际上就是公开的。自 2025 年 4 月以来的任何时候,任何查看过这些证书的人,都可以在普通硬件上以毫秒级的速度恢复出密钥。这是一个长达 17 个月的窗口期,且无法得知是否有人已经利用了这一点。

Chrome made the point that because Chrome enforces Certificate Transparency, and no TLS certificates chaining to these CAs ever showed up in CT, no forged certificate could have been trusted by default in Chrome. That’s true and it’s reassuring for browsers. CT detects mis-issuance though, it doesn’t prevent it, and a lot of software doesn’t check CT at all.

Chrome 指出,由于 Chrome 强制执行证书透明度(CT),且没有任何链接到这些 CA 的 TLS 证书出现在 CT 中,因此 Chrome 默认不会信任任何伪造证书。这确实属实,也让浏览器用户感到安心。然而,CT 只能检测到错误颁发,并不能阻止它,而且许多软件根本不检查 CT。

Mainstream and updated browsers are likely absolutely fine. Chrome and Firefox block the intermediates directly and both require CT, and Safari requires CT too.

主流且已更新的浏览器很可能是绝对安全的。Chrome 和 Firefox 直接阻止了这些中间证书,且两者都要求 CT,Safari 也同样要求 CT。

Everything else is a different story, though. Most non-browser TLS clients (so basically everything else, with default settings), things like curl, Python, Node, Go, Java, git, package managers and every script and daemon you’ve got, do three things that matter here: they trust a CA bundle on disk, they don’t check revocation by default, and they don’t check CT. So the fact that eMudhra and Sectigo have revoked these intermediates doesn’t help them at all. This is something that I find often when talking about TLS and PKI, understanding just how massive the client ecosystem is can be overlooked. We often focus on this in training when we look at modern solutions for revocation like CRLite, which works wonders on the desktop browsers, but does nothing for any other TLS client. Consider what needs its root store updating now, and this is just the tip of the iceberg:

然而,其他一切则完全是另一回事。大多数非浏览器 TLS 客户端(基本上是其他所有使用默认设置的程序),如 curl、Python、Node、Go、Java、git、包管理器以及你拥有的每一个脚本和守护进程,在这一点上都有三个共同点:它们信任磁盘上的 CA 捆绑包,默认不检查吊销状态,也不检查 CT。因此,eMudhra 和 Sectigo 吊销了这些中间证书的事实对它们毫无帮助。在讨论 TLS 和 PKI 时,我经常发现人们容易忽视客户端生态系统的庞大程度。我们在培训中讨论 CRLite 等现代吊销解决方案时经常关注这一点,它在桌面浏览器上效果显著,但对其他任何 TLS 客户端都毫无作用。想想现在有哪些东西需要更新其根证书库,这仅仅是冰山一角:

I tested this on my own machines using a local server and a certificate for api.stripe.com, a name that we can all likely agree is very high value. With default settings, curl said SSL certificate verify ok, Python completed the handshake, and Node said authorized: true. That was true on every Linux and macOS machine I tested. On Windows, CryptoAPI accepted the chain unless revocation checking was switched on, and even then only one of the two routes came back as revoked.

我在自己的机器上使用本地服务器和一个 api.stripe.com 的证书进行了测试,我们可能都同意这是一个非常有价值的域名。在默认设置下,curl 显示 SSL 证书验证通过,Python 完成了握手,Node 显示 authorized: true。在我测试的每一台 Linux 和 macOS 机器上都是如此。在 Windows 上,除非开启了吊销检查,否则 CryptoAPI 会接受该证书链,即便开启了检查,两条路径中也只有一条返回了已吊销的结果。

You can put any other hostname you want in that certificate and you have everything you need to intercept that device’s traffic, all you have to do is get on the network path.

你可以在该证书中填入任何你想要的域名,你就拥有了拦截该设备流量所需的一切,你唯一需要做的就是进入网络路径。

It’s fortunate that the steps required here aren’t particularly complicated for the devices you can update, and the advice essentially boils down to ‘update them’. The problem is the devices you can’t update or update easily.

幸运的是,对于可以更新的设备,所需的步骤并不复杂,建议归根结底就是“更新它们”。问题在于那些无法更新或难以更新的设备。

Eight bits. For 17 whole months, that’s all that stood between a huge amount of non-browser software and a forged certificate for any site blowing the security on all of your encrypted traffic.

八位。整整 17 个月,这就是大量非浏览器软件与任何网站的伪造证书之间的唯一屏障,而这足以摧毁你所有加密流量的安全性。