eMudhra’s Private Key Was 4: What Breaks in Chrome

2026-10-26
Brian

Subscribe
JOIN OUR NEWSLETTER
Be the first to know. Get fresh AI/Tech updates instantly, no spam, unsubscribe anytime

Short answer: Eight eMudhra intermediate certificate authority private keys were ordinary whole numbers below 256. One of them, on EM OV TLS CA – G3C, is the number 4. Chrome already blocked those eight public keys on 17 October 2026 at 19:45 UTC. Separately, on the morning of 27 October 2026 Pacific time, Chrome stops trusting the parent root, emSign ECC Root CA – G3. Honest sites that still chain only to that root will fail in Chrome even though their own keys were never the weak ones.

Hold this one picture: a signature proves possession of a number. If the number is 4, possession is free. The padlock cannot see that. You can.

Everything below was checked on 26 October 2026 against Google’s Chrome Security post of 20 October, Scott Helme’s write-up of the same day, Mozilla bug 2083449, CaptainDNS’s report of eMudhra’s Mozilla-ticket note, Certkit’s Certificate Transparency count, and eMudhra’s own status page. On this box the eight d values were recovered from the public certificates in under a second, and the OpenSSL chain check was run against live hosts.

What an eMudhra private key is, and why 4 is enough

Mind map of the eMudhra private key incident: d under 256, eight intermediates, Sectigo cross-sign, Chrome CRLSet then root drop, openssl chain check

A certificate authority (CA) is a firm browsers have agreed to trust as a stamper of website names. eMudhra is an Indian company that held that role for TLS (the protocol under HTTPS) through its emSign brand. An intermediate CA is a stamp that sits between a root (already baked into browsers) and a website certificate. The private key of that intermediate is the secret that makes new stamps. If the secret is public, anyone can stamp any name.

A key pair is two numbers that belong together: a public key you may show everyone, and a private key (cryptographers call it d) that must stay secret. Signing is possible only for whoever holds d. Anyone can check the stamp. Almost no one should be able to make a new one.

These eight keys used elliptic-curve cryptography on the P-384 curve. A normal P-384 private key is a random 384-bit number: about 2^384 possibilities, a 116-digit whole number. Guessing is not a plan. eMudhra’s eight secrets were not that. They were 47 bytes of zeros and then one byte. A byte has 256 possible values. The search is: compute 1 times the curve’s starting point, then 2 times, then 3 times, and stop when the public key on the certificate matches. At most 255 tries.

Nothing on the certificate looks broken. A public key made from d = 4 is a perfectly valid point on the curve. The format checks pass. The signature from the parent passes. The only thing wrong is that the secret is a number a person can say out loud.

The eight secrets, recovered on this box

Why an eMudhra private key of d equals 4 is guessable: try 1 through 255 times the P-384 base point until the public key matches

Scott Helme published the eight values on 20 October 2026 after recovering them from the public certificates on a laptop in under a second. The same recovery was re-run on this box on 26 October 2026 against the certificates listed in Mozilla bug 2083449 (SHA-256 fingerprints from that ticket, fetched from crt.sh). The script tries d = 1..255 on P-384 and stops when the public point matches. Results:

IntermediateJobSecret number dTime on this box
EM DV TLS CA – G3BWebsite15621.8 ms
EM DV TLS CA – G3CWebsite23032.5 ms
EM EV TLS CA – G3BWebsite11516.0 ms
EM EV TLS CA – G3CWebsite5612.7 ms
EM OV TLS CA – G3BWebsite15528.0 ms
EM OV TLS CA – G3CWebsite40.6 ms
EM OV CS CA – G3BCode signing669.4 ms
EM OV CS CA – G3CCode signing23733.4 ms

The letters DV, OV and EV are levels of identity check the authority claimed to do before issuing (domain-validated, organization-validated, extended-validated). Those labels do not matter here. The stamp was public either way. The two CS rows are code-signing intermediates trusted by Microsoft’s list, not the website padlock.

The tiny Python that produced the times above is this (Python 3.13.5, cryptography 43.0.0, OpenSSL 3.5.7, Asia/Calcutta, 26 October 2026). It takes a PEM certificate path as its only argument:

# Recover a tiny P-384 private key from a public certificate by trying d = 1..255
# Run on this box 26 October 2026: Python 3.13.5, cryptography 43.0.0
import sys, time
from cryptography import x509
from cryptography.hazmat.primitives.asymmetric import ec

