PEM frente a DER no es una elección entre datos distintos: un certificado, una clave, una CSR o una CRL se definen siempre como ASN.1 codificado en DER, y PEM es un envoltorio de texto alrededor de esos mismos bytes. La cuestión es qué representación espera una herramienta, un protocolo o una plataforma, y cómo reconocer y convertir cada una.
De un vistazo
| DER | PEM | |
|---|---|---|
| Qué es | Distinguished Encoding Rules de ASN.1 (ITU-T X.690): etiqueta, longitud y valor en binario | Texto del RFC 7468: base64 de DER entre etiquetas |
| Empieza por | El byte 0x30 (SEQUENCE) en certificados y claves | -----BEGIN CERTIFICATE-----, -----BEGIN PRIVATE KEY-----, etc. |
| Tamaño (certificado P-256, medido) | 389 bytes | 583 bytes (unos 4/3 más los saltos de línea y las etiquetas) |
| Objetos por archivo | Uno | Cualquier número de bloques (cadenas, clave más certificado) |
| Autodescriptivo | Sin etiqueta; el tipo se deduce del contexto | La etiqueta nombra la estructura |
| Extensiones habituales | .der, .cer, .crt (ambiguas) | .pem, .crt, .cer, .key, .csr (ambiguas) |
| Huella digital | SHA-256 de estos bytes | El mismo valor: las huellas se calculan sobre el DER del interior |
| Seguro en correo electrónico, YAML, variables de entorno | No | Sí |
Qué es cada uno
DER es la codificación binaria canónica de los datos ASN.1: cada valor es una etiqueta, una longitud y un contenido, con exactamente una codificación válida por valor. Esa propiedad canónica es lo que hace que las firmas funcionen: la firma de un certificado cubre los bytes DER de su tbsCertificate, y los verificadores no vuelven a codificar nada.
PEM —que toma su nombre del estándar Privacy-Enhanced Mail (correo con privacidad mejorada) de 1993 y que el RFC 7468 especifica para los objetos PKIX— envuelve esos bytes en base64 estándar, por convención con 64 caracteres por línea, entre una línea BEGIN y una línea END que nombran la estructura: CERTIFICATE, X509 CRL, CERTIFICATE REQUEST, PUBLIC KEY, PRIVATE KEY, ENCRYPTED PRIVATE KEY, además de las etiquetas heredadas de OpenSSL RSA PRIVATE KEY y EC PRIVATE KEY. El texto antes, entre o después de los bloques se ignora, y gracias a eso funcionan los bundles con comentarios y la salida de openssl x509 -text.
Conversión y comprobación
El script siguiente, ejecutado con OpenSSL 3.6.5, crea un certificado desechable y muestra que ambas codificaciones contienen el mismo objeto.
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
openssl req -new -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout key.pem \
-subj "/CN=example.com" -days 30 -out cert.pem 2>/dev/null
openssl x509 -in cert.pem -outform DER -out cert.der
printf 'cert.pem %s bytes, cert.der %s bytes\n' "$(wc -c < cert.pem | tr -d ' ')" "$(wc -c < cert.der | tr -d ' ')"
head -1 cert.pem
openssl x509 -in cert.der -inform DER -noout -fingerprint -sha256 | cut -c1-40
openssl x509 -in cert.pem -noout -fingerprint -sha256 | cut -c1-40
cd / && rm -rf "$dir"
cert.pem 583 bytes, cert.der 389 bytes
-----BEGIN CERTIFICATE-----
sha256 Fingerprint=FE:8B:DC:19:30:EE:A8:
sha256 Fingerprint=FE:8B:DC:19:30:EE:A8:
El mismo patrón se aplica a las claves (openssl pkey -in key.pem -outform DER), las CSR (openssl req -outform DER) y las CRL (openssl crl -outform DER). Para identificar un archivo desconocido: si empieza por -----BEGIN, es PEM; si xxd file | head -1 muestra 3082 cerca del principio, es casi seguro DER.
Errores típicos
no start line/Expecting: TRUSTED CERTIFICATEde OpenSSL: la herramienta esperaba PEM y recibió DER, o un bloque PEM con otra etiqueta. Añade-inform DERo comprueba la etiqueta.header too long/wrong tag: la herramienta esperaba DER y recibió texto PEM, o un archivo truncado.- Finales de línea de Windows o espacios sueltos dentro de un bloque PEM pegado en un formulario web o en YAML; los analizadores estrictos los rechazan. Vuelve a codificarlo en lugar de editarlo a mano.
- Un bundle PEM donde se esperaba un solo certificado: muchas herramientas solo leen el primer bloque, así que el orden importa (en los servidores, primero el certificado hoja).
- Base64url en lugar de base64: PEM usa el alfabeto estándar con
+,/y relleno; JOSE y WebAuthn usan base64url. Un certificado copiado del miembrox5cde una JWK es DER en base64 estándar, y envolverlo en líneas PEM lo convierte en un archivo PEM válido.
El explorador de ASN.1 acepta cualquiera de las dos codificaciones y muestra la estructura, y el divisor de bundles PEM separa los archivos con varios certificados.
Bundles y cadenas
Como DER contiene exactamente un objeto, todo lo que necesita varios objetos en un archivo usa la concatenación de PEM o un formato contenedor. El fullchain.pem de un servidor es el certificado hoja seguido de los intermedios; un bundle de CA como /etc/ssl/certs/ca-certificates.crt reúne cientos de certificados raíz en un solo archivo PEM. Las alternativas basadas en DER son los bundles de certificados PKCS #7 (.p7b, un SignedData de CMS sin contenido y solo con certificados, habitual en Windows) y PKCS #12 (.pfx) cuando una clave privada viaja con la cadena. Para convertir un .p7b a PEM se usa openssl pkcs7 -print_certs -in bundle.p7b, que escribe cada certificado como un bloque PEM propio.
El orden y la completitud importan más que la codificación: un servidor debe enviar primero su certificado hoja y todos los intermedios necesarios para llegar a una raíz en la que confíen los clientes, y si falta un intermedio, fallan los clientes que no lo descargan por sí mismos, sea cual sea el formato del archivo.
Cuándo elegir cada uno
- Servidores web, proxies inversos, clientes ACME: PEM (
fullchain.pem,privkey.pem). - Java (
keytool -importcert,CertificateFactory): cualquiera de los dos, aunque DER es la entrada canónica; los almacenes de claves usan PKCS #12 para la clave junto con la cadena. - Importación de certificados en Windows:
.ceren DER o.cercodificado en PEM; la clave junto con el certificado va en un.pfx. - Inserción en código fuente, variables de entorno, secretos de Kubernetes: texto PEM (o DER en base64, si un campo lo exige).
- Protocolos de red y contenedores binarios: DER, siempre; TLS, CMS, OCSP y las extensiones X.509 nunca transportan PEM.
- Archivado y auditoría: DER para un almacenamiento exacto byte a byte; PEM si las personas necesitan inspeccionar los archivos.
Notas de migración
No hay nada que migrar en sentido criptográfico; cambiar de codificación es un detalle del despliegue.
- Unifica los nombres de archivo:
.pempara PEM,.derpara DER, y evita las ambiguas.crty.ceren tus propias herramientas. - Convierte en el momento del despliegue, con una única fuente de verdad (normalmente PEM) en tu repositorio o tu almacén de secretos.
- Comprueba las huellas digitales después de la conversión con
openssl x509 -noout -fingerprint -sha256; deben coincidir. - En las claves privadas, mantén el cifrado:
openssl pkey -outform DERescribe una clave sin cifrar a menos que indiques un algoritmo de cifrado, y las herramientas que manejan claves DER suelen mostrar menos advertencias. - Documenta los formatos esperados en la configuración (
ssl_certificateespera PEM; los almacenes de confianza de Java esperan DER o PKCS #12), ya que la mayoría de los errores de formato vienen de suponerlos.