Saltar al contenido
ecdsa.com

Certificado autofirmado o de una CA: cuándo usar cada uno

Los dos cifran igual de bien. La diferencia está en quién avala la clave, cómo aprenden los clientes a confiar en ella y qué se rompe cuando la rotas.

Elegir entre un certificado autofirmado y uno firmado por una CA es decidir quién avala el vínculo entre una clave pública y un nombre. Un certificado autofirmado está firmado con su propia clave, así que solo demuestra que su titular tiene esa clave; un cliente confía en él solo si se le indicó que confiara en ese certificado exacto. Un certificado firmado por una CA lleva la firma de una autoridad de certificación en cuya raíz el cliente ya confía: una CA pública para internet o una CA privada que gestionas y distribuyes tú mismo.

De un vistazo

AutofirmadoCA privadaCA pública
Quién firma el certificado hojaLa propia clave del certificado hojaTu raíz o tu CA intermediaUna CA presente en los almacenes raíz de los navegadores y del sistema operativo
Cómo aprenden los clientes a confiar en élCada cliente fija o instala este certificado exactoSe instala una raíz (MDM, gestión de la configuración, imagen de contenedor)Ya es de confianza por defecto
Rotación del certificado hojaHay que actualizar todos los clientesTransparente para los clientesTransparente para los clientes
RevocaciónNo existe; hay que quitarlo de todos los clientesTu propia CRL, OCSP o vidas útiles cortasCRL publicadas por la CA
Nombres que puede incluirCualquieraCualquiera que permitan las restricciones de la raízSolo nombres de dominio públicos e IP públicas
Límites de vida útilNinguno por parte de los navegadores; las plataformas de Apple limitan a 825 días los certificados TLS emitidos desde julio de 2019El mismo límite de 825 días en las plataformas de Apple200 días ahora, 47 días a partir de marzo de 2029
Certificate TransparencyNo se registraNo se registraSe registra públicamente, con cada nombre de host
Coste y esfuerzoNinguno al principio; alto en cada rotaciónOperar la CA y proteger su claveGratis con ACME; requiere validación por DNS o HTTP
Herramientas habitualesopenssl req -x509, mkcert para desarrollo localstep-ca, HashiCorp Vault PKI, CA privadas en la nube, cert-managerLet's Encrypt y otras CA con ACME

Cómo decide un cliente si confía en un certificado

La validación de la ruta (RFC 5280 §6) construye una cadena desde el certificado del servidor hasta un ancla de confianza del almacén raíz del cliente y en cada eslabón comprueba la firma, el período de validez, las restricciones básicas, el uso de clave y las restricciones de nombres. Un certificado autofirmado tiene el mismo emisor y sujeto y está firmado con su propia clave, así que la única cadena posible es el propio certificado. Solo se valida si ese certificado es en sí mismo un ancla de confianza para el cliente, y eso es exactamente lo que significa «fijar» (pinning) o «instalar» un certificado autofirmado.

En un certificado hoja firmado por una CA, la firma es de una CA intermedia, que a su vez se encadena a una CA raíz. El cliente nunca necesita conocer de antemano el certificado hoja; le basta con la raíz. Esa indirección es lo que hace posibles la rotación, la revocación y la automatización.

El script siguiente, ejecutado con OpenSSL 3.6.5, crea un certificado autofirmado, una raíz privada limitada a los nombres bajo .internal y dos certificados hoja firmados por esa raíz.

Certificado autofirmado, CA privada y restricciones de nombres
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
P256="-newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc"

# 1. Self-signed server certificate
openssl req -x509 $P256 -keyout self.key -out self.pem -days 30 \
  -subj "/CN=dev.internal" \
  -addext "subjectAltName=DNS:dev.internal,IP:127.0.0.1" \
  -addext "basicConstraints=critical,CA:FALSE" 2>/dev/null
openssl verify self.pem
openssl verify -CAfile self.pem self.pem

