Сертификат X.509
Сервер предъявляет сертификат, и прошивка должна решить, верить ли ему: проверить подпись цепочки до корневого сертификата из флеш, сверить имя и убедиться, что срок действия не истёк. Последнее невозможно без часов — отсюда связка TLS и SNTP на любом контроллере.
Обновлено Редакция GAW
Сертификат X.509 — подписанный удостоверяющим центром (CA) документ, который связывает открытый ключ с именем его владельца на заданный срок действия. Профиль для интернета задаёт RFC 5280; именно такие сертификаты сервер предъявляет клиенту в рукопожатии TLS, а клиент решает, доверять ли ему, проверяя цепочку подписей до корневого сертификата из собственного хранилища.
Что внутри
По RFC 5280 (разд. 4.1) сертификат состоит из трёх частей: tbsCertificate — подписываемые данные, signatureAlgorithm — алгоритм подписи и signatureValue — сама подпись CA. Подписываемые данные кодируются по правилам DER; то, что обычно лежит в файле .pem, — это тот же DER, записанный в Base64.
| Поле tbsCertificate | Назначение (RFC 5280) |
|---|---|
| version | версия; при расширениях обязана быть 3 (разд. 4.1.2.1) |
| serialNumber | положительное целое, уникальное у данного CA, до 20 октетов (разд. 4.1.2.2) |
| issuer | имя удостоверяющего центра |
| validity | notBefore и notAfter, срок включительно (разд. 4.1.2.5) |
| subject | имя владельца |
| subjectPublicKeyInfo | алгоритм и открытый ключ |
| extensions | subjectAltName с DNS-именем или IP-адресом, basicConstraints с флагом cA, keyUsage, extendedKeyUsage |
Даты до 2049 года включительно записываются типом UTCTime (двузначный год), с 2050-го — GeneralizedTime; обе — по Гринвичу и с секундами. Для устройств, которым нельзя назначить разумный срок, RFC рекомендует notAfter = 99991231235959Z. Подпись покрывает дайджест данных от хеш-функции, поэтому изменить хоть байт в сертификате, не владея ключом CA, нельзя.
Цепочка и якорь доверия
Клиент редко хранит сертификат конкретного сервера. Он хранит якорь доверия — корневой сертификат CA — и проверяет путь сертификации (разд. 6.1): последовательность, в которой субъект каждого сертификата является издателем следующего, первый выпущен якорем доверия, последний — проверяемый, и все действительны на момент проверки. Сам якорь в путь не входит, а его выбор RFC называет вопросом политики: для прошивки это ответ на вопрос, какие корни положить во флеш. Для каждого звена проверяются подпись, срок, отсутствие отзыва и имя издателя (разд. 6.1.3), а сертификат с неизвестным критическим расширением обязаны отвергнуть. Промежуточный CA должен иметь basicConstraints с флагом cA, иначе его ключом нельзя подписывать другие сертификаты (разд. 4.2.1.9).
На микроконтроллере
Две практические трудности — хранилище корней и время. ESP-IDF встраивает в прошивку пакет корневых сертификатов из хранилища Mozilla NSS: полный, более 130 штук, или фильтр примерно из 38 самых распространённых, покрывающих около 93 % использования; во флеш попадают только имя субъекта и открытый ключ каждого корня, а обновляется пакет вместе с приложением при обновлении по воздуху. В ESP-TLS сервер проверяют через cacert_buf, глобальное хранилище CA или crt_bundle_attach, а поле common_name задаёт имя для SNI и сверки с сертификатом.
Проверка срока действия в mbedTLS на ESP32 включается опцией CONFIG_MBEDTLS_HAVE_TIME_DATE — по умолчанию она выключена, и даты сертификата игнорируются. При включении прошивка обязана выставить системные часы до первого соединения: документация рекомендует SNTP, а неверное время даёт ошибки MBEDTLS_X509_BADCERT_FUTURE или MBEDTLS_X509_BADCERT_EXPIRED. Если точного времени нет — нет сети до самого TLS или сервер времени недоступен, — помогают часы реального времени с батарейным питанием, но Espressif отдельно предупреждает о двух ловушках: корневые сертификаты могут истечь, пока устройство лежит офлайн, а сбой SNTP оставляет время неверным надолго после сброса. Когда клиентов и серверов немного и обе стороны настраиваются вручную, от сертификатов отказываются в пользу TLS-PSK.
Частые вопросы
Что проверяет клиент, получив сертификат сервера?
По RFC 5280 (разд. 6.1.3) для каждого сертификата в цепочке — что подпись проверяется открытым ключом издателя, что текущее время попадает в срок действия, что сертификат не отозван и что имя издателя совпадает с субъектом предыдущего. Цепочка должна начинаться с сертификата, выпущенного якорем доверия, — корневым сертификатом, который хранится у клиента. Сверх этого клиент TLS сопоставляет имя сервера с subjectAltName; в ESP-TLS за это отвечает поле common_name при skip_common_name = false.
Почему микроконтроллеру для TLS нужно знать время?
Потому что проверка срока действия сравнивает notBefore и notAfter с текущим временем. После сброса часы контроллера показывают 1970 год или случайное значение, и сертификат окажется «ещё не действителен» или «просрочен». В ESP-IDF проверка включается опцией CONFIG_MBEDTLS_HAVE_TIME_DATE (по умолчанию выключена, даты игнорируются), и документация требует выставить часы до первого TLS-соединения, рекомендуя SNTP; ошибки — MBEDTLS_X509_BADCERT_FUTURE и MBEDTLS_X509_BADCERT_EXPIRED.
Сколько живёт сертификат и что будет, когда он истечёт?
Срок задаёт издатель в полях notBefore и notAfter, обе границы включительно. У сертификатов устройств, которым разумный срок назначить нельзя, RFC 5280 рекомендует notAfter = 99991231235959Z, то есть «бессрочно». Для прошивки опаснее истечение не серверного, а корневого сертификата из флеш: Espressif предупреждает, что все доверенные сертификаты могут истечь, пока устройство офлайн, и тогда соединение для обновления не установится. Поэтому пакет корневых сертификатов обновляют вместе с прошивкой по OTA.
Источники
- IETF. RFC 5280 Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. D. Cooper et al., May 2008 — разд. 4.1: Certificate = tbsCertificate, signatureAlgorithm, signatureValue; подписываемые данные кодируются DER; TBSCertificate содержит version, serialNumber, signature, issuer, validity (notBefore, notAfter), subject, subjectPublicKeyInfo, необязательные идентификаторы и extensions (только в v3); разд. 4.1.2.1: при наличии расширений версия обязана быть 3 (значение 2), реализации обязаны принимать v3; разд. 4.1.2.2: серийный номер — положительное целое, уникальное у данного CA, пользователи обязаны принимать номера до 20 октетов; разд. 4.1.2.5: срок действия — от notBefore до notAfter включительно, даты до 2049 года кодируются UTCTime, с 2050 — GeneralizedTime, обе в Гринвиче с секундами; для устройств без разумного срока notAfter следует задавать 99991231235959Z; разд. 4.2.1.6: subjectAltName — DNS-имя, IP-адрес, URI, e-mail; разд. 4.2.1.9: basicConstraints с флагом cA и pathLenConstraint; разд. 4.2.1.12: extendedKeyUsage — назначения ключа, обычно в сертификатах конечных субъектов; разд. 6.1: путь сертификации — последовательность, где субъект сертификата x является издателем x+1, первый выпущен якорем доверия, последний — проверяемый, и каждый действителен на момент проверки; якорь доверия (самоподписанный сертификат) в путь не входит, его выбор — вопрос политики; разд. 6.1.3 (a): проверяются подпись, попадание текущего времени в срок действия, отсутствие отзыва, имя издателя; клиенты обязаны отвергать сертификат с неподдерживаемым критическим расширением
- Espressif. ESP-IDF Programming Guide v6.1, ESP32: Configuration Options Reference (Component config > mbedTLS); ESP x509 Certificate Bundle; ESP-TLS — CONFIG_MBEDTLS_HAVE_TIME_DATE — проверка срока действия сертификатов X.509 в mbedTLS, по умолчанию выключена: поля valid from и valid to игнорируются; при включении сравниваются с системным временем через time() и gmtime(), при несовпадении проверка завершается кодами MBEDTLS_X509_BADCERT_FUTURE или MBEDTLS_X509_BADCERT_EXPIRED; прошивка обязана выставить часы до использования TLS, рекомендуемый способ — SNTP; оговорка: все доверенные сертификаты могут истечь, пока устройство офлайн, а сбой SNTP оставит время неверным надолго; CONFIG_MBEDTLS_HAVE_TIME — относительное время для истечения билетов сеанса, верных часов не требует; страница ESP x509 Certificate Bundle: пакет корневых сертификатов из хранилища Mozilla NSS — полный более 130 сертификатов (обновлён 11 февраля 2026) или фильтр около 38 самых распространённых (около 93 % использования), в двоичный файл встраиваются имя субъекта и открытый ключ, пакет обновляется вместе с приложением по OTA; ESP-TLS: сервер проверяют по cacert_buf, глобальному хранилищу CA или crt_bundle_attach, поле common_name задаёт имя для SNI и сверки с сертификатом, skip_common_name = false
Нашли ошибку? ·
Смотрите также
- TLSШифрованный канал поверх TCP: рукопожатие, сертификаты, буферы и время на МК
- TLS-PSKАутентификация TLS общим секретом: наборы по RFC 4279, режимы TLS 1.3, зачем на МК и чем платят
- SNTPПодмножество NTPv4 для клиентов с одним сервером: пакет 48 байт, порт 123, 64-битная метка времени с 1900 года
- RTCСчётчик времени в режимах сна: источники такта, счётчик и календарь
- Криптографическая хеш-функция (SHA)Функция, сжимающая сообщение в дайджест, к которому нельзя подобрать другое сообщение
- Base64Запись двоичных данных 64 печатными символами: алфавит, группы по 3 байта, дополнение «=», base64url
- OTA (обновление по воздуху)Обновление прошивки ESP32 из работающей программы по сети
- ESP32ESP32, S2, S3, C2, C3, C5, C6, H2, P4: ядра, радио, USB, GPIO — сравнение и выбор