Что такое сертификат
Сертификат X.509 — это подписанное заявление, связывающее открытый ключ с идентичностью. Когда браузер подключается к сайту по HTTPS, сервер предъявляет сертификат, который, по сути, говорит: «этот открытый ключ принадлежит test.ronutz.com, и удостоверяющий центр за это ручается». Профиль, определяющий, какие поля несёт сертификат и как они интерпретируются, — это RFC 5280.
Связывание — вот что важно. Любой может сгенерировать пару ключей, так что голый открытый ключ ничего не доказывает о том, кто на другом конце. Сертификат добавляет подпись издателя, которому полагающаяся сторона уже доверяет, превращая анонимный ключ в ключ с прикреплённым именем. Это основа веб-инфраструктуры открытых ключей ().
Цепочка доверия
Одному сертификату редко доверяют самому по себе. Ему доверяют, потому что он был подписан издателем, который, в свою очередь, был подписан другим издателем, вверх до корня, который полагающаяся сторона уже держит в хранилище доверия:
Root CA (self-signed, in the OS/browser trust store)
| signs
Intermediate CA
| signs
Leaf / end-entity certificate (test.ronutz.com)
Каждое звено — это подпись: издатель подписывает сертификат потомка приватным ключом издателя, а проверяющий сверяет эту подпись открытым ключом издателя. Корень самовыпущен и самоподписан, поэтому самоподписанный сертификат — полезный локальный заменитель корня, но не несёт никакого внешнего авторитета. Инструмент X.509 отмечает самовыпущенный сертификат (издатель равен субъекту) и помечен ли сертификат как , и то и другое говорит вам, где сертификат находится на этой картине.
ASN.1 и DER: раскладка байтов
Сертификат — это не JSON и не текст. Он описан в .1 (Abstract Syntax Notation One) и закодирован Distinguished Encoding Rules (), определёнными в ITU-T X.690. DER — это формат tag-length-value (TLV): каждый элемент начинается с байта тега, говорящего, какого он типа, затем длина, затем столько байтов содержимого. Конструируемые типы вроде SEQUENCE и SET содержат дочерние элементы, так что весь сертификат — это дерево TLV.
Файл — это просто тот DER, закодированный в Base64 и обёрнутый в строки брони:
-----BEGIN CERTIFICATE-----
MIIELDCCAxSgAwIBAgIG... (Base64 of the DER)
-----END CERTIFICATE-----
Так что декодировать сертификат означает снять броню, декодировать из Base64 в DER, а затем обойти дерево TLV. Инструмент X.509 делает ровно это в вашем браузере, без библиотеки и без сетевого вызова.
Структура верхнего уровня
На самом внешнем уровне RFC 5280 определяет три части:
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING
}
tbsCertificate («to be signed», подлежащий подписи) содержит всё реальное содержимое. signatureAlgorithm называет, как издатель его подписал, например sha256WithRSAEncryption или ecdsa-with-SHA256. signatureValue — это сама подпись, вычисленная над байтами DER tbsCertificate. За этот последний пункт стоит держаться: подпись покрывает подлежащее-подписи тело ровно так, как закодировано, поэтому даже изменение в один байт где угодно в теле ломает проверку.
Внутри TBSCertificate
Подлежащее-подписи тело — это где инструмент проводит большую часть своего времени:
- Версия почти всегда v3, версия, которая ввела расширения.
- Серийный номер — большое целое число, которое назначает издатель. В сочетании с именем издателя он однозначно идентифицирует сертификат, и именно на него ссылается список отзыва.
- Издатель (Issuer) и Субъект (Subject) — это Различающие Имена (Distinguished Names). DN — это последовательность атрибутов вроде CN (common name), O (organization), OU (organizational unit), L (locality), ST (state) и C (country). RFC 4514 определяет однострочное, наиболее-конкретное-сначала отображение, которое вы видите, например
CN=test.ronutz.com, O=NTZ Technology, C=BR. - Срок действия (Validity) — это метки времени notBefore и notAfter. Они закодированы как UTCTime или GeneralizedTime; инструмент конвертирует обе в ISO-8601 и, против ваших локальных часов, говорит вам, действителен ли сертификат сейчас, ещё-не-действителен или истёк.
- subjectPublicKeyInfo несёт открытый ключ плюс его алгоритм. Для инструмент сообщает размер модуля (например, 2048-bit) и открытую экспоненту (почти всегда 65537). Для ключей на эллиптических кривых он сообщает именованную кривую (P-256, P-384, P-521), согласно RFC 5480.
Расширения v3
Расширения — это где современные сертификаты кодируют большую часть своей политики. У каждого расширения есть идентификатор, флаг критичности и значение. Флаг критичности важен: если полагающаяся сторона не понимает расширение, помеченное как критическое, она должна отклонить сертификат, а не игнорировать поле. Инструмент декодирует те, что несут наибольший вес:
- Subject Alternative Name () перечисляет идентичности, для которых сертификат действительно действителен, как DNS-имена, IP-адреса, адреса email или URI. Для TLS это поле, которое проверяют браузеры, а не CN. Сертификат для
test.ronutz.com, который опускает это имя из своего SAN, провалит проверку в современном клиенте, даже если CN совпадает. - Key Usage ограничивает то, что ключ может делать на низком уровне: digitalSignature, keyEncipherment, keyCertSign, cRLSign и другие. Сертификат CA несёт keyCertSign; лист TLS обычно несёт digitalSignature и keyEncipherment.
- Extended Key Usage (EKU) называет цели более высокого уровня вроде serverAuth (сервер TLS), clientAuth (клиент TLS), codeSigning или emailProtection.
- Basic Constraints заявляет, является ли сертификат CA, и если да, сколько промежуточных CA может появиться под ним (длина пути). Это поле останавливает использование листового сертификата для подписи других сертификатов.
- Subject Key Identifier и Authority Key Identifier — это хеши, позволяющие проверяющему быстро сопоставить сертификат с его издателем при построении цепочки.
Отпечатки
Отпечаток (fingerprint) сертификата — это просто криптографический хеш байтов DER сертификата, обычно (и, для более старых ссылок, SHA-1). Это не поле внутри сертификата; он вычисляется над всем целым. Отпечатки дают вам короткое значение фиксированной длины для сравнения двух сертификатов на равенство или для закрепления известного сертификата. Инструмент вычисляет и SHA-256, и SHA-1 локально с помощью Web Crypto API, так что байты, которые вы вставляете, никогда никуда не отправляются. Подробнее о том, чем хеш является и чем не является, см. статью о хешировании.
Декодирование — не проверка
Это единственная самая важная мысль, и она отражает ту же осторожность, что применяется к JSON Web Tokens. Чтение полей сертификата говорит вам, что он утверждает. Оно не говорит вам, что утверждение истинно. Полная проверка — это отдельный, более тяжёлый процесс: проверить, что подпись цепляется к доверенному корню, что ни один из сертификатов в цепочке не истёк и не отозван, что имя, к которому вы подключились, есть в SAN, и что использования ключа разрешают то, что вы делаете.
Декодировщик сертификатов, включая этот, — это инструмент инспекции и обучения. Он показывает вам в точности, что издатель утверждал и как это было закодировано. Относитесь к выводу как к точному прочтению документа, а не как к вердикту о том, доверять ли ему.