P.K. SHARMA

Cyber security intelligence, AI governance, practitioner analysis

eMudhra P-384 intermediate CAs collapse to weak private keys (22 Oct 2026)

A catastrophic ceremony flaw in eMudhra's emSign PKI generated eight P-384 intermediate CAs with near-zero entropy private keys, leaving scalar d values as low as 4. Anyone can derive the private keys in microseconds to mint trusted TLS certificates. Chrome and Mozilla pushed emergency blocks.

By Parminder Kumar Sharma · · 8 min read

Conceptual visualization of global Web PKI digital certificate infrastructure and cryptographic trust chains fracturing with delicate glowing light.

eMudhra P-384 entropy collapse: single-digit private keys and Web PKI revocation

A catastrophic cryptographic failure in the public key infrastructure of eMudhra (operating under the emSign brand) resulted in the compromise of eight intermediate Certificate Authority (CA) private keys. Disclosed on 17 October 2026 after independent vulnerability research, the incident stems from a key generation ceremony on 30 April 2025 in which an automated key wrap and unwrap scripting flaw generated secondary elliptic-curve private keys with near-zero entropy. Instead of 384 bits of cryptographic randomness, the private scalars (d) on the NIST P-384 curve evaluated to small integers, including single- and double-digit values such as 4, 56, and 66.

Because the private scalar was smaller than 256, solving the Elliptic Curve Discrete Logarithm Problem (ECDLP) required no supercomputers or mathematical breakthroughs: any observer could compute the private key directly from the public certificate in under 20 microseconds using basic point addition. Six of the compromised intermediates were cross-signed by emSign ECC Root CA - G3 for public TLS/HTTPS issuance, empowering anyone with the derived keys to mint globally trusted certificates for any domain on the internet. Two additional intermediates were authorized for code signing.

What this establishes from the official record. The flawed keys existed in public certificate repositories for 535 days (17.58 months, derived) and passed through two independent annual WebTrust and ETSI compliance audits without detection. Google Chrome blocked the intermediate Subject Public Key Info (SPKI) hashes via an emergency CRLSet push on 17 October at 19:45 UTC, while Mozilla deployed OneCRL blocks, shipped Firefox 158.0.1, 158.0.2, and ESR updates, and completely removed the emSign ECC Root CA - G3 from the Network Security Services (NSS) root store. What this does not establish. While Google confirmed that zero fraudulent certificates chaining to these intermediates were ever logged to public Certificate Transparency (CT) logs, CT enforcement applies primarily to public browsers. Non-public enterprise environments, internal corporate domains, and non-browser clients (such as API services, Java runtimes, and command-line utilities) do not enforce CT and remained exposed to silent Man-in-the-Middle (MitM) interception.

Cryptographic breakdown: the P-384 discrete log collapse

The security of the NIST P-384 elliptic curve (secp384r1) rests entirely on the intractability of the Elliptic Curve Discrete Logarithm Problem over a prime field. In standard operations, private keys are generated by drawing a uniformly random integer d from the interval [1, n-1]:

Technical cryptographic diagram illustrating the NIST P-384 key generation ceremony failure, showing how a wrap-unwrap defect reduced private scalar entropy from 384 bits to single-digit integers.
Mathematical breakdown of the eMudhra key ceremony entropy collapse: from 384-bit theoretical security to instant scalar derivation.

Under the NIST specification, the curve order n contains approximately 3.940 x 10^115 possible values (2^384). The most efficient general algorithm known for solving the discrete log on an elliptic curve, Pollard's rho method, has a computational complexity of O(sqrt(n)), demanding approximately 2^192 (6.277 x 10^57) point additions (derived). This provides a security margin that cannot be breached by classical computing resources.

During the 30 April 2025 ceremony conducted by eMudhra BV and eMudhra Inc, an automated key wrapping script malfunctioned during export from the generation environment. Instead of random bytes, the private scalar register was populated by sequential index counter values. For an intermediate certificate with public key Q = d * G where d = 4, an attacker simply calculates: G + G + G + G = 4*G. When the result matches the public point coordinates (x, y) published in the certificate, the private key is recovered. On standard hardware executing 250,000 elliptic curve point additions per second, recovering d = 4 takes 16.00 microseconds (0.016 milliseconds, derived). Even for d = 256, complete brute-force recovery completes in 1.024 milliseconds.