# 2. Private root CA limited to .internal names
openssl req -x509 $P256 -keyout ca.key -out ca.pem -days 3650 \
  -subj "/CN=Example Internal Root" \
  -addext "keyUsage=critical,keyCertSign,cRLSign" \
  -addext "nameConstraints=critical,permitted;DNS:.internal" 2>/dev/null

# 3. Two server certificates signed by that CA
for name in api.internal www.example.com; do
  openssl req -x509 $P256 -CA ca.pem -CAkey ca.key -keyout "$name.key" \
    -out "$name.pem" -days 90 -subj "/CN=$name" \
    -addext "subjectAltName=DNS:$name" \
    -addext "basicConstraints=critical,CA:FALSE" \
    -addext "extendedKeyUsage=serverAuth" 2>/dev/null
done
openssl verify api.internal.pem
openssl verify -CAfile ca.pem api.internal.pem
openssl verify -CAfile ca.pem www.example.com.pem
cd / && rm -rf "$dir"
Salida
CN=dev.internal
error 18 at 0 depth lookup: self-signed certificate
error self.pem: verification failed
self.pem: OK
CN=api.internal
error 20 at 0 depth lookup: unable to get local issuer certificate
error api.internal.pem: verification failed
api.internal.pem: OK
CN=www.example.com
error 47 at 0 depth lookup: permitted subtree violation
error www.example.com.pem: verification failed

El certificado autofirmado solo se verifica cuando se pasa como su propia ancla de confianza. El certificado hoja de la CA privada se verifica en cuanto se confía en la raíz, y las restricciones de nombres de la raíz le impiden avalar www.example.com, lo que limita el daño si alguna vez se hace un mal uso de la clave de la CA. Ten en cuenta que openssl req -x509 marca por defecto los certificados como CA a través de su archivo de configuración; el CA:FALSE explícito impide que el certificado autofirmado del servidor pueda usarse como emisor.

Qué dicen los clientes cuando no confían en el certificado

Conectamos cinco clientes a un servidor local que presentaba cada uno de los certificados, sin añadir nada a sus almacenes de confianza (20 de octubre de 2026, macOS).

ClienteCertificado autofirmadoCertificado hoja de una CA privada que no es de confianza
Node.js 26.10DEPTH_ZERO_SELF_SIGNED_CERTUNABLE_TO_VERIFY_LEAF_SIGNATURE
Python 3.14 (OpenSSL 3.6.5)certificate verify failed: self-signed certificatecertificate verify failed: unable to get local issuer certificate
Go 1.25 (verificador de macOS)x509: certificate signed by unknown authorityx509: “localhost” certificate is not trusted
curl 8.7.1 (LibreSSL)(60) SSL certificate problem: self signed certificate(60) SSL certificate problem: unable to get local issuer certificate
OpenSSL 3.6.5 s_clientVerify return code: 18 (self-signed certificate)Verify return code: 20 (unable to get local issuer certificate)

Los navegadores muestran NET::ERR_CERT_AUTHORITY_INVALID (Chrome) o MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT (Firefox). La solución nunca es desactivar la verificación (NODE_TLS_REJECT_UNAUTHORIZED=0, verify=False, InsecureSkipVerify, curl -k): eso elimina la autenticación de todas las conexiones que abre el proceso. En su lugar, dale al cliente el certificado o la raíz en que debe confiar (ca: en Node.js, cafile= en Python, un pool RootCAs propio en Go, --cacert en curl) o instala la raíz en el almacén del sistema operativo. Un certificado sin un nombre DNS en la extensión de nombre alternativo del sujeto (Subject Alternative Name) falla de otra forma: Chrome dejó de comparar el nombre común en la versión 58 (2017), y las plataformas de Apple, desde iOS 13 y macOS 10.15.

La vía intermedia: una CA privada

