Summary: in October 2026 a researcher found that eight publicly trusted intermediate certificate authorities run by eMudhra, an Indian CA, had elliptic-curve private keys that were tiny integers: 4, 56, 66, 115, 155, 156, 230 and 237. A real P-384 private key is a random number around \(2^{384}\). These keys could be recovered by trying at most 255 numbers, which takes well under a second. Anyone holding one could have issued a certificate for any website, or signed software that Windows would trust. Browsers blocked the intermediates within hours. Many other clients, such as Go programs, Python's certifi, Node, curl on macOS, Java, containers and appliances, kept trusting them until they were patched. The cause was not a hack. It was a bug in a key ceremony script, two keys with similar labels, and a warning sign in May 2025 that nobody followed up. This article walks through the whole story, the maths, the defenses that worked and the ones that did not, and concrete changes for security and software engineers.
1. A story that began in 2008
The post that brought this incident to many feeds opened with an older story, and it is the right place to start. In 2006 a Debian maintainer removed two lines from OpenSSL's random number generator because the memory-checking tool Valgrind complained that they used uninitialized memory. The warning went away. So did almost all of the randomness. After the change, the only meaningful input left was the process ID, which on Linux was at most 32,768 different values. Every SSH key, every TLS key and every OpenVPN key made on an affected Debian or Ubuntu system came from a pool of roughly 32,768 possibilities per key type and size.
Debian disclosed it in May 2008 as DSA-1571, tracked as CVE-2008-0166. Attackers did not need to break any cryptography. They generated every possible key once, built a lookup table, and matched public keys against it. The lesson the industry took away was: the algorithm can be perfect and the key can still be worthless, because a key is only as strong as the randomness that made it.
There is a famous xkcd strip (number 221) where a function returns 4, "chosen by fair dice roll, guaranteed to be random". In 2008 it was a joke about Debian. In October 2026 it described a publicly trusted certificate authority almost literally: one of its private keys was the number 4.
2. What happened, in one page
- The CA. eMudhra operates a publicly trusted CA hierarchy called emSign. Its third-generation elliptic-curve hierarchy sits under
emSign ECC Root CA - G3, with TLS and code-signing roots below it. - The ceremony. On 30 April 2025 eMudhra generated 24 subordinate CA keys in one key ceremony, across series A, B and C, in both RSA-4096 and P-384, for DV, OV, EV and code-signing purposes.
- The bug. An approved deviation from the normal ceremony script was added to test key wrap and unwrap. A flaw in that code created a second key pair next to each correct one, and the second pair was weak. Because the weak and correct keys had similar labels, the weak ones were used to build the certificate signing requests (CSRs).
- The result. Eight P-384 intermediates, series B and C, ended up certified with private keys below 256. Sectigo also cross-signed all eight under its widely trusted AAA Certificate Services root in May 2025, so there were 16 certificates in total.
- The discovery. A researcher known as Wayne ran a test corpus over the CCADB (the shared database of CA certificates) on 17 October 2026 and found the keys could be recovered. He emailed Apple, Chrome, Microsoft, Mozilla and eMudhra, and proved control by signing a message with each key.
- The response. Chrome blocked the six TLS intermediates within about two hours, Mozilla within five, eMudhra revoked them the next morning, and over the following days Apple, Microsoft, Linux distributions, language runtimes and tools shipped updates. Mozilla removed trust in the G3 ECC root from NSS and Chrome scheduled its removal. eMudhra later announced it would withdraw from the global TLS certificate business.
3. The eight intermediates and their keys
The certificate names and fingerprints come from Mozilla's incident (Bugzilla 2083449). The mapping of key value to certificate comes from Keytos's write-up. BleepingComputer independently verified only the value 4 for EM OV TLS CA - G3C, so treat the rest of the mapping as reported rather than confirmed.
| Intermediate | Type | Private key (reported) | CCADB | SHA-256 fingerprint |
|---|---|---|---|---|
| EM DV TLS CA - G3B | DV TLS | 156 | A012302 | 42C4ACCD...18BA1493 |
| EM OV TLS CA - G3B | OV TLS | 155 | A012308 | 98B89662...833BC25B |
| EM EV TLS CA - G3B | EV TLS | 115 | A012304 | E7568FE6...84333838 |
| EM DV TLS CA - G3C | DV TLS | 230 | A012294 | 0164D7CE...30934D19 |
| EM OV TLS CA - G3C | OV TLS | 4 | A012300 | CB6E1516...BF9C7C3F |
| EM EV TLS CA - G3C | EV TLS | 56 | A012296 | 432EC25F...8D0261F3 |
| EM OV CS CA - G3B | code signing | 66 | A012306 | 9E39DE28...5DB067B4 |
| EM OV CS CA - G3C | code signing | 237 | A012298 | 4B2460A4...74C630B1 |
The full fingerprints, serial numbers and the eight Sectigo cross-signed counterparts are in the Bugzilla bug. Use the full values, not the shortened ones above, if you build a blocklist.
4. Why a key of 4 is no key at all: the maths
You do not need to be a cryptographer to see why this is fatal. You need one idea about elliptic curves.
4.1 Private key, public key, generator
An elliptic curve like P-384 comes with a fixed, public starting point called the generator, \(G\). There is an operation called point addition that combines two points on the curve to get a third. Adding \(G\) to itself \(d\) times is called scalar multiplication and written \(dG\).
An ECDSA key pair is just:
\[ \text{private key } d \in \{1, \dots, n-1\}, \qquad \text{public key } Q = d \cdot G \]where \(n\) is the order of the curve's group, a 384-bit number for P-384. Security rests on the elliptic curve discrete logarithm problem: given \(Q\) and \(G\), finding \(d\) is believed to be infeasible when \(d\) is a uniformly random number of that size. The best known generic attacks take about \(\sqrt{n}\) steps, roughly \(2^{192}\) for P-384, far beyond any computer that exists.
4.2 What happens when \(d\) is small
The hardness assumption only holds if \(d\) is drawn from the whole range. If \(d\) is known to be below 256, the attacker simply walks the line:
\[ G,\; 2G,\; 3G,\; 4G,\; \dots \]and compares each result with the public key \(Q\) printed in the certificate. When \(kG = Q\), the private key is \(k\). For the value 4, that is four point operations. For the worst case here, 237, it is 237 operations, each taking microseconds. The entire search space had at most 8 bits, or 256 possibilities.
Put the numbers side by side:
\[ \underbrace{2^{8}}_{\text{these keys}} \quad \text{versus} \quad \underbrace{2^{384}}_{\text{a real P-384 key}} \]The difference is a factor of \(2^{376}\). For scale, that is more than the number of atoms in the observable universe, multiplied by itself several times over. Mozilla noted that baby-step giant-step or plain brute force both work, and that third-party AI agents recovered the keys from a simple prompt. Reports said all eight were recovered in under a second.
4.3 Try it yourself, safely
The snippet below creates a deliberately weak key, then recovers it the way an attacker would, using only the public key. It uses the Python cryptography package and runs on your own key, so it is a safe lab exercise.
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
CURVE = ec.SECP384R1()
def pub_bytes(key):
return key.public_key().public_bytes(
serialization.Encoding.X962,
serialization.PublicFormat.UncompressedPoint)
# A "CA key" that is the integer 4, like EM OV TLS CA - G3C
victim = ec.derive_private_key(4, CURVE)
target = pub_bytes(victim) # this is all an attacker sees
# Attacker: try every small scalar and compare public keys
for d in range(1, 1 << 16): # 65,535 tries, still instant
if pub_bytes(ec.derive_private_key(d, CURVE)) == target:
print("recovered private key:", d)
break
On a laptop this prints recovered private key: 4 immediately. Against a real certificate, the attacker would first extract the public key from the certificate with openssl x509 -in ca.pem -noout -pubkey and compare against that.
5. What an attacker could have done
An intermediate CA is a signing key that browsers and operating systems trust because a root they trust vouches for it. Holding its private key means you can create new certificates that chain to that root.
- The six TLS intermediates could sign a certificate for any domain name, such as
yourbank.comorlogin.microsoftonline.com. Combined with a network position, for example on public Wi-Fi, a compromised router, a malicious proxy or DNS hijack, an attacker could impersonate the site to any client that trusted the chain. - The two code-signing intermediates chained to a root that Microsoft trusted for code signing, so an attacker could have signed malware that Windows would show as published by a verified company.
The window of exposure was about 17 months, from the April 2025 ceremony to the October 2026 report. Every report agrees there is no evidence the keys were abused during that time. But "no evidence" is weaker than it sounds: a targeted attack using a certificate that was never submitted to Certificate Transparency logs, against a client that does not check CT, would leave very little trace.
After disclosure, the keys became public knowledge. Keytos reported that by 21 October more than 106,000 certificates signed with these intermediates had been logged to CT, almost all for google.com, mostly research and proof-of-concept work. That flood is harmless to clients that block the intermediates, and a live demonstration of the risk to those that do not.
6. Timeline
Times are UTC, primarily from Mozilla's Bugzilla 2083449 and Keytos's reconstruction.
| When | What |
|---|---|
| 30 Apr 2025 | Key ceremony generates 24 subordinate CA keys. A wrap and unwrap test deviation produces weak duplicates; eight weak P-384 keys are used for B and C series CSRs. |
| May 2025 | Sectigo cross-signs the eight intermediates under AAA Certificate Services. CRLs for six of the TLS intermediates start failing signature verification. |
| Jun 2025 | Bugzilla 1970728 flags the invalid CRL signatures. eMudhra fixes it by re-signing the CRLs with the flawed keys. The keys themselves are not examined. |
| 17 Oct 2026, 16:27 | Wayne's test-corpus run over CCADB finds the break. |
| 17 Oct, 18:05 | Report and signed proof sent to Apple, Chrome, Microsoft, Mozilla and eMudhra. |
| 17 Oct, 19:45 | Chrome blocks the six TLS intermediates via CRLSet. |
| 17 Oct, 21:28 | eMudhra acknowledges and disables one intermediate that was live. |
| 17 Oct, 21:48 | Mozilla independently recovers the private keys. |
| 17 Oct, 22:59 | Firefox blocks the intermediates through OneCRL. |
| 18 Oct, ~09:30 | eMudhra revokes all eight with reason cACompromise. Mozilla opens the public incident. |
| 19 Oct | Sectigo revokes its cross-signs. Apple adds protections (reports differ between 19 and 22 October). |
| 20 Oct | Microsoft blocks the intermediates. Firefox 158.0.1 and ESR updates, NSS 3.131.1, Go 1.27.3 and 1.26.10 (CVE-2026-111943) ship. Mozilla removes trust in emSign ECC Root CA - G3. |
| 21 Oct | eMudhra shares fall about 20 percent on Indian exchanges (per Keytos). CT logs show 106,000+ test certificates. |
| 27 Oct (planned) | Chrome Root Store version 43, which removes the G3 ECC root, expected in Stable. |
7. Why browsers were safe and everything else was not
This incident is a clean natural experiment. The same broken chain was blocked by browsers within hours and kept working in many other places for days. The difference is how each client decides to trust a certificate.
Fig 1. Browsers stack three defenses. Many non-browser clients rely on a single static file of trusted roots.
7.1 Certificate Transparency
Chrome and Safari require publicly trusted TLS certificates to be logged in public, append-only Certificate Transparency logs, and to carry proof of that (signed certificate timestamps). Chrome stated that no TLS certificates from these intermediates had been logged before its block. So a forged certificate that an attacker kept secret would have been rejected by Chrome even before the incident was known, because it had no CT proof. To pass, the attacker would have had to log it publicly, where researchers and domain owners watching the logs could see it. This is CT doing exactly its job: it turns a silent attack into a public one.
7.2 Pushed revocation
Classic revocation is weak in practice. CRLs are big, OCSP adds latency and leaks browsing data, and many clients "soft fail", accepting a certificate if the revocation check cannot be completed. Browsers solved this with their own push channels. Chrome's CRLSet and Firefox's OneCRL deliver a small list of revoked intermediates through the browser's update service, without a full browser release. Chrome's block landed less than two hours after the report and Firefox's within five.
7.3 The static CA bundle problem
Most software outside browsers trusts certificates by reading a file of root certificates, a CA bundle. Examples include /etc/ssl/certs/ca-certificates.crt on Debian and Ubuntu, Python's certifi package, Go's system pool or embedded roots, Java's cacerts, Node's built-in root list, and the bundle that ships inside an Electron app or a Docker image. These clients usually do not require CT, often do not check revocation, and only learn about a distrust when someone updates the file.
The reported testing results show the gap clearly. In tests described by Encryption Consulting, curl with default settings, Python and Node accepted a forged test certificate on Linux and macOS. On Windows, CryptoAPI accepted the chain unless revocation checking was enabled, and even then only one of two revocation routes flagged it. Mozilla's Dennis Jackson warned that macOS's built-in /usr/bin/curl reads /etc/ssl/cert.pem, which Apple had not updated, so command-line tools such as curl, git and python3 on a Mac could still trust the chain.
emSign ECC Root CA - G3) or to add the specific intermediates to a deny list, as Go's patch did by filtering chains containing the eight SPKI hashes. Simply updating a CRL somewhere does nothing for a client that never reads CRLs.8. What got patched, and where to check
Dennis Jackson's community tracker at emudhra.we-have-a-problem.com lists patched versions. A selection, as shown on the tracker when this was written:
| Area | Patched in |
|---|---|
| Firefox / NSS | Firefox 158.0.1 and ESR updates; NSS 3.131.1 (Android profile fix in 158.0.2) |
| Go | 1.27.3 and 1.26.10 (CVE-2026-111943); programs must be rebuilt |
| Python | certifi 2026.10.19; CPython 3.15.1, 3.14.9, 3.13.17; pip 26.2.2; uv 0.13.4 |
| Node.js | 26.12.1, 24.22.1, 22.23.4 |
| Java | 27.0.1.0.2, 25.0.5.0.2, 21.0.13.0.2, 17.0.21.0.2, 11.0.33.0.2, 8u511 |
| Electron | 44.9.1, 43.8.1, 42.11.16 |
| Bun / Deno | Bun 1.4.4, Deno 2.9.8 |
| Rust | webpki-roots 1.0.10, rustls-webpki 0.103.16 |
| Debian / Ubuntu | updated ca-certificates packages for supported releases |
| Alpine / Fedora / Arch | Alpine 20261020-r0, Fedora 2026.2.92_v9.0.319, Arch 3.131.1-1 |
| curl CA bundle | 2026-10-20 edition |
| Tools | Docker Desktop 4.96.2, ArgoCD 3.3.18, Conda 26.9.4 and others |
| Still pending at the time | Bottlerocket, Composer ca-bundle, Erlang certifi, Godot |
Check the tracker itself for the latest list. Versions move quickly in the days after an incident like this.
9. For security engineers: what to do this week
9.1 Test the real runtime, not your laptop
The tracker provides test hosts that serve chains through the compromised intermediates. A certificate error is the result you want.
# Linux, macOS, inside a container: expect a certificate error
curl -sSI https://dv-g3b-emudhra.we-have-a-problem.com/
curl -sSI https://dv-g3b-aaa-emudhra.we-have-a-problem.com/
# Hosts serving certificates never logged to CT: success here means
# the client trusts the chain AND does not enforce CT
curl -sSI https://dv-g3b-noct-emudhra.we-have-a-problem.com/
# Windows PowerShell: a trust failure means you are protected
Invoke-WebRequest https://dv-g3b-emudhra.we-have-a-problem.com/ -UseBasicParsing
Run these from inside each production image, CI runner and VM, not from your workstation. The point is to test the trust store that the application actually uses. Never "fix" a failing check by turning off certificate validation.
9.2 Inventory every trust store
- OS bundles: update
ca-certificateson every server and base image. - Containers: rebuild and redeploy images. A running container keeps the bundle it was built with.
- Language-level stores: Python certifi, Java
cacerts, Node and Electron built-ins, Go binaries (rebuild with a patched Go), Rust webpki-roots. - Appliances and devices: load balancers, proxies, VPN gateways, IoT and industrial devices with embedded trust stores. Ask vendors for patches and dates.
- Windows fleets: make sure automatic root and disallowed-certificate updates are not disabled by Group Policy.
- macOS CLI tools: until Apple updates
/etc/ssl/cert.pem, point tools at an updated bundle (for example viaSSL_CERT_FILEorPIP_CERT).
9.3 Hunt for abuse
- Code signing: search endpoints for binaries signed by
EM OV CS CA - G3BorG3C. In Microsoft Defender for Endpoint, Keytos suggests a KQL query along these lines; an empty result is what you want.
DeviceFileCertificateInfo
| where Timestamp > ago(30d)
| where Issuer has "EM OV CS CA"
| summarize Devices = dcount(DeviceId), Files = dcount(SHA1) by Issuer, Signer
- TLS: if you run TLS inspection or log certificate chains at a proxy, search for any chain containing the eight intermediates' fingerprints from Bugzilla 2083449.
- Your domains in CT: monitor Certificate Transparency for certificates issued for your domains by unexpected CAs. Services such as crt.sh make this easy to automate.
- Network: Cisco Talos published Snort SIDs 67363 to 67374 for these certificates.
9.4 If you are an eMudhra customer
eMudhra estimated about 30,000 certificates needed to move from the G3 hierarchy to emSign Root CA - G1, about 97 percent of them issued through ACME. If you use ACME with automated renewal, the migration is a config change and a forced renewal. If your certificates were issued by ticket and installed by hand, plan the work now. Also note that eMudhra announced its withdrawal from the global TLS business, so you may need a new CA altogether. Binaries already signed with legitimate certificates from the affected code-signing chain can stop validating on Windows and will need re-signing.
10. For software engineers: design changes that would have helped
10.1 Validate keys, not just algorithms
Every policy here checked the algorithm name: P-384, good. Nothing checked the key. If you generate keys anywhere, in a CA, a KMS wrapper, a signing service or a test fixture, add a cheap sanity check on the private scalar before the key is used. For an EC key you control, the check is one line:
from cryptography.hazmat.primitives.asymmetric import ec
def assert_strong_ec_key(key: ec.EllipticCurvePrivateKey) -> None:
d = key.private_numbers().private_value
bits = key.curve.key_size # 384 for P-384
# A uniform random scalar has fewer than (bits - 64) bits with
# probability about 2^-64. Anything that small is a generation bug.
if d.bit_length() < bits - 64:
raise ValueError(f"weak EC private key: only {d.bit_length()} bits")
Inside an HSM you cannot read \(d\), and you should not be able to. There, the controls are procedural: generate keys only through the HSM's validated mechanism, record and verify the exact key handle used for each CSR, and have an independent witness confirm it. A test key created during a deviation should be destroyed before anything else in the ceremony continues.
10.2 Never select keys by name
The proximate cause was human: two keys with similar labels, and the wrong one was picked. This is the same class of bug as deploying to prod-db-2 instead of prod-db-1. Select keys by an immutable identifier, such as the hash of the public key, and assert it matches the value you expect at each step. Treat any duplicate or near-duplicate label in a key store as an error, not a warning.
10.3 Treat cryptographic anomalies as incidents
The strongest hint came in May 2025. CRLs from six intermediates failed signature verification. According to eMudhra, the CRLs had been signed with the correct, strong HSM keys, which did not match the weak public keys in the certificates. The fix was to re-sign the CRLs with the weak keys so the signatures would verify. In other words, the system said "these keys do not match" and the response was to use the keys that did match the broken certificates. A signature that does not verify against its own certificate is never a configuration issue. It means the key you think you are using is not the key that was certified.
10.4 Test the ceremony code like production code
The weak keys came from a one-off script change for a wrap and unwrap test. One-off code paths are where generation bugs live, because they are not exercised often and are written under time pressure. A ceremony script deserves unit tests, review, a dry run on test hardware, and a check of the output keys' properties before the real run.
10.5 Build for CA agility
- Automate certificate issuance with ACME so a forced reissue is a pipeline run, not a project.
- Do not pin to a single CA or intermediate in mobile apps or clients unless you have a tested plan to rotate pins quickly.
- Make trust stores updatable. Do not freeze a CA bundle inside a binary or device you cannot update. If you must embed one, have a signed update channel for it.
- Rebuild images on a schedule so base-image trust stores never get more than a few weeks old.
- Rehearse distrust. Run a tabletop exercise: "our CA is distrusted tomorrow; how long until every certificate and client is fixed?"
10.6 Make clients stricter by default
If you write a TLS client or a library that others use, consider what this incident showed. Requiring CT for publicly trusted certificates, consuming a pushed revocation list, or at least being able to ship a deny list quickly (as Go did with SPKI hashes) are the differences between hours and weeks of exposure. Rustls-based and Go clients got fixed by a library release; clients that trust whatever is on disk got fixed only when someone updated the disk.
11. The long history of weak keys
| Year | Incident | What went wrong |
|---|---|---|
| 2008 | Debian OpenSSL (CVE-2008-0166) | A patch to silence Valgrind removed entropy; keys came from about 32,768 possibilities based on the process ID. |
| 2010 | Sony PlayStation 3 signing key | ECDSA signatures reused the same per-signature random value, which lets anyone solve for the private key from two signatures. |
| 2012 | "Mining your Ps and Qs" | Researchers found many network devices with RSA keys that shared prime factors, because devices generated keys at first boot with almost no entropy. |
| 2017 | ROCA (CVE-2017-15361) | A key generation library in Infineon chips produced RSA keys with structure that made them factorable, affecting smart cards and identity documents. |
| 2026 | eMudhra intermediate CAs | A ceremony script bug and label confusion put scalars below 256 into publicly trusted CA certificates. |
The pattern is consistent. The algorithm was fine every time. The failure was in how a key was generated or used, and it was found by someone looking at the public artifacts, the keys and signatures everyone could see. eMudhra's keys sat in a public database for 17 months, findable by anyone who thought to check.
12. Lessons, condensed
- Randomness is the key. A key is only as strong as the process that made it. Validate output, not just inputs and labels.
- HSMs are not a guarantee. A pairwise consistency test proves a key pair matches, not that it is strong.
- Every anomaly in signatures is a key question. The invalid CRLs were the alarm that rang 16 months early.
- CT works. It is why browsers were safe before anyone knew. Clients without CT were exposed for the whole window.
- Revocation needs a push channel. CRLSet and OneCRL fixed browsers in hours. Static bundles took days to weeks.
- Your real attack surface is every trust store you ship. Containers, binaries, appliances and CLI tools all count.
- CA distrust should be a rehearsed event, not a crisis. Automation decides whether it takes an afternoon or a quarter.
13. Open questions
- How exactly did a sub-256 scalar come out of a claimed FIPS 140-2 Level 3 HSM? Mozilla requested ceremony records and module certificate numbers.
- Are the RSA and A-series keys from the same ceremony really unaffected? This was eMudhra's claim, not yet independently verified.
- Was the May 2025 CRL incident disclosed to auditors, and why did the fix not trigger a key review?
- Mozilla's thread notes about 30,800 unexpired precertificates chain to the G3 ECC root, mostly via InCommon subordinate CAs, while eMudhra said no end-entity certificates were issued from the eight affected intermediates. How those subscribers are migrated matters.
- How many appliances, devices and internal tools will keep trusting the G3 chain until 2039, when the certificates would naturally expire?
FAQ
Was eMudhra hacked?
No evidence suggests that. The keys were weak from the moment they were generated in April 2025, because of a ceremony script bug and a key selection mistake. They were "compromised" in the sense that anyone could compute them from public data, not because someone broke into eMudhra's systems.
Am I at risk if I just use Chrome or Firefox?
Very little, as long as your browser is up to date. Browsers required CT, blocked the intermediates within hours, and are removing the root. The bigger risk is software that is not a browser.
Does this affect Indian digital signatures (DSC) and eSign?
According to eMudhra and Indian officials quoted in reporting, the Indian DSC and eSign services run on separate infrastructure and are not affected. The incident concerns the emSign G3 publicly trusted TLS and code-signing hierarchy.
Why not just revoke the intermediates and stop there?
Because many clients never check revocation. They trust any chain that ends at a root in their bundle. Removing or distrusting the root, or shipping an explicit deny list, is the only fix that reaches those clients.
How can I tell if my own keys are weak?
For software-held keys, check the bit length of the private scalar (for EC) or run a weak-key scanner such as the ones used for ROCA and shared-prime checks (for RSA). For HSM-held keys, verify the generation process and the exact key handle used, because you cannot inspect the private value.
Glossary
| Term | Meaning |
|---|---|
| Intermediate CA | A CA certificate signed by a root, used to issue end-entity certificates so the root key can stay offline. |
| Cross-sign | A second certificate for the same CA key, signed by a different root, to widen trust. Here Sectigo's AAA root cross-signed all eight. |
| P-384 | A NIST elliptic curve with a 384-bit group order; private keys should be random numbers of that size. |
| Scalar | The private key \(d\) in \(Q = dG\). |
| Key ceremony | A scripted, witnessed process for generating and certifying CA keys inside HSMs. |
| HSM | Hardware security module: tamper-resistant hardware that generates and stores keys. |
| CCADB | Common CA Database, shared by root programs to track CA certificates. |
| Certificate Transparency (CT) | Public append-only logs of issued certificates; browsers require proof of logging. |
| CRLSet / OneCRL | Chrome's and Firefox's pushed lists of revoked intermediates. |
| SPKI hash | A hash of a certificate's public key info, used to identify a key regardless of which certificate carries it. |
cACompromise | The revocation reason code meaning the CA's private key is compromised. |
References
- Mozilla Bugzilla 2083449: eMudhra private key compromise of intermediate certificates The primary incident record, with fingerprints, timeline and eMudhra's root-cause statements.
- Mozilla Bugzilla 1970728: eMudhra invalid CRL signatures The missed warning sign from 2025.
- Community incident tracker and test hosts Patched versions across OSes, runtimes and tools.
- Cisco Talos: compromised eMudhra intermediate certificates Certificate list, Go CVE and Snort coverage.
- BleepingComputer: browsers block compromised eMudhra certificates Vendor timeline and the verified key of 4.
- Keytos: eMudhra CA key compromise explained Key-to-certificate mapping, test commands and remediation.
- Encryption Consulting: what the incident teaches about CA agility Ceremony details and client testing results.
- Debian DSA-1571: predictable random number generator in OpenSSL The 2008 precedent.
- xkcd 221: Random Number The comic that became a CA key.
Sourcing note: this article relies on Mozilla's public incident record first, then on Cisco Talos, BleepingComputer, Keytos and Encryption Consulting. Some details, such as the per-certificate key values and client test results, come from a single secondary source and are labeled as reported. eMudhra's root-cause account was preliminary at the time of writing.