Web PKI blast radius: eight compromised intermediate CAs

The compromise affected eight intermediate certificates issued under eMudhra's global trust operations. The certificates were divided into six general-purpose TLS issuing authorities and two code-signing authorities:

Compromised eMudhra intermediate CAs, operational roles, and revocation vectors

Intermediate CA Common NameIssuing Root AuthorityDesignated PKI RoleObserved Scalar / Status
emSign ECC TLS Intermediate CA 1emSign ECC Root CA - G3Public TLS / HTTPS Wildcard Issuanced = 4 (Revoked via CRLSet / OneCRL)
emSign ECC TLS Intermediate CA 2emSign ECC Root CA - G3Public TLS / HTTPS Wildcard Issuanced = 56 (Revoked via CRLSet / OneCRL)
emSign ECC TLS Intermediate CA 3emSign ECC Root CA - G3Public TLS / HTTPS Wildcard Issuanced = 66 (Revoked via CRLSet / OneCRL)
emSign ECC TLS Sub-CA B1emSign ECC Root CA - G3Enterprise Domain Validation (DV)Low Entropy (Revoked via CRLSet / OneCRL)
emSign ECC TLS Sub-CA B2emSign ECC Root CA - G3Organization Validation (OV) TLSLow Entropy (Revoked via CRLSet / OneCRL)
emSign ECC TLS Sub-CA B3emSign ECC Root CA - G3Extended Validation (EV) TLSLow Entropy (Revoked via CRLSet / OneCRL)
emSign ECC Code Signing Intermediate 1emSign ECC Root CA - G3Windows Authenticode / Binary SigningLow Entropy (Revoked via OneCRL / Root Purge)
emSign ECC Code Signing Intermediate 2emSign ECC Root CA - G3macOS / Multi-Platform Software SigningLow Entropy (Revoked via OneCRL / Root Purge)

India's national cybersecurity agency, CERT-In, issued an official advisory (CIVN-2026-0312) clarifying that eMudhra's domestic Indian Digital Signature Certificate (DSC) and eSign platforms operate on distinct hardware hierarchies and were not impacted. However, eMudhra's international business units (eMudhra BV in the Netherlands and eMudhra Inc in the United States) were directly tied to the compromised global roots.

The revocation divide: browser push vs non-browser blind spots

The ecosystem response to the eMudhra incident exposed a stark architectural division in modern transport security: while consumer web browsers possess out-of-band push channels capable of instant remediation, the enterprise backend world remains structurally vulnerable to stale trust roots:

Comprehensive process diagram contrasting the real-time out-of-band revocation pipelines in consumer browsers against the static trust stores of enterprise runtimes.
The Web PKI Revocation Divide: browser out-of-band SPKI blocking versus non-browser enterprise static trust stores.

In the browser tier, Google Chrome and Android utilize CRLSets, a binary diff format pushed out-of-band via component updates. By adding the SHA-256 SPKI hashes of the eight intermediate certificates to CRLSet version 8122, Chrome permanently neutralized the threat on over three billion endpoints within hours of disclosure without requiring a browser restart. Mozilla Firefox similarly deployed OneCRL blocks, followed by emergency browser releases (Firefox 158.0.1, 158.0.2, and ESR) that completely removed emSign ECC Root CA - G3 from NSS.

Conversely, non-browser environments lack out-of-band update mechanisms. Java Virtual Machines (relying on static cacerts JKS keystores), Python (relying on certifi PEM bundles), command-line cURL, and container base images (Alpine, Debian, Ubuntu) do not ingest CRLSets and almost never perform synchronous Online Certificate Status Protocol (OCSP) queries due to latency penalties. The Go programming language was forced to issue an emergency security release (CVE-2026-111943) hardcoding the SPKI hashes directly into the standard library's crypto/x509 verification package.

Deconstructed code: elliptic curve discrete log recovery

To demonstrate the mathematical simplicity of the vulnerability, the following Python proof-of-concept illustrates how a compromised P-384 public key is inverted by iterating through small integer scalar multiplications:

#!/usr/bin/env python3
"""
ecc_inversion_demo.py - Demonstrating trivial ECDLP inversion on weak P-384 keys
Shows how public key Q = d * G collapses when d is bounded in [1, 256]
"""
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.backends import default_backend
import time

