Ресурсы: техническое описание TLS, LaTeX - в картинки (img), криптографическая библиотека Arduino, шифр "Кузнечик" на ассемблере AMD64/AVX и ARM64
Отпечатки ключей и практика TLS
Удивительно, что во многих проектах, оказывается, TLS с сертификатами “из коробки” используется для подтверждения не только источника, но и подлинности важных данных (например, кода обновления и т.д.). То есть, если узел-источник аутентифицирован в рамках коробочного TLS, относительно внешних УЦ, то и все данные, полученные с этого узла, подлинные – потому что источник, как бы, подлинный. Cейчас этот момент, – “неожиданно!”, – обсуждается. Естественно, в свете истории с тривальными ключами удостоверяющего центра (УЦ) eMudhra, которые, несмотря на свою тривиальность, упешно и без вопросов были включены во все распространённые программы доверия CA/B-форума, в том числе, в браузеры от Google и Mozilla (к большому сожалению), где и находились больше года.
Вообще, если у вас приложение, которое скачивает обновления или ещё какие-то важные данные, то TLS тут можно и нужно использовать, но хорошо бы понимать, что и как там работает. То есть, тут однозначно нужен и key pinning, и дополнительное (помимо TLS!) удостоверение подлинности данных. То есть, данные в любом случае должны быть подписаны от доверенных ключей, и доверие должно быть зашито в приложение помимо внешней системы УЦ. Казалось бы, это хрестоматийные азы данного направления. И тем не менее – не везде таким правилам следуют.
Что такое key pinning? Это когда ваше приложение дополнительно сверяет отпечатки ключей сервера и, возможно, УЦ, с внутренними эталонами. Как и почему это работает? Если кто-то перехватил соединение и подменил сертификат сервера, то на стороне вашего приложения будет виден другой открытый ключ, не тот, который закреплён за подлинным сервером. Да, на этот открытый ключ будет выдан поддельный “доверенный” сертификат, для выпуска которого использовался скомпрометированный УЦ. Но ключ заведомо будет другим, что и позволит обнаружить подмену. Простое следование тому, что библиотека с системным хранилищем доверенных ключей подтвердила “подлинность TLS-сервера”, означает совсем не то, о чём, как оказывается, многие разработчики думают.
Действительно, даже в начале моего собственного описания TLS написано, буквально, следующее:
“TLS ставит своей целью создание между двумя узлами сети защищённого от прослушивания и подмены информации канала связи, пригодного для передачи произвольных данных в обоих направлениях, а также проверку того, что обмен данными происходит между именно теми узлами, для которых канал и планировался. Эти задачи называются, соответственно, обеспечением конфиденциальности, целостности и подлинности соединения (аутентификации).”
Тут всё написано верно. Но, похоже, надо будет добавить пояснения. Дело в том, что, да, одна из целей TLS – обеспечить проверку того, что “обмен данными происходит между именно теми узлами, для которых канал и планировался”. Но из этого не следует, что TLS-библиотека автоматически и прозрачно подтверждает подлинность узлов. TLS – это набор спецификаций. То, как с этими спецификациями живут библиотеки, – а тем более – списки доверенных ключей, – несколько другая история. TLS предоставляет возможности для аутентификации, которые описаны в протоколе. Но TLS, как спецификация, не гарантирует даже правильного понимания спецификаций.
Посудите сами. Во-первых, инфраструктура TLS-сертификатов находится за рамками TLS и имеет мало отношения именно к спецификации клиент-серверного TLS-соединения. Во-вторых, типичный “коробочный” процесс аутентификации узла использует некоторый внешний набор доверенных ключей. Обычно, этот набор является внешним даже для TLS-библиотеки! Аутентификация в TLS, на фундаментальном уровне, возможна только в отношении открытых ключей, а никак не IP-соединения. Соответственно, нужно понимать, что когда аутентификация выполняется библиотекой без должного внимания (без сравнения отпечатков), успех этой аутентификации означает не то, что “узел подлинный”, а, – внимание!, – то, что некоторый внешний игрок (УЦ) говорит, что узел с данным ключом и под данным именем контролирует тот же, кто подавал заявку на соответствующий сертификат. Это совсем другое! Почувствуйте, как говорится, разницу. Кому тут верит клиент? Конечно – УЦ, а не оконечному узлу.
В рамках TLS сервер передаёт свой открытый ключ и подтверждает, что знает соответствующий секретный ключ. То же самое может сделать и TLS-клиент. То есть, TLS предоставляет механизм для такого обмена: описывает, в какие блоки данных записывать ключи, в какие – записывать подписи, что именно подписывать, как обмениваться результатом. Но проверка того, что ключи действительно те самые, находится за пределами спецификации. Очевидно, спецификация универсального протокола не может ничего такого гарантировать – нельзя “прибить ключи” в спецификацию (хотя в библиотеки вот уже начали прибивать, но это – от непонимания).
Почему вообще возникает проблема? Потому что открытая схема использования TLS, – например, в вебе, для HTTPS, – предполагает, что клиент не может заранее узнать значения ключей. Это совершенно верное, логичное допущение. В нём и смысл – нужно сделать так, чтобы доверие можно было распространять на новые ключи ранее неизвестных узлов, автоматически. TLS это позволяет реализовать. Но нужно создать общий список доверенных ключей третьей стороны. Отсюда возникает инфрастурктура УЦ.
Однако это совсем другая история, по сравнению с загрузкой, например, конкретных обновлений в конкретное приложение (или на устройство, тем более). Там-то как раз заранее известно, что нужно верить только в определённые ключи, и ключи сами – известны. И замена ключей в такой схеме вполне возможна: всё это отработано годами (см. устройство браузеров, репозиториев ОС). Должны быть резервные ключи, новые ключи – подписываются от старых, и так далее: это никак не мешает ведению собственной, независимой от произвольного списка внешних УЦ, схемы.
Адрес записки: https://dxdt.blog/2026/10/24/19496/
Похожие записки:
- Сертификаты и их цепочки в вебе
- Новые квантовые атаки "на решётки" и ML-DSA/ML-KEM
- Реплика: LLM на IMO - ответ раньше решения
- Техническое: внутренние параметры ECDSA и значение k
- Языковые задачи и "третья ветка из двух"
- Машинный ИИ в книгах прошлого века
- Техническая реплика: наведённый антагонизм систем IP
- Сбой DNSSEC в .RU
- Реплика: DNS и ошибки
- Подозрительные TLS-сертификаты для 1.1.1.1
- DNS и TCP
Новый
Написать комментарий