// Engineering Log

HTTPS y servidor web en la práctica: Parte 2 — Formatos de certificados PEM, DER, PFX y CSR: en qué se diferencian y cómo convertirlos

Publicado el 30.10.2026 · Autor:

// Ruta rapida

Este articulo pertenece al tema Seguridad y proteccion.

El centro de certificación envió un archivo con .crt, .ca-bundle y .p7b, y el servidor pide .pfx. O al revés: desde Windows se exportó .pfx, y Nginx necesita por separado certificado y clave. Dentro de todos estos archivos están las mismas entidades — certificado, clave privada, certificados intermedios — lo que difiere es solo el empaquetado. Más abajo — cómo saber qué contiene un archivo, cómo convertirlo al formato necesario y cómo no equivocarse al montar la cadena. Cómo están hechos el certificado y la cadena de confianza — en el artículo «¿Qué es HTTPS y cómo funciona el apretón de manos TLS?».

Qué hay dentro

  • Certificado — clave pública con datos del propietario, firmada por la entidad certificadora. No es secreta; el servidor la entrega a cada cliente.
  • Clave privada — secreta. Quien la posee puede hacerse pasar por tu sitio.
  • Certificados intermedios (chain, bundle, CA bundle) — eslabones entre tu certificado y el raíz de la CA.
  • Solicitud de firma (CSR) — clave pública y nombres que envías a la CA para obtener un certificado.

Formatos

PEM — texto en Base64 entre líneas marcadoras. El formato más común en Linux: lo usan Nginx, Apache, HAProxy, servidores de correo. En un solo archivo puede haber varios bloques seguidos.

-----BEGIN CERTIFICATE-----
MIIFBTCCA+2gAwIBAgISA...
-----END CERTIFICATE-----

Extensiones — .pem, .crt, .cer, .key, .ca-bundle. La extensión no garantiza nada: .crt puede ser PEM o DER. El tipo de contenido lo determina la línea marcadora:

MarcadorContenido
BEGIN CERTIFICATEcertificado
BEGIN CERTIFICATE REQUESTCSR
BEGIN PRIVATE KEYclave privada en formato PKCS#8 (cualquier algoritmo)
BEGIN ENCRYPTED PRIVATE KEYclave PKCS#8 cifrada con contraseña
BEGIN RSA PRIVATE KEYclave RSA en formato antiguo PKCS#1
BEGIN EC PRIVATE KEYclave ECDSA en formato antiguo
BEGIN PKCS7contenedor PKCS#7 con la cadena

DER — el mismo certificado en binario, sin Base64. Extensiones .der, .cer. Se encuentra en Windows y Java. En un editor de texto se ve como basura.

PKCS#7 (.p7b, .p7c) — contenedor con uno o varios certificados, normalmente la cadena. No contiene la clave privada. Así entregan la cadena muchas CAs comerciales y Windows.

PKCS#12 (.pfx, .p12) — contenedor con todo junto: certificado, clave privada y cadena, protegidos por contraseña. Se usa en Windows (IIS, Exchange, RDP), en Java, para importar certificados cliente en el navegador y en el teléfono.

JKS — almacén de claves de Java. Desde Java 9 por defecto se usa PKCS#12, y JKS solo se encuentra en sistemas antiguos.

Cómo saber qué hay en el archivo

bash
head -1 file.crt                                   # PEM — se ve la línea BEGIN
openssl x509 -in file.crt -noout -subject -issuer -dates         # certificado PEM
openssl x509 -in file.cer -inform der -noout -subject -dates     # certificado DER
openssl req -in file.csr -noout -text -verify                    # CSR
openssl pkey -in file.key -noout -text | head -1                 # clave: algoritmo y tamaño
openssl pkcs12 -in file.pfx -info -noout                         # PFX (pedirá contraseña)
openssl pkcs7 -in file.p7b -print_certs -noout                   # P7B

Cuántos certificados hay en un archivo PEM y cuáles:

bash
openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout

Conversión

DER → PEM y viceversa:

