Pular para o conteúdo
ecdsa.com

PEM vs DER: o mesmo certificado em texto ou binário

O DER é a codificação ASN.1 binária em que certificados e chaves são definidos. O PEM é esse mesmo DER, codificado em base64 entre as linhas BEGIN e END. A conversão não altera nada do conteúdo.

PEM vs DER não é uma escolha entre dados diferentes: um certificado, uma chave, um CSR ou uma CRL são sempre definidos como ASN.1 codificado em DER, e o PEM é um invólucro de texto em torno exatamente desses bytes. A questão é qual representação uma ferramenta, um protocolo ou uma plataforma espera, e como reconhecer e converter cada uma.

Visão geral

DERPEM
O que éDistinguished Encoding Rules do ASN.1 (ITU-T X.690): tag-length-value binárioTexto da RFC 7468: base64 do DER entre rótulos
Começa comByte 0x30 (SEQUENCE) em certificados e chaves-----BEGIN CERTIFICATE-----, -----BEGIN PRIVATE KEY----- etc.
Tamanho (certificado P-256, medido)389 bytes583 bytes (cerca de 4/3, mais quebras de linha e rótulos)
Objetos por arquivoUmQualquer número de blocos (cadeias, chave mais certificado)
AutodescritivoSem rótulo; o tipo vem do contextoO rótulo nomeia a estrutura
Extensões comuns.der, .cer, .crt (ambíguas).pem, .crt, .cer, .key, .csr (ambíguas)
Impressão digitalSHA-256 destes bytesMesmo valor: as impressões digitais são calculadas sobre o DER interno
Seguro em e-mail, YAML, variáveis de ambienteNãoSim

O que é cada um

O DER é a codificação binária canônica de dados ASN.1: cada valor é uma tag, um comprimento e um conteúdo, com exatamente uma codificação válida por valor. É essa propriedade canônica que faz as assinaturas funcionarem: a assinatura de um certificado cobre os bytes DER do seu tbsCertificate, e os verificadores não recodificam nada.

O PEM (cujo nome vem do padrão Privacy-Enhanced Mail, de 1993, e que a RFC 7468 especifica para objetos PKIX) envolve esses bytes em base64 padrão, por convenção com 64 caracteres por linha, entre uma linha BEGIN e uma linha END que nomeiam a estrutura: CERTIFICATE, X509 CRL, CERTIFICATE REQUEST, PUBLIC KEY, PRIVATE KEY, ENCRYPTED PRIVATE KEY, além dos rótulos legados do OpenSSL, RSA PRIVATE KEY e EC PRIVATE KEY. O texto antes, entre ou depois dos blocos é ignorado, e é por isso que funcionam os bundles com comentários e a saída de openssl x509 -text.

Conversão e verificação

O script abaixo, executado com o OpenSSL 3.6.5, cria um certificado descartável e mostra que as duas codificações carregam o mesmo objeto.

OpenSSL: um certificado em PEM e em DER
#!/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"
Saída
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:

O mesmo padrão vale para chaves (openssl pkey -in key.pem -outform DER), CSRs (openssl req -outform DER) e CRLs (openssl crl -outform DER). Para identificar um arquivo desconhecido: se ele começa com -----BEGIN, é PEM; se xxd file | head -1 mostra 3082 perto do início, é quase certamente DER.

Erros típicos

  • no start line / Expecting: TRUSTED CERTIFICATE no OpenSSL: a ferramenta esperava PEM e recebeu DER, ou um bloco PEM com outro rótulo. Adicione -inform DER ou confira o rótulo.
  • header too long / wrong tag: a ferramenta esperava DER e recebeu texto PEM, ou um arquivo truncado.
  • Quebras de linha do Windows ou espaços soltos dentro de um bloco PEM colado em um formulário web ou em YAML; parsers estritos os rejeitam. Recodifique em vez de editar à mão.
  • Um bundle PEM onde se esperava um único certificado: muitas ferramentas leem apenas o primeiro bloco, então a ordem importa (nos servidores, o certificado folha vem primeiro).
  • Base64url em vez de base64: o PEM usa o alfabeto padrão, com +, / e padding; o JOSE e o WebAuthn usam base64url. Um certificado copiado do membro x5c de uma JWK é DER em base64 padrão, e envolvê-lo nas linhas PEM o transforma em um arquivo PEM válido.

O explorador de ASN.1 aceita qualquer uma das duas codificações e mostra a estrutura, e o divisor de pacotes PEM separa arquivos com vários certificados.

Bundles e cadeias

Como o DER contém exatamente um objeto, tudo o que precisa de vários objetos em um só arquivo usa concatenação de PEM ou um formato de contêiner. O fullchain.pem de um servidor é o certificado folha seguido dos intermediários; um bundle de CAs como /etc/ssl/certs/ca-certificates.crt reúne centenas de certificados raiz em um único arquivo PEM. As alternativas baseadas em DER são os bundles de certificados PKCS #7 (.p7b, um SignedData do CMS sem conteúdo e só com certificados, comum no Windows) e o PKCS #12 (.pfx), quando uma chave privada viaja junto com a cadeia. Para converter um .p7b em PEM, use openssl pkcs7 -print_certs -in bundle.p7b, que grava cada certificado em um bloco PEM próprio.

A ordem e a completude importam mais que a codificação: um servidor deve enviar o certificado folha primeiro, além de todos os intermediários necessários para chegar a uma raiz em que os clientes confiam, e a falta de um intermediário quebra os clientes que não o buscam por conta própria, seja qual for o formato do arquivo.

Quando escolher cada um

  • Servidores web, proxies reversos, clientes ACME: PEM (fullchain.pem, privkey.pem).
  • Java (keytool -importcert, CertificateFactory): qualquer um dos dois, mas o DER é a entrada canônica; os keystores usam PKCS #12 para chave mais cadeia.
  • Importação de certificados no Windows: .cer em DER ou .cer codificado em PEM; chave mais certificado vão em um .pfx.
  • Incorporação em código-fonte, variáveis de ambiente, Secrets do Kubernetes: texto PEM (ou DER em base64, se um campo exigir).
  • Protocolos de rede e contêineres binários: DER, sempre; TLS, CMS, OCSP e as extensões X.509 nunca transportam PEM.
  • Arquivamento e auditoria: DER para armazenamento exato, byte a byte; PEM se pessoas precisarem inspecionar os arquivos.

Notas de migração

Não há nada a migrar no sentido criptográfico; trocar de codificação é um detalhe de implantação.

  1. Padronize os nomes de arquivo: .pem para PEM, .der para DER, e evite as extensões ambíguas .crt e .cer nas suas próprias ferramentas.
  2. Converta no momento da implantação, mantendo uma única fonte da verdade (normalmente PEM) no seu repositório ou cofre de segredos.
  3. Confira as impressões digitais depois da conversão com openssl x509 -noout -fingerprint -sha256; elas devem ser iguais.
  4. Em chaves privadas, mantenha a criptografia ativada: openssl pkey -outform DER grava uma chave não criptografada, a menos que você passe uma cifra, e as ferramentas costumam manipular chaves DER com menos avisos.
  5. Documente os formatos esperados na configuração (ssl_certificate espera PEM; os truststores do Java esperam DER ou PKCS #12), já que a maioria dos erros de formato vem de suposições.

Referências

Todas as comparações