Выбор между PEM и DER — это не выбор между разными данными: сертификат, ключ, CSR или CRL всегда определяется как ASN.1 в кодировке DER, а PEM — текстовая обёртка вокруг тех же самых байтов. Вопрос лишь в том, какое представление нужно инструменту, протоколу или платформе и как распознать и конвертировать каждое из них.
Коротко о главном
| DER | PEM | |
|---|---|---|
| Что это | Distinguished Encoding Rules для ASN.1 (ITU-T X.690): двоичный формат тег-длина-значение | Текст по RFC 7468: base64 от DER между метками |
| Начинается с | Байта 0x30 (SEQUENCE) у сертификатов и ключей | -----BEGIN CERTIFICATE-----, -----BEGIN PRIVATE KEY----- и т. д. |
| Размер (сертификат P-256, замер) | 389 байт | 583 байта (примерно 4/3 плюс переводы строк и метки) |
| Объектов в файле | Один | Сколько угодно блоков (цепочки, ключ вместе с сертификатом) |
| Самоописываемость | Метки нет; тип известен из контекста | Метка называет структуру |
| Типичные расширения | .der, .cer, .crt (неоднозначно) | .pem, .crt, .cer, .key, .csr (неоднозначно) |
| Отпечаток | SHA-256 от этих байтов | То же значение: отпечатки вычисляются по DER внутри |
| Можно без опаски вставлять в письма, YAML, переменные окружения | Нет | Да |
Что представляет собой каждый формат
DER — каноническая двоичная кодировка данных ASN.1: каждое значение состоит из тега, длины и содержимого, и у каждого значения ровно одна допустимая кодировка. Именно благодаря каноничности работают подписи: подпись сертификата покрывает DER-байты его tbsCertificate, и проверяющим сторонам ничего не нужно перекодировать.
PEM (название восходит к стандарту Privacy-Enhanced Mail 1993 года, а для объектов PKIX формат определён в RFC 7468) кодирует эти байты стандартным base64, по традиции по 64 символа в строке, и помещает их между строками BEGIN и END, которые называют структуру: CERTIFICATE, X509 CRL, CERTIFICATE REQUEST, PUBLIC KEY, PRIVATE KEY, ENCRYPTED PRIVATE KEY, а также устаревшие метки OpenSSL RSA PRIVATE KEY и EC PRIVATE KEY. Текст до блоков, между ними и после них игнорируется, поэтому и работают пакеты с комментариями и вывод openssl x509 -text.
Конвертация и проверка
Скрипт ниже, запущенный с OpenSSL 3.6.5, создаёт одноразовый сертификат и показывает, что обе кодировки содержат один и тот же объект.
#!/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:
Так же конвертируются ключи (openssl pkey -in key.pem -outform DER), CSR (openssl req -outform DER) и CRL (openssl crl -outform DER). Как определить формат неизвестного файла: если он начинается с -----BEGIN, это PEM; если xxd file | head -1 показывает 3082 в начале, это почти наверняка DER.
Типичные ошибки
no start line/Expecting: TRUSTED CERTIFICATEот OpenSSL: инструмент ожидал PEM, а получил DER или блок PEM с другой меткой. Добавьте-inform DERили проверьте метку.header too long/wrong tag: инструмент ожидал DER, а получил текст PEM или обрезанный файл.- Переводы строк в стиле Windows или лишние пробелы внутри блока PEM, вставленного в веб-форму или YAML; строгие парсеры такие блоки отклоняют. Перекодируйте данные, а не правьте их вручную.
- PEM-пакет там, где ожидался один сертификат: многие инструменты читают только первый блок, поэтому порядок важен (для серверов первым идёт конечный сертификат).
- Base64url вместо base64: PEM использует стандартный алфавит с
+,/и дополнением, а JOSE и WebAuthn — base64url. Сертификат, скопированный из элементаx5cв JWK, — это DER в стандартном base64, и если обернуть его строками PEM, получится корректный PEM-файл.
Просмотр структуры ASN.1 принимает обе кодировки и показывает структуру, а разделитель PEM-пакетов разбирает файлы с несколькими сертификатами на отдельные блоки.
Пакеты и цепочки
Поскольку DER вмещает ровно один объект, всё, что требует нескольких объектов в одном файле, использует склейку блоков PEM или формат-контейнер. Файл сервера fullchain.pem — это конечный сертификат, за которым следуют промежуточные; пакет сертификатов CA, например /etc/ssl/certs/ca-certificates.crt, — это сотни корневых сертификатов в одном PEM-файле. Альтернативы на основе DER — пакеты сертификатов PKCS #7 (.p7b, структура CMS SignedData без содержимого, только с сертификатами; распространены в Windows) и PKCS #12 (.pfx), когда вместе с цепочкой передаётся закрытый ключ. .p7b конвертируется в PEM командой openssl pkcs7 -print_certs -in bundle.p7b, которая записывает каждый сертификат отдельным блоком PEM.
Порядок и полнота важнее кодировки: сервер должен отправлять сначала свой конечный сертификат, а затем все промежуточные, которые нужны, чтобы дойти до корневого сертификата, которому доверяют клиенты; без нужного промежуточного сертификата перестают работать клиенты, которые не загружают его сами, в каком бы формате ни был файл.
Что когда выбирать
- Веб-серверы, обратные прокси, клиенты ACME: PEM (
fullchain.pem,privkey.pem). - Java (
keytool -importcert,CertificateFactory): подходят оба, но каноническими входными данными считается DER; в хранилищах ключей ключ вместе с цепочкой хранится в формате PKCS #12. - Импорт сертификатов в Windows:
.cerв DER или.cerв кодировке PEM; ключ вместе с сертификатом помещают в.pfx. - Встраивание в исходный код, переменные окружения, секреты Kubernetes: текст PEM (или DER в base64, если этого требует поле).
- Сетевые протоколы и двоичные контейнеры: всегда DER; в TLS, CMS, OCSP и расширениях X.509 PEM не встречается никогда.
- Архивирование и аудит: DER для хранения с точностью до байта; PEM, если файлы должны просматривать люди.
Заметки о миграции
В криптографическом смысле мигрировать нечего: смена кодировки — деталь развёртывания.
- Унифицируйте имена файлов:
.pemдля PEM,.derдля DER; в собственных инструментах избегайте неоднозначных.crtи.cer. - Конвертируйте при развёртывании, а единственный источник истины (обычно PEM) храните в репозитории или хранилище секретов.
- Сверяйте отпечатки после конвертации командой
openssl x509 -noout -fingerprint -sha256: они должны совпадать. - Не отключайте шифрование закрытых ключей:
openssl pkey -outform DERзаписывает ключ без шифрования, если не указать шифр, а ключи в DER инструменты часто обрабатывают с меньшим числом предупреждений. - Фиксируйте ожидаемые форматы в конфигурации (для
ssl_certificateнужен PEM, для хранилищ доверенных сертификатов Java — DER или PKCS #12): большинство ошибок формата возникает из-за догадок.