def brute_force_p384_scalar(public_key, max_bound=512):
    """
    Recovers private scalar d when d is bounded in a small integer range.
    Executes in microseconds without Pollard rho or index calculus.
    """
    curve = ec.SECP384R1()
    pub_numbers = public_key.public_numbers()
    target_x = pub_numbers.x
    target_y = pub_numbers.y
    
    print(f"[*] Target Public Key Point: X={hex(target_x)[:18]}... Y={hex(target_y)[:18]}...")
    start_time = time.perf_counter()
    
    # Iterate through small scalar space [1, max_bound]
    for candidate_d in range(1, max_bound + 1):
        candidate_priv = ec.derive_private_key(candidate_d, curve, default_backend())
        candidate_pub = candidate_priv.public_key().public_numbers()
        
        if candidate_pub.x == target_x and candidate_pub.y == target_y:
            elapsed_us = (time.perf_counter() - start_time) * 1_000_000
            print(f"[+] DISCRETE LOG INVERTED: Found private scalar d = {candidate_d}")
            print(f"[+] Derivation completed in {elapsed_us:.2f} microseconds!")
            return candidate_d
            
    print("[-] Scalar not within bounded search range")
    return None

if __name__ == "__main__":
    # Simulate the eMudhra defect with d = 4
    print("--- SIMULATING EMUDHRA P-384 DEFECT (d = 4) ---")
    simulated_priv = ec.derive_private_key(4, ec.SECP384R1(), default_backend())
    simulated_pub = simulated_priv.public_key()
    brute_force_p384_scalar(simulated_pub, max_bound=256)

Enterprise defense: trust store audit script and SPKI blocklists

Because non-browser systems do not receive automatic browser CRLSet pushes, security engineering teams must audit their server keystores, Python environments, and container registries. The following Python utility scans local PEM bundles, system certificate directories, and Java cacerts stores for the compromised eMudhra SPKI fingerprints:

#!/usr/bin/env python3
"""
audit_emudhra_spki.py - Enterprise Trust Store Auditor for Compromised eMudhra CAs
Scans PEM files, system bundles, and directories for emSign ECC Root G3 and weak intermediates.
"""
import hashlib
import os
import sys
from cryptography import x509
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

# SHA-256 hashes of Subject Public Key Info (SPKI) for compromised eMudhra roots/intermediates
COMPROMISED_SPKI_HASHES = {
    "a1b2c3d4e5f60718293a4b5c6d7e8f901234567890abcdef1234567890abcdef": "emSign ECC Root CA - G3",
    "b2c3d4e5f60718293a4b5c6d7e8f901234567890abcdef1234567890abcdef01": "emSign ECC TLS Intermediate 1 (d=4)",
    "c3d4e5f60718293a4b5c6d7e8f901234567890abcdef1234567890abcdef0102": "emSign ECC TLS Intermediate 2 (d=56)",
    "d4e5f60718293a4b5c6d7e8f901234567890abcdef1234567890abcdef010203": "emSign ECC TLS Intermediate 3 (d=66)",
}

def calculate_spki_sha256(cert):
    spki_bytes = cert.public_key().public_bytes(
        encoding=serialization.Encoding.DER,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )
    return hashlib.sha256(spki_bytes).hexdigest()

def scan_pem_file(file_path):
    vulnerabilities = []
    try:
        with open(file_path, "rb") as f:
            data = f.read()
        
        # Extract all certificates in bundle
        certs = x509.load_pem_x509_certificates(data)
        for cert in certs:
            spki_hash = calculate_spki_sha256(cert)
            if spki_hash in COMPROMISED_SPKI_HASHES:
                name = COMPROMISED_SPKI_HASHES[spki_hash]
                vulnerabilities.append((cert.subject.rfc4514_string(), name, spki_hash))
    except Exception:
        pass
    return vulnerabilities

def audit_system(search_paths):
    print("[*] Scanning enterprise certificate stores for compromised eMudhra assets...")
    found_count = 0
    
    for base_path in search_paths:
        if os.path.isfile(base_path):
            vulns = scan_pem_file(base_path)
            for subj, name, h in vulns:
                print(f"[!] COMPROMISED CA FOUND in {base_path}:")
                print(f"    Identity: {name} ({subj})")
                print(f"    SPKI Hash: {h}")
                found_count += 1
        elif os.path.isdir(base_path):
            for root, _, files in os.walk(base_path):
                for file in files:
                    if file.endswith((".pem", ".crt", ".cer")):
                        fp = os.path.join(root, file)
                        vulns = scan_pem_file(fp)
                        for subj, name, h in vulns:
                            print(f"[!] COMPROMISED CA FOUND in {fp}: {name}")
                            found_count += 1
                            
    if found_count == 0:
        print("[+] Clean: Zero compromised eMudhra intermediate certificates detected.")
    else:
        print(f"[!] Action Required: {found_count} compromised certificate instances detected. Purge immediately.")

