Saltar al contenido

Certificados, CAs y cadenas de confianza: una guía para no perderse

Augusto Mancuso
Published date:

Certificados, CAs y cadenas de confianza: una guía para no perderse

Cuando uno empieza a meterse con certificados, HTTPS, TLS, proxies, Kubernetes o infraestructura en general, aparecen varias siglas que al principio parecen más abstractas de lo necesario:

Y suele pasar algo bastante común: configurás un certificado, el servicio levanta, el navegador deja de quejarse, curl responde bien… pero en el fondo queda la duda de qué está pasando realmente.

Este post busca ordenar esas piezas.

No quiero hacer una definición de libro ni meterme en todos los detalles criptográficos posibles. La idea es entender qué problema resuelve PKI, cómo se construye la confianza y por qué HTTPS termina funcionando cuando todo está bien configurado.


El problema de fondo

Supongamos que tengo un servidor con este dominio:

api.midominio.com

Y un cliente quiere conectarse por HTTPS. Ese cliente puede ser muchas cosas:

La pregunta importante es:

¿Cómo sabe el cliente que realmente está hablando con api.midominio.com y no con otro servidor que se está haciendo pasar por él?

Porque cualquiera podría levantar un servidor, generar una clave pública y decir:

“Hola, sí, yo soy api.midominio.com”.

Claramente no alcanza con que el servidor lo diga. Hace falta un mecanismo para asociar identidad, claves y confianza.

Ahí entra PKI.


Entonces, ¿qué es PKI?

PKI significa Public Key Infrastructure.

El nombre suena enorme, y en la práctica puede serlo, pero la idea base es bastante concreta:

PKI es el conjunto de componentes, reglas y procesos que permiten emitir, validar, revocar y confiar en certificados que vinculan identidades con claves públicas.

Dicho de otra manera: PKI es todo lo que hace posible que un certificado tenga valor.

No es solamente un archivo .crt. Incluye varias piezas:

Lo importante es no pensar en PKI como “un certificado”, sino como el modelo completo que permite que ese certificado sea emitido, validado y confiable dentro de cierto contexto.


Todo arranca con un par de claves

La base de todo esto está en la criptografía asimétrica.

Hay dos claves:

Clave privada

Es la clave secreta. La que no debería salir nunca del servidor, del cliente o del componente que la usa.

Si alguien obtiene la clave privada de un servidor, puede hacerse pasar por ese servidor mientras el certificado siga siendo aceptado por los clientes.

Por eso la clave privada se protege con mucho cuidado.

Clave pública

Es la clave que se puede compartir con otros.

La idea general es esta:

Hasta ahí, todo bien.

Pero hay un punto importante:

Demostrar posesión de una clave privada no es lo mismo que demostrar identidad.

Yo podría generar una clave pública ahora mismo y decir:

“Esta clave pertenece a google.com”.

Y también podría demostrar que tengo la clave privada correspondiente a esa clave pública.

Pero eso no alcanza para probar que soy google.com.

Hace falta algo que afirme:

“Esta clave pública pertenece a esta identidad, y alguien confiable lo garantiza”.

Ese “algo” es el certificado.


Qué es un certificado digital

Un certificado digital es un documento que vincula:

y además está firmado por una entidad en la que otros pueden confiar.

En términos prácticos, un certificado dice algo como:

“La clave pública X pertenece a api.midominio.com, y esta afirmación fue firmada por una autoridad confiable”.

Un certificado incluye varios datos, por ejemplo:

La parte importante es esta:

Un certificado no es simplemente “la clave pública del servidor”. Es una afirmación firmada sobre esa clave pública.

Esa diferencia parece chica, pero es central para entender todo el modelo.


Qué son los SANs y por qué importan

SAN significa Subject Alternative Name.

En la práctica, es la extensión del certificado donde se indican los nombres para los que ese certificado es válido.

Por ejemplo, un certificado podría tener estos SANs:

DNS:api.midominio.com
DNS:www.midominio.com
DNS:grafana.interna.local

Cuando un cliente se conecta a:

https://api.midominio.com

no alcanza con que el certificado esté firmado por una CA confiable. El cliente también tiene que verificar que el nombre al que se está conectando aparece dentro del certificado.

