3 Power Tips + Power Link I15
En octubre de 2026 se hizo público que ocho certificados intermedios de eMudhra tenían claves privadas que cualquiera podía calcular. Los tres tips siguen el problema desde la clave hasta el cliente que confía en ella: cómo se detecta, por qué revocar no alcanzó y qué almacenes quedan afuera del parche. Al final, otra discusión sobre qué hay que verificar y qué alcanza con declarar.
Power Tip #1 La debilidad no se ve, se prueba
Ocho certificados intermedios se veían normales, con curva P-384 y una clave pública del tamaño esperado, y sus claves privadas se calculaban en segundos.
- En una clave de curva elíptica, la privada es un entero
dy la pública es el puntoQ = d · G, que viaja en el certificado:G, un punto fijo de la curva igual para todos, sumado consigo mismodveces. Esa cuenta es fácil de hacer y, con undal azar de unos 384 bits, inviable de deshacer. - En las claves de eMudhra,
dera menor a 256.Qno lo delata: el punto que sale ded = 7se ve tan aleatorio como cualquier otro. - La única forma de saberlo es probar la hipótesis: calcular
d · Gpara valores chicos y comparar conQ. Así recuperó Mozilla las claves por su cuenta, sin más dato que la clave pública de cada certificado. - La prueba no se limita a valores tan chicos. Baby-step giant-step arma una tabla con los primeros múltiplos de
Gy salta desdeQhacia atrás, de a tramos largos, hasta caer en ella. Así, descartar cualquierdde hastakbits (menor a 2^k) cuesta del orden de 2^(k/2) operaciones: hasta 64 bits, unas 2^32 por clave, y otras tantas entradas de tabla en memoria.
import sys from cryptography import x509 from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat pub = x509.load_pem_x509_certificate(open(sys.argv[1], "rb").read()).public_key() q = pub.public_bytes(Encoding.X962, PublicFormat.UncompressedPoint) # d · G para cada candidato, comparado con el Q del certificado for d in range(1, 256): if ec.derive_private_key(d, pub.curve).public_key().public_bytes(Encoding.X962, PublicFormat.UncompressedPoint) == q: print("d =", d) break
Que la prueba no encuentre d dice que la clave no tiene esa debilidad puntual, no que sea fuerte. ROCA, la falla divulgada en 2017 en las claves RSA que generaban los chips de Infineon, dejaba una marca en la clave pública y se detectaba con solo mirarla. Esta no deja ninguna: nadie la vio antes porque nadie había corrido la prueba sobre esos certificados.
Power Tip #2 Revocar un certificado no revoca la clave
eMudhra revocó los ocho certificados intermedios el 18 de octubre, y las claves seguían sirviendo para firmar certificados que un cliente sin control de revocación aceptaría.
- Cada una de las ocho claves tenía dos certificados: uno firmado por una raíz de eMudhra y otro por AAA Certificate Services, la raíz histórica de Sectigo. Mismo sujeto, misma clave pública, distinto emisor: una firma cruzada.
- La revocación de eMudhra alcanzó solo a los certificados emitidos por sus propias raíces. Hasta que Sectigo revocó las firmas cruzadas, un día después, un certificado firmado con una de esas claves validaba igual por el otro camino: quien lo presenta elige qué intermedio manda en la cadena.
- Además, la revocación solo protege a quien la consulta. Los navegadores reciben listas de bloqueo propias (OneCRL en Firefox, CRLSets en Chrome).
curl, Python o Java no consultan CRL ni OCSP con su configuración por defecto.
for c in intermedia-raiz-emsign.pem intermedia-raiz-aaa.pem; do openssl x509 -in "$c" -noout -issuer; openssl x509 -in "$c" -noout -pubkey | openssl sha256; done
El bug de Mozilla lista la huella SHA-256 de los dieciséis certificados, y https://crt.sh/?d=<huella> devuelve cada uno en PEM; el script del tip 1 corre sobre cualquiera de ellos.
Dos emisores distintos y el mismo hash: cerrar la clave exige revocar cada certificado emitido sobre ella, y aun así eso solo alcanza a quien consulta la revocación. Para el resto, lo único que corta la cadena es que la raíz salga del almacén.
Power Tip #3 El almacén que actualizaste no es el único
Actualizaste ca-certificates y la raíz salió del almacén del sistema, pero una aplicación en el mismo host sigue aceptando las cadenas que pasan por ella.
-
update-ca-trustregenera los almacenes de/etc/pki/ca-trust/extracted/, que leen OpenSSL, GnuTLS, NSS y el Java empaquetado por la distro. Hasta ahí llega el cambio. - Quedan afuera los que traen su propia copia de las raíces: el
certifiinstalado conpipdentro de un entorno virtual, el JDK descomprimido de un tarball (ver el Power Tip #2 del I14), las raíces dewebpki-rootscompiladas dentro de un binario de Rust, y las imágenes de contenedor con su propioca-certificates, congelado el día en que se construyeron. - Desde el sistema, la palanca es gruesa. La mitigación manual de Red Hat bloquea dos raíces completas: emSign ECC Root CA - G3 y Comodo AAA Services root, la misma que en los certificados figura como AAA Certificate Services. Mozilla y Chrome ya habían sacado AAA de sus almacenes. El bloqueo pesa solo donde el almacén todavía la tiene, y ahí deja de validar también las cadenas legítimas que pasan por ella.
trust list --filter=blocklist find / -xdev \( -name cacerts -o -name cacert.pem \) -exec ls -l {} + 2>/dev/null
En p11-kit anterior a 0.24, como el de RHEL 8, el filtro se llama blacklist.
El almacén del sistema protege a quien lo lee, y a nadie más. Antes de aplicar la mitigación manual en un host hay dos preguntas: qué almacenes de ese host no alcanza, y qué cadenas legítimas que pasan por AAA va a dejar de aceptar.
Power Link
En el kernel se discute si conviene seguir pidiendo que cada commit declare con la etiqueta Assisted-by el uso de herramientas de IA. Torvalds sostiene que a quien contribuye hay que juzgarlo por si entiende su código y no por las herramientas que usó; Laurent Pinchart, que una regla difícil de hacer cumplir igual fija expectativas: Torvalds calls AI disclosure rules 'utterly stupid' as Linux drops its tag

Comentarios
Comments powered by Disqus