cert = x509.load_pem_x509_certificate(open(sys.argv[1], "rb").read())
target = cert.public_key().public_numbers()
start = time.perf_counter()
for d in range(1, 256):
    guess = ec.derive_private_key(d, ec.SECP384R1()).public_key().public_numbers()
    if (guess.x, guess.y) == (target.x, target.y):
        ms = (time.perf_counter() - start) * 1000
        print(f"{cert.subject.rfc4514_string()}")
        print(f"  d = {d}  (found after {d} tries, {ms:.1f} ms)")
        break
else:
    print("not in 1..255 - a normal, strong key")

A strong P-384 public key from the same library on the same box is not found in 1..255; the script prints “not in 1..255 – a normal, strong key” and stops. That is the expected result for a correctly generated key.

Why a signing key is worse than a website key

TLS chain of trust: root signs intermediate, intermediate signs site; a weak intermediate private key lets anyone mint a new site certificate

A website’s own private key, if stolen, lets an attacker impersonate that one name. An intermediate is the stamp, not the letter. If the intermediate’s private key is public, the holder can sign a fresh certificate for any name they want: a bank, a university, google.com. The browser will follow the chain up to the root and say yes, unless some later check says no.

There is a second copy of the problem. Sectigo cross-signed these same public keys in May 2025 (Helme; Mozilla lists the eight Sectigo SHA-256 fingerprints in bug 2083449). A cross-signature means eight secrets and sixteen certificates. Blocking one copy is not enough. Google blocked by the Subject Public Key Info (SPKI) hash itself, which covers both copies. That is why Chrome’s CRLSet update did not need a browser restart.

It was not a burglary

A hack, in the ordinary sense, is someone breaking into a network and copying a secret. That is not what eMudhra says happened, and nothing in Google’s or Helme’s write-ups describes a stolen database.

The keys were born in a key ceremony on 30 April 2025. eMudhra’s account on Mozilla bug 2083449 (Naveen Kumar ML, comment 11) is that the keys were created inside Ultimaco HSMs (FIPS 140-2 Level 3), that an approved wrap/unwrap deviation for export to US and European data centers produced a second, weaker set of keys beside the strong ones, that the labels looked alike, and that staff used the weak set when they asked the root to sign the intermediates and when they sent CSRs to Sectigo for cross-signing. So the strong keys may still be sitting in the box. The keys the world was told to trust were the weak twins.

eMudhra says the root’s own private key was not in this set, that its infrastructure was not breached, and that its India-regulated Digital Signature Certificate (DSC) and eSign services run on a different system. India’s Ministry of Electronics and Information Technology (MeitY) has said the same about those regulated services. Those are their statements, not an audit of their network. Mozilla and Chrome are still pressing for the full ceremony script, and as of 26 October 2026 the full root-cause report is still pending inside the CCADB 14-day window.

Two claims line up with a public record. eMudhra says the eight intermediates never issued an end-entity certificate (a certificate for a final name that is not itself allowed to sign other certificates). Google checked Certificate Transparency logs before the block and said no TLS certificate chaining to the six website intermediates was there. Certificate Transparency is a public, append-only list of certificates. Chrome requires it by default. A forged certificate that was never logged could not have been accepted by Chrome even before the block.

That is a real limit on the scare for browsers. It is not a limit on the key. Anyone can still mint a certificate. Browsers that demand the public log, and that have the block, refuse it. Programs that do neither will accept it.

Your browser and your Python script are having two different days

This is the loop that most headlines skip. “Browsers are safe” and “the key still works” are both true. They are true for different programs.

A client deciding whether to trust a certificate can apply three separate tests:

  1. Is the chain rooted in my trust list?
  2. Revocation: did I actually go and read a published “stop believing this certificate” statement?
  3. Certificate Transparency: does this certificate appear in the public log, and do I refuse it if it does not?

Updated Chrome, Firefox and Safari do all three for public websites, or an equivalent of them. On 17 October Chrome shipped the revocation as a CRLSet update (Chrome’s packaged list of blocked keys) at 19:45 UTC, about 100 minutes after the report arrived at 18:05 UTC. Firefox followed the same evening via OneCRL. Mozilla also removed the parent root from Firefox’s trust store on 20 October.

Most non-browser TLS clients do one of the three. They trust a file of roots on disk. They do not check revocation unless you turn that on. They do not check Certificate Transparency at all.

Helme tested this on his own machines, against a local server, with a certificate he made for the name api.stripe.com. With default settings, curl said the certificate verified, Python completed the handshake, and Node reported authorized. That was on the Linux and macOS machines he tried. Windows accepted the chain too, unless revocation checking was switched on. He did not break into Stripe. He stood up his own server and presented a forged ID for Stripe’s name. A program that does not check revocation or the public log believed the ID.