Si el certificado es válido para www.midominio.com, pero el cliente se conecta a api.midominio.com, la validación debería fallar.

Este es uno de los errores más comunes:

certificate is valid for www.midominio.com, not api.midominio.com

La cadena puede estar perfecta, la CA puede ser confiable y el certificado puede no estar vencido, pero si el nombre no coincide, el certificado no sirve para esa conexión.


Qué es una CA

CA significa Certificate Authority.

Una CA es una entidad que emite y firma certificados.

Es la que dice:

“Validé esta información y firmo que esta clave pública pertenece a esta identidad”.

Algunos ejemplos de CAs públicas conocidas son:

También puede haber CAs internas, por ejemplo:

En todos los casos, el rol conceptual es el mismo: emitir certificados que otros puedan validar.


Qué significa que una CA firme un certificado

Esto conviene entenderlo bien.

Cuando se dice que una CA “firma” un certificado, no se está hablando de un sello visual ni de algo simbólico.

Lo que pasa es criptográfico.

De forma simplificada:

  1. la CA toma los datos del certificado que deben ser firmados
  2. calcula un hash sobre esos datos
  3. firma ese hash con su clave privada
  4. esa firma queda dentro del certificado

En X.509, la firma no se entiende como “firmar un archivo .crt cualquiera”, sino como firmar la parte del certificado que contiene los datos que deben quedar protegidos por esa firma.

Después, cualquier cliente que tenga la clave pública de esa CA puede verificar la firma.

Entonces, cuando un cliente revisa un certificado firmado por una CA, esa verificación permite comprobar dos cosas:

Pero eso por sí solo no alcanza para aceptar el certificado.

Además de verificar la firma, el cliente también tiene que validar otras cosas:

Ahí empieza a aparecer la idea de confianza.


Root CA: la raíz de la confianza

Dentro de una PKI, la autoridad más importante es la Root CA.

Es la raíz de confianza. La base sobre la que se apoya todo lo demás.

La Root CA tiene una característica especial: normalmente es autofirmada.

Eso significa que su propio certificado fue firmado por ella misma.

A primera vista suena circular, pero tiene sentido. La Root no recibe confianza desde una autoridad superior. La confianza viene de otro lado: de que el sistema operativo, el navegador o la aplicación ya la trae instalada como confiable.

El cliente no dice:

“Confío en esta Root porque alguien más la firmó”.

Dice:

“Confío en esta Root porque está en mi trust store”.

Esa diferencia explica por qué una Root CA es tan sensible. Si está en el trust store, pasa a ser un punto de confianza para todo lo que dependa de ella.


Entonces, ¿qué es una Intermediate CA?

Una Intermediate CA es una autoridad intermedia.

Fue firmada por una Root CA y, a su vez, puede firmar certificados para servidores, clientes, servicios o dispositivos.

Pero hay un detalle importante: una Intermediate CA solo puede actuar como CA si su certificado fue emitido con las extensiones correctas para eso.

Por ejemplo, su certificado debería indicar que puede funcionar como CA mediante extensiones como:

Además, puede tener restricciones adicionales, como límites de profundidad de cadena, políticas o restricciones de nombres.

Esto se hace principalmente por seguridad.

Si la Root CA firmara todos los certificados directamente, tendría que estar activa todo el tiempo. Y eso sería un riesgo enorme.

Por eso, en una PKI bien armada, suele hacerse algo así:

Visualmente:

Root CA
   └── Intermediate CA
          └── Certificado del servidor

La Root queda como base de confianza. La intermedia queda como autoridad operativa.


Por qué no se usa la Root para todo

Porque si se compromete la Root, el problema es enorme.

La Root es la base de confianza de toda la estructura. Si alguien obtiene su clave privada, podría emitir certificados que serían confiables para todos los clientes que confíen en esa raíz.

Por eso la práctica habitual es:

De esa forma, si una Intermediate tiene un problema, se puede revocar o reemplazar sin tener que destruir toda la PKI desde cero.

La Root se usa lo menos posible. La Intermediate es la que trabaja todos los días.


Qué es la cadena de confianza

La cadena de confianza es una de las ideas más importantes de todo este tema.

Es el camino que un cliente puede reconstruir desde el certificado final del servidor hasta una Root CA que ya conoce y en la que confía.