bash
openssl x509 -in cert.der -inform der -out cert.pem
openssl x509 -in cert.pem -outform der -out cert.der

P7B → PEM (obtener la cadena como certificados individuales):

bash
openssl pkcs7 -in chain.p7b -print_certs -out chain.pem

En la salida, antes de cada certificado habrá líneas subject= e issuer= — Nginx las ignora, pero por orden se pueden eliminar.

PFX → PEM (de Windows a Linux):

bash
openssl pkcs12 -in site.pfx -clcerts -nokeys -out cert.pem          # certificado del sitio
openssl pkcs12 -in site.pfx -cacerts -nokeys -out chain.pem         # intermedios
openssl pkcs12 -in site.pfx -nocerts -nodes -out privkey.pem        # clave sin contraseña

-nodes guarda la clave sin cifrar — de lo contrario Nginx pedirá la contraseña en cada arranque. Protege inmediatamente los permisos: chmod 600 privkey.pem.

Si OpenSSL 3 responde unsupported algorithm (RC2-40-CBC) o Algorithm (RC2-40-CBC : 0), Properties (), el archivo está cifrado con algoritmos obsoletos que por defecto están deshabilitados. Añade -legacy:

bash
openssl pkcs12 -legacy -in site.pfx -nocerts -nodes -out privkey.pem

PEM → PFX (de Linux a Windows o Java):

bash
openssl pkcs12 -export -out site.pfx \
  -inkey privkey.pem -in cert.pem -certfile chain.pem \
  -name "example.ru"

OpenSSL 3 cifra el PFX con el algoritmo AES-256. Sistemas antiguos (Windows Server 2016 y anteriores, algunas versiones de Java) no abren ese archivo y reportan contraseña incorrecta. Para ellos crea el PFX con algoritmos antiguos:

bash
openssl pkcs12 -export -legacy -out site-legacy.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem

PFX → JKS (para aplicaciones Java que necesitan exactamente JKS):

bash
keytool -importkeystore -srckeystore site.pfx -srcstoretype pkcs12 \
  -destkeystore site.jks -deststoretype jks

Clave: quitar contraseña, convertir a PKCS#8:

bash
openssl pkey -in encrypted.key -out privkey.pem           # pedirá contraseña, guardará sin ella
openssl pkcs8 -topk8 -nocrypt -in rsa-pkcs1.key -out privkey.pem

Construcción de la cadena (fullchain)

Nginx y HAProxy esperan un solo archivo: primero el certificado del sitio, luego los intermedios en orden; el raíz no es necesario.

bash
cat example.ru.crt intermediate.crt > fullchain.pem

Errores al construir:

  • orden incorrecto — Nginx al arrancar toma la clave del primer certificado en el archivo y da key values mismatch si el primero es un intermedio;
  • no hay salto de línea al final del archivo — al concatenar queda -----END CERTIFICATE----------BEGIN CERTIFICATE----- en una línea, y el segundo certificado no se lee. Comprobación: grep -c 'BEGIN CERTIFICATE' fullchain.pem debe coincidir con el número de certificados;
  • se añadió el raíz — no es un error, pero bytes extra en cada apretón de manos; y un raíz antiguo caducado puede confundir a algunos clientes;
  • intermedio equivocado — la CA puede emitir certificados desde varios intermedios; usa el que aparece en el campo issuer de tu certificado.

Para HAProxy el certificado, la cadena y la clave se colocan en un único archivo: cat fullchain.pem privkey.pem > /etc/haproxy/certs/example.ru.pem.

Cómo crear un CSR

Para una CA comercial o una CA interna necesitas una clave y una solicitud. La clave se crea en tu lado y no se envía a nadie.

bash
# clave ECDSA P-256
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out example.ru.key

# CSR con nombres en SAN (OpenSSL 1.1.1+)
openssl req -new -key example.ru.key -out example.ru.csr \
  -subj "/CN=example.ru" \
  -addext "subjectAltName=DNS:example.ru,DNS:www.example.ru"

Para clave RSA: openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out example.ru.key.