The missing piece, if you are picturing someone becoming Stripe from a kitchen table, is a man in the middle: a person or machine sitting on the path between the client and the real server, able to hand over a different certificate. The key does not let an attacker read traffic from across the internet by magic. It lets them impersonate a name to any client that still trusts the stamp and that they can get to connect to them. On a cafe network, a compromised router, or a piece of software tricked into the wrong address, that is enough. On an updated browser that enforces the log, it is not.

There is a long tail past browsers. Helme notes the certificates run until July 2039. A device that baked the root in at the factory and never checks revocation will keep accepting a forgery until that date. Nobody has a census of those devices. Do not invent one.

What actually breaks on 27 October 2026 is the honest certificates

What to check before 27 October 2026: openssl chain for emSign ECC Root CA - G3, replace the certificate, update certifi and CA bundles

Hold the two events apart.

WhenWhat changedWho feels it
17 October 2026, 19:45 UTCChrome blocked the eight weak intermediate keys by SPKIForged certificates using those keys, in Chrome
17 October, later that eveningFirefox blocked the same keys via OneCRLSame, in Firefox
20 OctoberFirefox removed the parent root from its trust storeHonest sites that only chain to that root, in Firefox
Morning of 27 October 2026, Pacific timeChrome Root Store removal of emSign ECC Root CA – G3 reaches devicesHonest sites that only chain to that root, in Chrome

The 27 October break is not “hackers turned the weak key against you at dawn.” It is the opposite. Google is pulling the parent so that even a client which does not read the revocation list will stop trusting anything under it. Honest certificates come down with the parent.

Google’s instruction to site owners is direct: if your certificate chains to emSign ECC Root CA – G3, get a new one from a different hierarchy that is in the Chrome Root Store, and install it before that morning.

eMudhra said on 22 October that it is leaving the global TLS certificate business (about 1 percent of its revenue, per its press release). A replacement promise with no date is not a plan for 27 October morning. If your automatic renewal still points at eMudhra, the next renewal will ask a company that is winding the service down.

One secondary count is worth knowing and worth not over-trusting. In the Mozilla ticket on 20 October, eMudhra estimated about 30,000 certificates need to move, and that about 97 percent of them were obtained through ACME (the automatic protocol tools such as Certbot use). Certkit, reviewing Certificate Transparency, wrote that Chrome’s picture of unexpired certificates under this root was about 30,800, and that almost all of them belong to InCommon (the certificate service Internet2 runs for US universities and research groups). The leaf certificate may not say eMudhra on it. It may say Internet2 or InCommon. The root at the top is still the one Chrome is removing. That count was not re-run on this box. The check below does not need it.

The check, from zero: which chain does a site serve?

You need a domain name and a terminal with OpenSSL. This prints the names on the certificates the server sends. s: is the subject (the name on that card). i: is the issuer (who signed it).

echo | openssl s_client -showcerts -connect YOURDOMAIN:443 -servername YOURDOMAIN 2>/dev/null \
  | openssl x509 -noout -issuer -subject

That first command shows only the leaf (the website’s own card). The parent is the thing that breaks. Ask for every certificate in the chain:

echo | openssl s_client -showcerts -connect YOURDOMAIN:443 -servername YOURDOMAIN 2>/dev/null \
  | awk '/s:|i:/{print}' 

If any line contains emSign ECC Root CA - G3, or an issuer like EM DV TLS, EM OV TLS or EM EV TLS with G3 in the name, replace the certificate today. Install the new certificate and the chain the new authority gives you, reload the web server, and run the command again. The old root should be gone.

On this box on 26 October 2026 the same commands were run against a few public hosts. www.umn.edu, umich.edu, www.cmu.edu, ucsd.edu and www.washington.edu (names Certkit had flagged as heavy InCommon users earlier in the week) all returned non-eMudhra chains: Let’s Encrypt, Google Trust Services, or InCommon RSA under USERTrust / Sectigo R46. reposquare.com returned Let’s Encrypt. That is a spot check of five names, not a census of 30,000 certificates. If your inventory still points at eMudhra or InCommon ECC G3, do not take comfort from someone else’s hostname.