Por ejemplo:

Certificado de api.midominio.com
   firmado por
Intermediate CA
   firmada por
Root CA

El razonamiento del cliente sería algo así:

  1. este certificado fue firmado por esta Intermediate CA
  2. esta Intermediate CA fue firmada por esta Root CA
  3. yo ya confío en esa Root CA
  4. entonces puedo confiar en el certificado final, siempre que el resto de las validaciones también pasen

Eso es la famosa cadena de confianza.

No se trata de confiar mágicamente en el certificado del servidor. Se trata de poder seguir una cadena de firmas hasta llegar a una raíz que el cliente ya acepta.

Y además de llegar a una raíz confiable, la cadena tiene que ser válida:


Qué es el trust store

El trust store es el conjunto de certificados raíz que un sistema considera confiables.

Puede existir en distintos lugares:

Cuando un cliente recibe un certificado, intenta construir una cadena hasta una Root CA que esté en su trust store.

Si puede construir esa cadena, y el resto de las validaciones también pasan, acepta el certificado.

Si no puede llegar a una Root confiable, falla.

Por eso a veces un certificado funciona en un cliente y falla en otro. No todos tienen exactamente el mismo trust store, ni las mismas versiones, ni las mismas reglas de validación.

Un caso típico es Java. Una aplicación Java puede fallar validando un certificado aunque el sistema operativo lo acepte, porque la JVM puede estar usando su propio almacén de confianza.


Un ejemplo simple del proceso completo

Supongamos que quiero emitir un certificado para:

api.midominio.com

Paso 1: ya existe una Root CA

Primero existe una Root CA creada previamente.

Tiene:

Esa Root es la base de confianza.

Paso 2: se crea una Intermediate CA

Después se crea una Intermediate CA.

La Intermediate genera:

La Root firma esa CSR y emite un certificado para la Intermediate.

A partir de ese momento, si el certificado de la Intermediate fue emitido con las extensiones correctas, esa Intermediate queda autorizada para emitir certificados dentro de los límites definidos por la Root y por la política de la PKI.

Paso 3: el servidor genera su clave y su CSR

El servidor de api.midominio.com genera:

La CSR incluye datos como:

Paso 4: la Intermediate firma el certificado del servidor

La Intermediate revisa la solicitud y firma el certificado del servidor.

Ese certificado final también debería tener los usos adecuados para el escenario donde se va a usar. Para un servidor HTTPS normalmente se espera un certificado válido para autenticación de servidor, indicado mediante serverAuth.

Entonces queda una estructura así:

Root CA
   └── firma a Intermediate CA
            └── firma a api.midominio.com

Paso 5: el servidor presenta el certificado

Cuando un cliente se conecta por HTTPS, el servidor le entrega:

En general, el servidor presenta el certificado final y las intermedias necesarias, pero no necesita enviar la Root CA. La Root se espera del lado del cliente, dentro de su trust store.

Paso 6: el cliente valida

El cliente verifica varias cosas:

Si todo eso cierra, acepta la conexión.


Qué pasa si falta la cadena

Este error aparece muchísimo.

A veces el servidor presenta solamente su certificado final, pero no envía la Intermediate CA.

Entonces el cliente ve algo como:

“Este certificado fue emitido por tal autoridad, pero no tengo la pieza intermedia para llegar hasta una Root conocida”.

Y la validación falla.

Por eso muchas configuraciones usan fullchain.pem, que incluye:

Normalmente fullchain.pem no debería incluir la Root CA, porque la raíz de confianza tiene que venir del trust store del cliente.

No alcanza con tener solo el certificado final. El cliente necesita poder reconstruir la cadena completa hasta una raíz que ya confía.


Qué pasa si la Root no es confiable para el cliente

Este es el caso típico de certificados internos.

Imaginemos que armás tu propia CA para una red interna y emitís un certificado para:

grafana.interna.local

Técnicamente puede estar todo bien:

Pero si el navegador o el cliente no tienen instalada la Root CA interna, va a fallar igual.

La criptografía puede estar perfecta, pero la confianza no existe del lado del cliente.

Por eso, en una PKI interna, no alcanza con emitir certificados. También hay que distribuir la Root CA a todos los clientes que tengan que confiar en ella.