Indica los nombres en SAN: los navegadores comprueban solo ese campo; el campo CN ya no se usa para verificación de nombre. Las CA suelen añadir SAN a partir de CN, pero mejor no confiar en eso.

RSA o ECDSA

  • ECDSA P-256 — clave de 256 bits con resistencia comparable a RSA 3072, certificado más pequeño, la firma en el apretón de manos es más rápida. Soportado por todos los navegadores y sistemas operativos de los últimos diez años.
  • RSA 2048 — necesario solo para clientes muy antiguos: dispositivos embebidos, Java antiguos y Windows XP.

Nginx puede servir ambos certificados simultáneamente y elige el apropiado según las capacidades del cliente:

nginx
ssl_certificate     /etc/ssl/example.ru.ecdsa.crt;
ssl_certificate_key /etc/ssl/example.ru.ecdsa.key;
ssl_certificate     /etc/ssl/example.ru.rsa.crt;
ssl_certificate_key /etc/ssl/example.ru.rsa.key;

certbot emite ECDSA por defecto desde la versión 2.0; para RSA — --key-type rsa.

Errores de Nginx al cargar el certificado

  • PEM_read_bio_X509_AUX() failed (SSL: error:0480006C:PEM routines::no start line) — el archivo no está en PEM: has indicado DER, PFX o P7B. Convierte.

  • SSL_CTX_use_PrivateKey(...) failed (SSL: error:05800074:x509 certificate routines::key values mismatch) — la clave no pertenece a este certificado o el primer elemento en fullchain no es el certificado del sitio. Comparar clave y certificado:

    bash
    openssl x509 -in cert.pem -noout -pubkey | openssl sha256
    openssl pkey -in privkey.pem -pubout | openssl sha256
  • Nginx al arrancar pide contraseña o no inicia via systemd — la clave está cifrada; quita la contraseña (openssl pkey) y protege el archivo con permisos.

  • cannot load certificate ... Permission denied — Nginx lee los certificados como root al arrancar, pero revisa permisos y contexto SELinux si los archivos no están en /etc.

Después de cualquier cambio: nginx -t && systemctl reload nginx, y luego comprueba con openssl s_client — en detalle en el artículo «Depuración de TLS».

Almacenamiento de claves

  • Permisos 600 en la clave, propietario — root; el directorio — 700.
  • No se envía la clave por correo ni por mensajería junto con el certificado. Si necesitas transferir un PFX — la contraseña se transmite por un canal separado.
  • No pongas la clave en el repositorio. Si eso ocurre, la clave se considera comprometida: hay que revocar el certificado y emitir uno nuevo con una clave nueva.
  • Al emitir un nuevo certificado es recomendable generar también una clave nueva.

// Tarea parecida

Si estas resolviendo algo parecido

Este articulo pertenece a uno de los temas principales de trabajo. Puedes seguir leyendo sobre el tema, ir a la pagina principal para entender a que me dedico o abrir directamente los servicios.

Tema del articulo

Seguridad y proteccion

SSL, hardening, accesos, proteccion de servicios y configuraciones seguras.

Tareas frecuentes de esta tema

  • Configurar SSL, certificados y conexiones seguras
  • Restringir accesos y cerrar puntos de entrada innecesarios
  • Reforzar la configuracion del servidor y los servicios

// Siguiente paso

Si necesitas ayuda con este tema y no solo otro articulo, es mejor ir directo a la pagina del servicio. La pagina principal y la seleccion de materiales quedan como rutas secundarias.

Abrir servicios

// Reviews

Reseñas relacionadas

apande

apande

Configuración de Nginx y OpenCart

07.09.2024 · ★ 5/5

Un comprador muy poderoso
kireevk

kireevk

Diagnóstico de Nginx Proxy Manager en un contenedor Docker y solución del problema

15.03.2024 · ★ 5/5

Comprador acostumbrado

// Contact

¿Necesitas ayuda?

Escríbeme y te ayudaré a resolver el problema

Respondo en un día laborable (03:00-13:00 GMT)

O deje su solicitud aquí:

Confirme que no es un bot.

Escribir y recibir una respuesta rápida