Then look at the machine that talks to other machines, not only the machine that serves your site.

  • A browser update does not rewrite the trust file inside a server, a container image, or a language runtime (Python, Node, Go).
  • If the app vendors a bundle (ships its own copy of the trust list, often through a package such as certifi), update that package and redeploy. On this box, certifi 2026.7.22 still contains emSign ECC Root CA - G3; certifi 2026.10.18 and later do not. The copy baked into last month’s image is still last month’s copy.
  • Turn revocation on for any client that can sit on an untrusted network and that does not enforce Certificate Transparency. Helme’s Stripe-name test is exactly the default-off case.
  • Code-signing keys 66 and 237 are a different door. If you accept signed software from these intermediates, that is Microsoft’s trust list and your own policy, not the website padlock.

Related reading on this site: Updating WordPress does not close PHP2Shell is a different stack with the same shape of mistake (updating the wrong layer). How Do I Know If My VPS Is Secure? is the practical audit checklist for the host that is serving the certificate. Did Moonshot Actually Make Kimi Worse at Hacking? is another case where the public numbers only make sense once you know what was measured.

What this is not

It is not PHP2Shell, the PHP bug that took sites offline earlier this month. Different software, different fix. Updating PHP does nothing for this, and replacing a certificate does nothing for PHP.

It is not evidence that a particular bank or university was impersonated. Google’s check says no forged website certificate under the six weak intermediates was in the public log before the block. Logs do not see certificates that were never submitted. Absence from the log is strong for browsers and weak for everything else.

It is not a reason to stop using HTTPS. The system worked in the boring way: the public key was public, someone tried the small numbers, the browsers shipped a block in hours. The failure was a procedure that published a secret of 4 and a lot of software that never asks for the revocation list.

On 20–21 October, researchers logged proof-of-concept certificates for names such as google.com signed with the recovered keys (Mozilla bug 2083449, comment 44, citing about 106,050 google.com SANs in e-Szignó CT logs). Updated browsers still reject those certificates, because the intermediate is revoked and, in Chrome’s case, because a certificate missing from a usable public log was never going to pass. The mechanism is real. The “100,000 hobbyist google.com certs” figure circulating on social posts is not treated as a primary fact here; the Bugzilla-cited count is.

The whole thing, once more, in one pass

A browser trusts a few hundred roots. Those roots sign intermediates. Intermediates sign websites. The private key on an intermediate is supposed to be a random number so large that the public key does not reveal it. eMudhra’s eight intermediates, created 30 April 2025 and cross-signed by Sectigo, had private keys 4, 56, 66, 115, 155, 156, 230 and 237. The math accepts that. The trust model does not.

Browsers that check the public log were never going to honor a quiet forgery, and since 17 October they refuse these keys outright. Programs that only check “is the root in my file?” will still believe a forgery if someone can sit on the connection, potentially until July 2039. Separately, on the morning of 27 October 2026 Pacific time, Chrome drops the parent root, and honest certificates still hanging from emSign ECC Root CA – G3 go with it.

The lesson is smaller than the headlines and more useful. A signature proves possession of a number. If the number is 4, possession is free. The padlock cannot see that. You can.

Common questions about eMudhra’s weak keys

Does Chrome already reject forged certificates from these keys?

Yes for updated Chrome. The CRLSet update of 17 October 2026 at 19:45 UTC blocks the eight public keys by SPKI hash, so both the eMudhra-issued and Sectigo-cross-signed copies are covered. Chrome also enforces Certificate Transparency by default, and Google reported no TLS certificate chaining to the six website intermediates in CT before the block.

Will my honest certificate break on 27 October 2026?

Only if it still chains to emSign ECC Root CA – G3. Run the OpenSSL chain command above. If the chain shows that root, or an EM * TLS * G3 intermediate, replace the certificate from a different hierarchy in the Chrome Root Store before the morning of 27 October 2026 Pacific time.

Are eMudhra’s India DSC and eSign services affected?

eMudhra and MeitY both say no: those regulated services run on separate infrastructure. That claim is attributed, not audited here. The exit announced on 22 October is from the global TLS certificate business.

Is updating certifi enough for my Python clients?

It helps for the root-removal half. certifi 2026.10.18 and later no longer ship emSign ECC Root CA – G3; 2026.7.22 still does. Revocation of the eight intermediates is a separate question: default Python TLS clients still do not check CRLs or OCSP unless you turn that on, so a forged leaf under a still-trusted root can pass even after certifi is current. Update the bundle and prefer clients that enforce CT or check revocation on untrusted networks.

JOIN OUR NEWSLETTER
Be the first to know. Get fresh AI/Tech updates instantly, no spam, unsubscribe anytime

Leave a comment