Qué rol cumple cada componente

Root CA

Es la autoridad raíz.

La base de confianza de toda la PKI.

Intermediate CA

Es la autoridad operativa.

Está firmada por la Root y se usa para emitir certificados reales, siempre dentro de las restricciones definidas por su propio certificado y por las políticas de la PKI.

Certificado final o leaf certificate

Es el certificado del servidor, cliente, servicio o dispositivo final.

Es el certificado que se presenta durante la conexión.

Servidor

Es quien presenta el certificado.

En HTTPS, por ejemplo, el servidor entrega su certificado al cliente durante el handshake TLS.

Cliente

Es quien valida el certificado y decide si confía o no.

Puede ser un navegador, curl, una app, un proxy, un servicio backend o cualquier componente que inicie la conexión.

Trust store

Es el conjunto de raíces confiables que el cliente ya conoce.

Si la cadena no llega hasta una de esas raíces, la validación falla.


Una analogía simple

Una forma útil de pensarlo es esta.

Root CA

Es como la autoridad máxima de un país.

Intermediate CA

Es como un organismo autorizado por esa autoridad para emitir documentos.

Certificado del servidor

Es como el documento final emitido a una persona, empresa o servicio.

Cliente

Es como el inspector que controla si ese documento es válido.

El inspector no necesita conocer personalmente a la persona o al servidor. Solo necesita poder reconstruir esta lógica:

Eso, llevado a certificados, es la cadena de confianza.


Y en mTLS, ¿qué cambia?

En TLS normal, el cliente valida al servidor.

En mTLS, además de eso, el servidor también valida al cliente.

El flujo queda así:

Ahí PKI sirve para autenticar a ambos lados: no solo al servidor frente al cliente, sino también al cliente frente al servidor.

El cifrado de la comunicación lo proporciona TLS mediante las claves de sesión negociadas durante el handshake. PKI ayuda a que esa negociación esté asociada a identidades verificables y no a un servidor o cliente impostor.

Esto es muy útil en escenarios como:

También es común que los certificados de cliente tengan usos específicos, como clientAuth, y que el servidor valide no solo la firma y la cadena, sino también si ese certificado está autorizado para actuar como cliente.

La idea de fondo sigue siendo la misma: cada parte presenta un certificado y la otra parte decide si puede confiar en él.


No confundir cifrado con confianza

Un punto que suele generar confusión: TLS no es solo “cifrar”.

En una conexión HTTPS pasan varias cosas:

PKI participa principalmente en la parte de identidad y confianza.

Es decir: ayuda a responder “¿estoy hablando con quien creo que estoy hablando?”.

Después, TLS se encarga de negociar las claves de sesión y proteger la comunicación.

Por eso un certificado puede ser criptográficamente válido, pero no confiable para un cliente determinado. La confianza depende de la cadena, del trust store y de las reglas de validación.


Cómo inspeccionar certificados en la práctica

Para mirar el certificado que presenta un servidor, se puede usar openssl s_client.

openssl s_client \
  -connect api.midominio.com:443 \
  -servername api.midominio.com \
  -showcerts

El parámetro -servername es importante porque activa SNI. Sin SNI, algunos servidores podrían devolver otro certificado, especialmente cuando alojan varios dominios en la misma IP.

También se puede revisar el certificado con más detalle:

openssl x509 \
  -in certificado.crt \
  -noout \
  -text

Algunas cosas útiles para mirar:

Para validar una cadena usando una Root y una Intermediate:

openssl verify \
  -CAfile root-ca.crt \
  -untrusted intermediate-ca.crt \
  api.midominio.com.crt

Si todo está bien, deberíamos ver algo parecido a esto:

api.midominio.com.crt: OK

Si falla, el error suele dar una pista bastante buena: certificado vencido, issuer desconocido, cadena incompleta, nombre incorrecto o extensiones inválidas.


Ejemplo con curl

curl también sirve mucho para diagnosticar problemas de certificados.

Para ver detalles de la conexión TLS:

curl -v https://api.midominio.com

Si se trata de una CA interna, se puede indicar explícitamente qué Root CA usar:

curl \
  --cacert root-ca-interna.crt \
  https://grafana.interna.local