Una CA privada conserva la principal ventaja de la autofirma (sin terceros, cualquier nombre interno, sin registro público) y elimina su principal coste (redistribuir la confianza en cada rotación). Reglas prácticas:

  • Mantén la raíz sin conexión y emite desde una CA intermedia; una intermedia comprometida se puede sustituir sin tocar todos los clientes.
  • Restringe los nombres a tus zonas internas, como en la demostración, y mantén pathlen y el uso de clave bien acotados.
  • Automatiza los certificados hoja: step-ca, Vault PKI y cert-manager pueden emitir mediante ACME o sus propias API, así que los certificados hoja pueden durar horas o días y la revocación deja de ser necesaria.
  • Respeta igualmente las reglas de los clientes: las plataformas de Apple exigen un nombre DNS en el SAN, el uso extendido de clave serverAuth y una validez de 825 días como máximo para los certificados TLS emitidos desde el 1 de julio de 2019, también con raíces privadas; el límite de 398 días solo se aplica a las raíces de confianza pública.
  • Planifica la distribución de la raíz: los almacenes del sistema operativo, los almacenes de claves de Java, las imágenes de contenedor, los navegadores con almacén propio (Firefox) y el software que trae su propio conjunto de raíces (el paquete certifi en el que se apoya requests de Python, y Node.js, que usa su conjunto integrado de Mozilla salvo que se inicie con --use-system-ca) necesitan la raíz, cada uno por su lado.

Dónde no puede ayudar una CA pública

Las CA públicas tienen prohibido emitir certificados que contengan nombres internos o direcciones IP reservadas (Baseline Requirements §4.2.2). Por eso, nombres como printer.local, los hosts de una sola etiqueta, 10.0.0.5 o cualquier nombre bajo .internal, que la ICANN reservó de forma permanente para uso privado el 29 de julio de 2024, solo pueden venir de una CA privada o de un certificado autofirmado. Los hosts internos con nombres públicos (por ejemplo, db.corp.example.com) pueden obtener certificados públicos mediante el desafío DNS-01 sin ser accesibles desde internet, pero entonces cada nombre aparece en los registros públicos de Certificate Transparency, lo que revela tu topología interna a cualquiera que los consulte.

Cuándo elegir cada uno

  • Sitios web públicos, API y servidores de correo: CA pública con ACME.
  • Servicios internos, mallas de servicios, mTLS entre cargas de trabajo: CA privada con certificados hoja de corta duración.
  • Desarrollo local: una CA de desarrollo local como mkcert, que instala su raíz en tus propios almacenes de confianza, en lugar de certificados autofirmados que cada herramienta rechaza de una forma distinta.
  • Dispositivos y equipos dedicados en el primer arranque: un certificado autofirmado cuya huella digital verifica una vez el usuario o el sistema de aprovisionamiento, seguido de la inscripción en una CA privada.
  • Fixtures de pruebas: certificados autofirmados que genera la propia prueba y que se pasan explícitamente al cliente que se está probando.
  • Socios e integraciones B2B mediante mTLS: una CA privada dedicada a esa relación, nunca tu raíz interna general.

Notas de migración

  1. Haz inventario de los certificados autofirmados en uso: escanea los endpoints internos y recopila los certificados que fijan los clientes; el decodificador de certificados muestra el emisor, los SAN y la caducidad.
  2. Pon en marcha una CA privada con una raíz sin conexión y una CA intermedia emisora, restringida a tus dominios internos; genera las solicitudes con el generador de CSR.
  3. Distribuye la raíz antes de cambiar ningún servidor y después sustituye los certificados hoja servicio a servicio; el constructor de cadena de certificados confirma que cada servidor envía su certificado intermedio.
  4. Elimina los atajos inseguros (-k, verify=False, InsecureSkipVerify) cuando los clientes ya confíen en la raíz, y busca en el código para que no vuelvan.
  5. Pasa los nombres expuestos al público a una CA pública con ACME y, si mantienes alguna fijación, aplícala a las claves y no a los certificados; el generador de pines SPKI calcula pines que sobreviven a la renovación con la misma clave.

Referencias

Todas las comparaciones