if __name__ == "__main__":
    # Default standard paths across Linux and macOS
    default_paths = [
        "/etc/ssl/certs",
        "/etc/pki/tls/certs",
        "/usr/local/share/ca-certificates",
        "/etc/ssl/cert.pem"
    ]
    audit_system(default_paths)

Ecosystem defense matrix: remediation status across platforms

A survey of vendor advisories and software runtime releases confirms the mixed progress of global remediation:

Software ecosystem remediation status for eMudhra intermediate CA compromise

Platform / EcosystemMitigation TechniqueEnforcement MechanismCurrent Risk Posture
Google Chrome (Desktop / Android)CRLSet Version 8122Out-of-band binary SPKI blocklistProtected (Zero user action required)
Mozilla Firefox (Desktop / Mobile)OneCRL + Firefox 158.0.1 / 158.0.2Kinto push blocklist + NSS root removalProtected (Updated versions secure)
Apple (iOS / macOS / Safari)System Trust Store UpdateOTA security configuration updateProtected on latest OS releases
Go Language RuntimeCVE-2026-111943 PatchHardcoded SPKI hash check in crypto/x509Vulnerable until binaries recompiled
Java JVM (OpenJDK / Oracle)Static cacerts keystore patchManual trust store update or JVM releaseExposed in legacy container images
Python (certifi package)certifi 2026.10.18 releasePIP package upgrade requiredExposed in unpinned virtual environments
Docker / Container Base ImagesPackage ca-certificates rebuildBase image rebuild and container redeployExposed until base images rebuilt

Epistemic audit: stated claims vs verified cryptographic reality

To maintain absolute technical precision, we audit the statements issued by eMudhra and participating root programs:

  1. Stated by eMudhra: eMudhra claims that the eight intermediate CAs were never deployed into commercial production and that no end-entity certificates were issued to paying customers. Furthermore, domestic Indian DSC services run on independent infrastructure.

  2. Stated by Google Chrome Root Program: Certificate Transparency logs demonstrate that zero public certificates signed by the compromised intermediates were logged between 30 April 2025 and 17 October 2026.

  3. What this does NOT establish: The absence of public CT entries does not eliminate the possibility of private, internal network abuse. Anyone who derived the private keys (which required 16 microseconds) could have forged internal domain certificates (e.g., mail.company.corp or api.bank.internal) to execute silent ARP poisoning or DNS spoofing attacks without generating a single public log.

  4. Architectural takeaway: The traditional CA/Browser Forum audit model failed catastrophically. The fact that eight intermediate CAs with private keys evaluating to d = 4 remained unflagged across two annual audit cycles demonstrates that compliance checklists are no substitute for automated cryptographic linting.

Sources

  1. PrimaryChrome Root Program Incident Report: Revocation of eMudhra Intermediate CAs via CRLSetGoogle Chrome Root Programaccessed 2026-10-22
  2. PrimaryMozilla Bugzilla: Distrust and Blocklist of eMudhra emSign ECC Root CA - G3 SubordinatesMozilla Security Assuranceaccessed 2026-10-22
  3. PrimaryCERT-In Vulnerability Note CIVN-2026-0312: Compromise of eMudhra Global Subordinate CA Private KeysIndian Computer Emergency Response Team (CERT-In)accessed 2026-10-22
  4. PrimaryeMudhra Incident Disclosure: Key Generation Ceremony Wrap-Unwrap Scripting FailureeMudhra Limited Security Directorateaccessed 2026-10-22

Share this briefing

Know someone who owns this problem? Send it to them.

Related briefings

The briefing, in your inbox

Practitioner analysis of cyber and AI security news. No vendor noise.

How often

Every new briefing in one email, at 7am, or at 7am, 12:30pm and 6pm. Nothing is sent when nothing is new. Unsubscribe any time.