Esto no “arregla” el certificado. Solo le dice a curl que confíe en esa Root para esa ejecución.

Si querés que el sistema confíe de forma permanente, la Root CA debería instalarse en el trust store correspondiente.


Ejemplo en Kubernetes

En Kubernetes, un caso común es usar certificados TLS en un Ingress.

Normalmente se crea un Secret de tipo kubernetes.io/tls:

kubectl create secret tls api-tls \
  --cert=fullchain.pem \
  --key=privkey.pem \
  -n default

Después se referencia desde el Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api
spec:
  tls:
    - hosts:
        - api.midominio.com
      secretName: api-tls
  rules:
    - host: api.midominio.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api
                port:
                  number: 8080

Acá hay un detalle práctico importante: el archivo usado en --cert debería incluir el certificado del servidor y las intermedias necesarias.

Es decir, normalmente se usa el fullchain.pem, no solamente el certificado leaf.

Si el Ingress entrega una cadena incompleta, algunos clientes pueden fallar aunque en tu máquina parezca funcionar.


Errores comunes

Usar solo el certificado final

El servidor presenta el certificado de api.midominio.com, pero no presenta la Intermediate CA.

Resultado: algunos clientes no pueden construir la cadena.

Instalar la Intermediate como si fuera la Root

Para una PKI interna, los clientes deberían confiar en la Root CA correspondiente, no depender de instalar certificados intermedios como raíces confiables sin entender el impacto.

Olvidarse de los SANs

El certificado puede estar firmado por una CA confiable, pero si no incluye el nombre correcto en los SANs, va a fallar la validación de hostname.

Confundir certificado con clave privada

El certificado puede ser público. La clave privada no.

Compartir un .crt no suele ser el problema. Compartir un .key sí.

Usar certificados sin los usos correctos

Un certificado de servidor debería tener usos compatibles con autenticación de servidor, como serverAuth.

Una CA intermedia debería tener extensiones que le permitan actuar como CA.

Pensar que “si abre en el navegador, está perfecto”

Un navegador puede aceptar una cadena que otro cliente no acepta.

Distintos clientes pueden tener distintos trust stores, distintas políticas y distinto soporte para algoritmos o cadenas.

Ignorar la revocación

Un certificado puede no estar vencido, pero haber sido revocado.

Dependiendo del cliente, la configuración y el entorno, la revocación puede validarse mediante CRL u OCSP.


Checklist rápido para diagnosticar problemas TLS

Cuando aparece un error de certificados, conviene revisar en este orden:

  1. Nombre: el dominio usado por el cliente está dentro de los SANs.
  2. Vigencia: el certificado no está vencido y todavía es válido.
  3. Cadena: el servidor entrega el certificado final y las intermedias necesarias.
  4. Root confiable: el cliente tiene la Root CA en su trust store.
  5. Usos: el certificado sirve para el uso esperado, por ejemplo serverAuth.
  6. CA intermedia: la Intermediate tiene CA:TRUE y permisos para firmar certificados.
  7. Revocación: si aplica, el certificado no está revocado.
  8. Cliente específico: revisar si el problema ocurre en navegador, curl, Java, contenedor, proxy o solo en un entorno puntual.

Este checklist evita quedarse atrapado en el clásico:

SSL certificate problem: unable to get local issuer certificate

Ese mensaje no siempre significa lo mismo, pero casi siempre apunta a un problema de cadena o de confianza local.


La idea más importante

Si tuviera que quedarme con una sola idea de todo esto, sería esta:

Un certificado no vale por sí solo. Vale porque forma parte de una cadena de confianza que termina en una raíz que el cliente ya conoce y acepta.

Esa es la base del modelo PKI.

Cuando algo falla con certificados, muchas veces el problema está en alguno de estos puntos:

Entender la cadena ayuda muchísimo a diagnosticar esos errores sin quedarse solamente con el clásico “problema de SSL”.


Resumen rápido


Fuentes

1) PKI y X.509

2) TLS y autenticación con certificados

3) Validación de certificados y cadena de confianza

4) Roots, intermediates y chains en la práctica

5) Buenas prácticas de despliegue TLS

Previous
Ingress vs Gateway API: dos formas de exponer tráfico en Kubernetes