# eMudhra CA compromise: eight private keys, and one of them is 4

eMudhra generated eight intermediate CA private keys so weakly that all were under 256 and one was 4, allowing forged certificates for any domain.

- Payout: Research
- Severity: critical
- Program: eMudhra
- Write-up by: Aikido Security
- Disclosed: 2026-10-22
- Write-up quality: 7/10
- Original: https://www.aikido.dev/blog/emudhra-ca-compromise
- Library page: https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-emudhra-ca-compromise
- Tags: area:cloud domain:infra impact:data-leak impact:integrity kind:research platform:threat-intel sev:critical tech:curl tech:docker technique:source-review vuln:crypto vuln:misconfiguration

**Target:** Intermediate CA signing certificates chaining to emSign ECC Root CA - G3
**Root cause:** eMudhra generated intermediate CA private keys incorrectly, producing values below 256 (one equal to 4) instead of ~10^115-range secrets, likely via a type-cast/truncation bug. Keys are recoverable from the public certificates.
**Steps:**
1. Obtain the eight eMudhra intermediate CA certificates (public, dated April 2025)
2. Brute force the private key over the range 0-255 for each certificate
3. Sign an arbitrary message with each recovered key to confirm (Wayne signed `We have a problem here`)
4. Use a recovered intermediate key to sign a certificate for any target domain
5. Present the forged chain to a client that trusts the intermediate and does not enforce revocation/CT
6. Verify trust with `curl -sS -o /dev/null -w "HTTP %{http_code}\n" https://dv-g3b-emudhra.we-have-a-problem.com/` — HTTP 200 means still trusted, HTTP 000 means fixed
**How found:** Researcher Wayne discovered the keys were recoverable from the public certificates and proved compromise by signing the message 'We have a problem here' with each of the eight keys, then reported to root program teams. Analysis suggests a type-cast/truncation bug (large random number cast to a byte, or old Go decimal conversion truncating to one byte).
**Exploitation:** Attacker recovers an intermediate private key by trying at most 256 values, then signs a certificate for any domain. Requires a network position (hostile Wi-Fi, compromised router) to intercept traffic. Clients enforcing certificate transparency (Firefox, Chrome, Edge, Safari) could not be attacked since the intermediates had no CT entries; non-CT-enforcing clients (curl, git, language runtimes, containers, IoT) could be impersonated. Two of the eight were Microsoft-trusted code-signing CAs, enabling malware signed under any publisher name.
**Escalation:** Impact widened beyond browsers to CLI tools, container images, bundled language runtimes (Go, Java, Node.js, certifi, webpki-roots), IoT firmware and code signing, since these never check revocation and only a CA bundle update removes trust.
**Insight:** When auditing CA/key generation, check whether key material is recoverable from the public certificate — e.g. test small-integer keys and look for truncation/casting bugs in the generation code path; a key space of 256 is brute-forceable instantly. Also note that revocation is not honored by CLI tools, containers and bundled runtimes, so a CA compromise persists there until the trust store is rebuilt.
