Вот одна из интересных концепций, позволяющих оптимизировать взаимодействие интернет-узлов по разным сессионным протоколам: “при повторном подключении – сразу отправляем полезные данные для приложения”; это вместо сложного этапа установления соединения, требующего отправки и приёма нескольких сообщений, до того, как полезные данные станут доступны приложению.

То есть, если при первом соединении два узла должны выполнить некоторый обмен пакетами по схеме “запрос-ответ-подтверждение”, чтобы на обоих концах “сокета” сформировался синхронный контекст, то почему бы не запомнить контекст на стороне клиента и при повторных соединениях обойтись без дополнительных шагов для формирования нового контекста, а просто отправить вместе с начальным сообщением немедленно и полезные данные?

Пример уровня сетевого транспорта – TCP Fast Open, который, почему-то, известен мало: здесь клиент в рамках первого TCP-соединения, выполняемого по обычной схеме с созданием сессии, получает специальный идентификатор (cookie), чтобы при последующих соединениях сразу начать передачу полезных данных.

В TCP штатно используется схема установления соединения с тремя этапами согласования (SYN, SYN-ACK, ACK), когда передача данных приложению начинается только после завершения всех трёх этапов. И тут уже есть интересный момент, про который, бывает, забывают даже специалисты: вообще-то, данные между узлами в TCP начинают передаваться сразу же, с первым пакетом (SYN), так же, как, скажем, в UDP; потому что если бы данные не передавались (как минимум, заголовки с идентификаторами и параметрами), то и установить соединение было бы невозможно – это очевидно. То есть, с точки зрения возможности “отправить пакет в одну сторону”, TCP не слишком-то отличается от UDP на уровне, так сказать, NOC. Другое дело, что начальная информация TCP, составляющая обмен для установления сессии, не должна быть штатно доступна на уровне абстракции “сокета”. И вот тут-то начинаются отличия от того же UDP. Но сами по себе пакеты TCP вполне могут служить транспортом для “безсессионной” доставки данных.

Вариант Fast Open, если оставить за скобками детали, лишь обобщает эту возможность (о чём прямо написано в RFC), выводя её на уровень того самого “сокета”. Это делается при помощи дополнительной информации (cookie), подтверждающей, что сессия уже была установлена с соответствующими параметрами. Это и есть пример внедрения метода “сразу отправляем полезные данные”. Для реализации аналогичных логических схем в других протоколах используется, конечно, и UDP – посмотрите на WireGuard через Wireshark.

На уровне выше – тоже есть примеры: в TLS 1.3 имеется достаточно продвинутая сокращённая схема установления соединения 0-RTT (Zero Round-Trip Time), где клиент сразу же начинает передачу полезных данных в защищённом виде, если известна дополнительная информация о TLS-сервере, которую можно было получить в предыдущих соединениях (или как-то ещё).

Так что использование одной и той же полезной логической схемы самого верхнего уровня позволяет оптимизировать разные протоколы. Если задуматься, то сюда даже попадает port knocking. Вообще, если клиент и сервер заранее договорились о некотором секрете, то и обмен данными можно свести к отправке “случайных” пакетов со “случайным шумом” по случайным адресам. Пропускная способность, впрочем, будет не велика. Это работает далеко не только для Интернета.



Комментировать »

Кстати, ECH для TLS я достаточно подробно, – но, вместе с тем, популярно, – описывал в отдельной статье на сайте ТЦИ в 2021 году. Описание там дано в контексте развития “этих интернетов”, начиная от ESNI, что, на мой взгляд, весьма полезно.



Comments Off on Ссылки: популярное описание ECH

Как технологии “уровня приложений” помогают что-то узнавать про базовый уровень Интернета, то есть, про IP? Вот свежий пример того, как именно: на стороне веб-серверов поддержка постквантовых криптосистем в TLS есть у Cloudflare; соответственно, увидев на уровне веба для каких-то IP-адресов поддержку X25519Kyber768, можно предположить, что за этими IP-адресами скрываются системы Cloudflare, пусть адреса напрямую за Cloudflare и не записаны; сделав же такое предположение – можно подтвердить (или опровергнуть) его другими способами, скажем, через анонсы BGP и т.д. Полезный инструмент.

Вообще, что касается ветки “опровергнуть”: конечно, тот же Kyber768 есть, скажем, и у меня на тестовом сервере, который не за Cloudflare (но, кстати, их низкоуровневую библиотеку c Kyber и ML-KEM я всё же использую, так что влияние есть и тут); раз есть и где-то ещё поддержка, то можно и ошибиться. Можно, но тогда, скорее всего, там окажется Google – обособленных узлов, реализующих новшества, крайне мало, их количество начинает расти только тогда, когда поддержка появляется в распространённых линейках веб-серверов (Apache, nginx и др.). Но всё та же компания Cloudflare выступает тут локомотивом: ничего не поделать, поскольку именно наличие собственной полноценной разработки на всех базовых уровнях только и позволяет говорить что-то о практическом владении технологией. К сожалению, данный момент сейчас почти повсеместно замылен: факт прикручиваения “готового движка” теперь нередко является мерой “освоения технологии” (хорошо, что хоть не прикручивания “шильдика”).

Да, это отдельный вопрос, где именно и как именно возникает настоящая “технологическая зависимость”. Принято считать, что, как минимум, начинается она “от станкостроения”, то есть, не от изготовления, допустим, конкретных гвоздей при помощи некоторой машины, а от процесса изготовления этой машины. Но есть и более глубокие моменты. В примере с гвоздями – они касаются знаний о том, как нужно выстраивать процессы разработки машин, пусть и таких “простых”, как машины, делающие гвозди. Кстати, не так давно я писал ещё и про обратную разработку карамелек – похожая тема, пусть и не только “про эти ваши интернеты”.



Комментировать »

На сайте ТЦИ опубликована моя статья «Постквантовые криптосистемы в TLS и не только». Там про ML-KEM и вес ключей, а также о сертификатах и, – немного, – о квантовых вычислениях. Цитата:

Может даже показаться, что массовый переход на постквантовую криптографию в Интернете уже почти завершился, а вот квантовых компьютеров, из-за которых всё и было затеяно много лет назад, на горизонте пока не видно. Впрочем, это не совсем так. Но, конечно, не в части видимости квантовых компьютеров на горизонте, – их не видно всё так же, как и двадцать лет назад, – а в части внедрения постквантовой криптографии. Несмотря на бесспорные практические успехи и огромнейший отрыв от сугубо теоретических квантовых компьютеров, до всеобъемлющего внедрения всё ещё далеко (если такое внедрение когда-либо вообще потребуется).



Комментировать »

Поскольку браузеры, – в том числе, самый свежий Firefox, – перешли с Kyber768 на ML-KEM, я добавил на свой тестовый сервер TLS поддержку X25519MLKEM768 (не удаляя “гибриды” с Kyber768). Проверить можно при помощи новых версий браузеров Chrome и Firefox.

Кстати, немного занимательных элементов. В процессе развития постквантовой криптографии в TLS уже успели поменять “порядок байтов”. Так, в новых версиях представлений гибридных ключей – разная конкатенация массивов: в “старом” X25519Kyber768, если смотреть в сетевом порядке (так сказать, слева направо, что, конечно, математически неверно), сначала идёт ключ X25519, а потом – Kyber768; в “новом” X25519MLKEM – наоборот, сначала данные ML-KEM, а потом – X25519.

Почему это занимательно? А вот почему. Те немногие читатели dxdt.ru, которые непосредственно связаны с разработкой и реализацией ГОСТ-криптографии, совершенно точно наслышаны о технической шутке про “вращение байтов”, всплывающей в данной области постоянно и много лет. Суть вот в чём: при записи криптографических представлений, понятно, очень важен порядок байтов; так вот, в реализациях ГОСТ-криптографии, порядок байтов местами “сетевой”, а местами – в другую сторону. “Тупоконечное” и “остроконечное” представление. Так сложилось исторически. И смена направления, хоть и строго определена, но всегда происходит неожиданно. И она вовсе не так тривиальна, как можно подумать: байтовые последовательности попадают в хеш-функции; координаты точек – записываются в файлы; и так далее, и тому подобное. Понятно, что на стойкость и свойства математических операций, как и на описание алгоритмов в спецификациях, это не влияет. Однако если две реализации “байты вертят в разные стороны”, то они между собой несовместимы. На этом направлении даже есть тесты, которые, впрочем, не всегда помогают (как и в других областях, конечно). А самый забавный вариант – это когда значение оказалось “палиндромом”.



Комментировать »

В массовом TLS для веба криптосистемы с постквантовой стойкостью уже имеются, но есть ещё немало направлений, где такие криптосистемы нужны (если учитывать “угрозу квантовых компьютеров”, конечно). И во многих случаях требуются не криптосистемы согласования симметричного секрета, как в случае внедрения ML-KEM для TLS, а криптосистемы подписи. Можно, например, посмотреть в сторону DNS и DNSSEC, пусть последняя и не очень-то распространена, но там требуется именно электронная подпись. В DNS всегда приветствовались короткие пакеты данных, без излишнего раздутия. В предлагаемых сейчас постквантовых криптосистемах, традиционно, ключи и/или подписи – очень большие. Как это будет упаковываться в DNS – пока что не очень понятно: десять, предположим, килобайт на подписи с ключами – для DNS это слишком много.

Вообще, уже из распространённого предположения, что симметричные шифры сохраняют достаточную стойкость перед “квантовыми атаками”, можно сделать вывод, что возможны и короткие подписи, – то есть, что-то асимметричное, – главное, чтобы такие криптосистемы оказались ещё и эффективными: проверка 256-битной подписи, занимающая один час, тоже не особенно хороший вариант.

Длины ключей/подписей в текущем состоянии постквантовой криптографии и “квантовых вычислений” тема довольно странная: с одной стороны, как оно могло бы преобразовываться на “квантовом компьютере” не ясно, но если исходить из того, что для RSA нужна тысяча “квантовых элементов” компьютера на один бит ключа, то и для RSA можно просто добавить несколько килобит, получив практическую постквантовую стойкость – в конце концов, стойкость к обычным атакам для RSA развивалась именно так: 512-битный ключ сейчас можно факторизовать достаточно быстро для того, чтобы практическую разрядность передвинули к 2048 битам. С другой стороны, нет никаких гарантий того, что для задач, лежащих в основе уже стандартизованных постквантовых систем, тоже не найдут эффективных квантовых алгоритмов.

Поэтому, кстати, довольно странно читать в популярных статьях и новостных сообщениях по этой теме, что “сложность решения задач не отличается для обычных и квантовых компьютеров”. Ведь вовсе и не предполагается, что квантовые компьютеры что-то там вычисляют, так что вообще странно сравнивать сложность для “обычных и квантовых” компьютеров, поскольку там разные модели. При этом: и для классических атак (на “обычном компьютере”) на постквантовые криптосистемы возможны улучшения, и всякий квантовый алгоритм можно выполнить на классическом компьютере, и ту же задачу факторизации “нетрудно” очень быстро решать для произвольных больших чисел, если только вычислитель обладает быстрой памятью в объёме факториала от обрабатываемого числа (“небольшая” особенность, да).

Естественно, длина ключей постквантовых подписей диктуется и скоростью работы на практических компьютерах, и требованиями стойкости к атакам на этих практических классических компьютерах: улучшат такие атаки – разрядность (в том или ином виде) придётся увеличивать, вне зависимости от того, появились уже подходящие квантовые компьютеры или нет (собственно, посмотрите на тот же ML-KEM – бывший Kyber, – там уже сейчас несколько вариантов с разной классической стойкостью).

Но вернёмся к DNS и TLS. Можно предположить, что если “огромные постквантовые ключи” в данную систему не влезут, а уменьшить длину ключей не получится, то, скорее всего, из этого выйдет лишь ещё одна причина для повсеместного перехода на очередной вариант “DNS-over-TLS”: мол, там постквантовая стойкость уже есть, а то, что задача решается совсем другая – аутентификация узлов, а не защита подлинности данных, – ну так придётся как-то скорректировать модель угроз и привыкать “к новым подходам”. Впрочем, возможны и какие-то не использующие TLS, но существенно более интерактивные, варианты на замену DNS, поскольку именно интерактивность позволяет встроить более компактные схемы проверки подлинности данных. Речь тут про схемы, когда и конкретный запрос формируется с учётом некоторого ключа, и ответ приходит – тоже с учётом состава сессионных ключей из запроса и долгих ключей “из DNSSEC”. Возможны, скажем, варианты алгоритма Диффи-Хеллмана (постквантового, конечно). Поэтому, если темпы внедрения постквантовой криптографии не ослабеют, то можно ожидать новой, “интерактивной DNS”.



Комментировать »

Неочевидные особенности веб-TLS в Интернете. Посмотрим на сертификат узла dxdt.ru, а точнее на разные таймстемпы, присутствующие в этом сертификате, выпущенном удостоверяющим центром (УЦ) Let’s Encrypt. Так, время в SCT-метках: Sep 4 20:35:05 2024 GMT (миллисекунды я не указываю), а начальная граница интервала валидности сертификата: Sep 4 19:36:35 2024 GMT. То есть, время меток позже почти ровно на один час. Как такое могло бы получиться? Естественно, вариант тут только один: УЦ Let’s Encrypt выпускает сертификаты, сдвинув время начала действия на час назад. То есть, что называется, “задним числом” (backdate), но только на один час. Реальное время заказа сертификата ближе к таймстемпу из SCT-метки – понятно, что данный УЦ не мог ждать один час, чтобы отправить пресертификат в лог. Тем не менее, это означает, что сертификат “действовал” за час до того, как его заказали.

Это известная особенность, неоднократно упоминавшаяся в обращениях в Let’s Encrypt. Её традиционно объясняют необходимостью учитывать возможные неточности часов у клиентов: то есть, сертификат выпускается за секунды и должен заработать мгновенно, но если у клиентского компьютера отстают часы, то он покажет ошибку, так как в сертификате время стоит позже момента валидации по “сдвинутым часам”.

Почему достаточно одно часа? Не ясно. Возможно, из-за летнего/зимнего времени. Возможно, из-за того, что в 60 минут укладывается бо́льшая часть обычного “дрейфа” локальных часов (она, конечно, укладывается минут в двадцать, но почему бы не взять один час?).

Как это коррелирует с тем, что в SCT-метке всё равно стоит актуальное время, которое оказывается “в будущем” и валидатор всё равно мог бы заругаться? Ну, наверное, эффект остался с тех пор, когда никакие SCT-метки в сертификаты не ставились, к тому же, опережение на час находится в допустимом интервале и валидаторы браузеров не пугает: лишь бы подписи сходились.

Означает ли это, что Let’s Encrypt выпускает пресертификаты (для добавления в CT-лог) “с упреждением”? Вряд ли. Но проверить это нельзя: технически, УЦ может какие угодно сертификаты у себя штамповать, на то он и УЦ. Выпуск пресертификата без факта его заказа и подтверждения прав управления DNS-именем – будет являться грубейшим нарушением принятых правил, но (пре)сертификат ещё должен утечь. Тем не менее, какого-то смысла в подобных фокусах не просматривается.

Вообще, даже и выпуск сертификатов “задним числом” – довольно серьёзное нарушение для УЦ: в своё время именно его использовали в качестве одной из причин для отзыва доверия браузеров к некоторому китайскому УЦ. Но, наверное, один час – это не так много. Обратите внимание на то, что в сертификатах нет никакого зонирования времени, там просто таймстемп, – в случае с CT-логами – миллисекундный, – поэтому списать данную особенность на разные часовые пояса не получится.



Комментировать »

Ещё одна из Британских заморских территорий, а именно – территория в Индийском Океане (IO, то есть), – должна перейти к другому государству (Республика Маврикий), а это вызывает опасения относительно перспектив домена верхнего уровня io. Домен весьма известный, конечно. В статье по ссылке в качестве примера приводят домен Советского Союза – su. Этот домен продолжает работать в глобальной DNS, но, действительно, история очень похожая: государства нет, а национальный домен – есть. История очень похожая, но не точно такая же: всё же, при всём уважении, сравнивать историческое наследие СССР и данной Британской территории – довольно сложно: весовые категории разные. С другой стороны, в зоне .io гораздо больше имён зарегистрировано, и среди этих имён есть весьма важные. Наличие работающих имён в доменной зоне является хорошим аргументом в сторону её сохранения. (Я в su размещаю, например, nox.su – он про DNSSEC.)



Комментировать »

Немного про разные подставные URL/URI, используемые в целевых рассылках по электронной почте (имитирующих “запрос на смену пароля”, “просмотр заказа” или ещё что-то), а также в других подобных инструментах. Такие ссылки, как известно, могут вести совсем не туда, “куда написано”, или почти туда, но, всё же, не совсем – последнее актуально для корпоративных сред. Помимо подмены DNS и прочих внешних действий, у самих ссылок есть некоторые занимательные признаки, повышающие “степень подозрительности”.

Понятно, что современные почтовые клиенты позволяют замаскировать реальную ссылку многими способами, начиная от простой замены с использованием HTML и вплоть до изящных трюков с CSS, спецсимволами, сочетаниями букв, которые похожи по начертанию на “настоящее имя”, с картинками и Punycode. Бывает, что ссылка отображается верно, но выглядит от этого только подозрительнее. Простой признак: какое-то странное “цифровое” имя – site-11.test.ru. (Здесь test.ru выбрано вместо того или иного “корпоративного” домена.) Очень редко использование разных “технических хостнеймов” может быть тут уместным. Скорее – это просто случайный взломанный узел в корпоративной сети: используется то имя, которое досталось, то есть, было присвоено ранее, возможно, автоматически.

Открытый протокол HTTP (http://), если его использование вообще возможно, тоже добавляет баллы подозрительности. Если ссылка указывает на http://example.com/api/123/, то это вовсе и не означает, что, при клике, она поведёт браузер на настоящий узел под example.com. И речь даже не про подмену DNS. Запрос с протоколом HTTP – то есть, направляемый в открытом виде, – может быть перехвачен и перенаправлен на промежуточном узле. Скажем, взломан либо сам этот промежуточный узел (читай – “роутер”), либо, через ту или иную атаку с подменой сетевых маршрутов, трафик конкретной атакуемой рабочей станции может быть перенаправлен в направлении нужного узла (иногда это может делаться при помощи атаки на уровне клиента VPN). Понятно, что при таком перенаправлении перехватить можно любые запросы, однако, если используется TLS/HTTPS, то защищённый трафик ещё нужно раскрыть, что довольно трудно, да и аккуратная подмена открытых запросов требует более изящного подхода – поэтому прочий трафик, не с заданным в ссылке хостнеймом, будет переправляться к месту назначения без изменений.

Отдельный характерный момент, про который часто забывают, – непривилегированный номер порта. Если в ссылке указано example.com:7788 (то есть, на порт с номером 7788, больше 1000), то это может свидетельствовать о том, что трафик будет принимать какое-то приложение, запущенное с правами обычного пользователя. Другими словами: на каком-то произвольном сервере в локальной сети подсажена программа с правами непривилегированного пользователя, сервер имеет имя в локальном DNS-сервисе – всё, можно принимать трафик по HTTP. Можно и по HTTPS, если удалось получить подходящий TLS-сертификат, однако с сертификатом всё несколько сложнее.



Комментировать »

В “Яндекс-картах” запустили сервис “Геоаналитика”. Сообщают, что будут визуализировать “автомобильный и пешеходный трафик”, вместе с социально-демографическими данными, сведения о “поисковых запросах” и “насыщенности различными типами бизнесов” с геолокацией.

В 2013 году (да и раньше) я писал о том, что “Яндекс.Метрика”, установленная на “коммерческом сайте”, предоставляет “Яндексу” данные, которые потом используются платформой интернет-рекламы, чтобы показывать пользователям сайта очень точно подобранные рекламные объявления конкурентов. Сейчас времена поменялись, а технологии развились.

Понятно, что тут уже никакой “Яндекс.Метрикой” на сайте не отделаться: географические данные для “Яндекса” собирают многочисленные пользователи мобильных приложений и прочих сервисов в смартфоне (подключены и курьерские службы, и такси, и т.д.). Зато хорошо видно, в каком объёме и какие сведения можно собирать при таком масштабе: не ясно, всё ли новый сервис “Яндекса” выводит из данных, которые там собираются, но нетрудно предположить, что собирается гораздо больше, поскольку задачи должны бы быть шире, чем запуск некоторой публичной геоаналитики. По крайней мере, потенциально – шире.



Комментировать »

Иногда при отладке программ требуется просматривать трафик, защищённый TLS. Распространённый случай – HTTPS. Чтобы просматривать содержание TLS-трафика при помощи анализаторов протоколов (Wireshark) нужны сессионные ключи. В этой записке посмотрим, с примерами кода, как экспортировать эти ключи, если используется типовая библиотека Go crypto/tls.

Принцип довольно простой: при установлении TLS-соединения библиотека будет выводить сеансовые симметричные секреты и сопроводительный параметр (поле Random) в заданный файл, который позже использует Wireshark (или tshark, как в примерах ниже) для раскрытия трафика. Чтобы это заработало в Go, достаточно в структуре конфигурации TLS-клиента (или TLS-сервера) указать (KeyLogWriter) имя интерфейса для записи в файл (writer в терминологии Go), а сам интерфейс предварительно создать и направить вывод в нужный файл. А именно (ниже будет рабочий пример кода; здесь – фрагмент):

SessionKeysFile, err := os.OpenFile("s-keys.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
[...]
}
[...]
TLSConfig.KeyLogWriter = SessionKeysFile

Так сконфигурированный экземпляр TLS-соединения (в смысле кода Go) будет писать в заданный файл s-keys.txt сведения о ключах, в текстовом формате. Сам формат очень простой, но отличается для TLS 1.3 и других версий (см. ниже). Полный пример работающего кода для TLS-клиента (логика кода экспорта ключей для сервера – не отличается):

package main

import (
	"fmt"
	"net"
	"time"
	"crypto/tls"
	"os"
)

func main(){
	var TLSConfig tls.Config
	SessionKeysFile, err := os.OpenFile("s-keys.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		fmt.Printf("File error: %s\n", err.Error())
		os.Exit(1) 
	}
	hostname := "example.com"

	TLSConfig.KeyLogWriter = SessionKeysFile
	TLSConfig.MinVersion = tls.VersionTLS13
	TLSConfig.MaxVersion = tls.VersionTLS13
	TLSConfig.RootCAs = nil
	TLSConfig.InsecureSkipVerify = true

	timeout := 3 * time.Second
	TCPConn, err := net.DialTimeout("tcp", hostname + ":443", timeout)
	if err != nil {
		fmt.Printf("Connection error: %s\n", err.Error())
		os.Exit(1)
	}

	TCPConn.SetReadDeadline(time.Now().Add(timeout))
	TCPConn.SetWriteDeadline(time.Now().Add(timeout))

	TLSConn := tls.Client(TCPConn, &TLSConfig)

	HTTPGet := "GET / HTTP/1.1\r\nHost: " + 
				hostname + "\r\n" + 
				"Connection: close\r\n" +
				"User-Agent: TLS-keys-dump" + 
				"\r\n\r\n"
				
	_, err = TLSConn.Write([]byte(HTTPGet))
	if err != nil {
		fmt.Printf("Connection (TLS) write error: %s\n", err.Error())
		TLSConn.Close()
		os.Exit(1)
	}
	TLSConn.Close()
	os.Exit(0)
}

Используя привычные многим tcpdump и tshark нетрудно посмотреть, что получилось. В tshark файл с сессионными секретами передаётся при помощи опции tls.keylog_file (в Wireshark – можно загрузить через интерфейс редактирования параметров TLS-парсера). Вызов tshark:

$ tshark -r dump-ens.pcap -o tls.keylog_file:tls-export-keys/s-keys.txt -O tls -S "-----PACKET-----" -x

Здесь: dump-ens.pcap – дамп трафика, записанный tcpdump; s-keys.txt – файл, в который экспортированы TLS-секреты.
Фрагмент результата работы:

Decrypted TLS (83 bytes):
0000  47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a   GET / HTTP/1.1..
0010  48 6f 73 74 3a 20 65 78 61 6d 70 6c 65 2e 63 6f   Host: example.co
0020  6d 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63   m..Connection: c
0030  6c 6f 73 65 0d 0a 55 73 65 72 2d 41 67 65 6e 74   lose..User-Agent
0040  3a 20 54 4c 53 2d 6b 65 79 73 2d 64 75 6d 70 0d   : TLS-keys-dump.
0050  0a 0d 0a

Обратите, кстати, внимание на то, что в TLS 1.3 без секретных ключей сессии не удалось бы посмотреть даже серверные сертификаты. Так что, вообще говоря, для того, чтобы убедится в работоспособности метода, можно было бы даже и не отправлять GET-запрос HTTP, как написано в коде выше: для минимальной проверки в TLS 1.3 достаточно сразу разорвать TLS-соединение, при этом факт успешной записи части сессионных ключей в файл отразится в том, что tshark смог разобрать TLS-сертификаты, присланные сервером. Другое дело, что в TLS 1.3 для зашифрования сертификатов используются другие ключи, не те, что для защиты трафика (см. ниже).

Почему это работает? Прежде всего потому, что в TLS для защиты трафика в рамках сессии используются симметричные шифры и, соответственно, симметричный набор секретов для получения не менее симметричных секретных ключей. Так что для расшифрования не нужно получать “ключи сервера” или “ключи от сертификата сервера”. Симметричных ключей используется пара: один для отправки данных, второй – для получения (на клиенте и сервере эти ключи меняются местами). Соответственно, если анализатор трафика знает симметричные ключи, то он может расшифровать записанный трафик. Посмотрим, какой формат у файла с экспортированными ключами. Для TLS 1.3:

CLIENT_HANDSHAKE_TRAFFIC_SECRET [%RANDOM%] [%SECRET%]
SERVER_HANDSHAKE_TRAFFIC_SECRET [%RANDOM%] [%SECRET%]
CLIENT_TRAFFIC_SECRET_0 [%RANDOM%] [%SECRET%]
SERVER_TRAFFIC_SECRET_0 [%RANDOM%] [%SECRET%]

Чтобы не перегружать текст шестнадцатеричными цифрами я заменил поля, содержащие соответствующие данные, на понятные имена: [%RANDOM%] и [%SECRET%]. В исходном файле, очевидно, на месте этих обозначений будут длинные наборы шестнадцатеричных цифр.

В поле с именем [%RANDOM%] записывается значение из поля Random начального сообщения ClientHello. Это может показаться загадочным, если вы не сталкивались с TLS ранее, однако тут данное значение нужно лишь для того, чтобы анализатор протокола мог быстро сопоставить конкретный секрет и конкретную TLS-сессию в записанном трафике: то есть, в данном случае, это всего лишь метка. Сам секрет, позволяющий получить ключи для шифров, указывается в поле [%SECRET%]. (Ключи вычисляются на основе данного секрета при помощи соответствующей функции HKDF.)

В файле указаны клиентские и серверные секреты для разных этапов соединения TLS 1.3. CLIENT(SERVER)_HANDSHAKE_TRAFFIC_SECRET – это ключи для защиты начальных сообщений. CLIENT(SERVER)_TRAFFIC_SECRET_0 – это ключи первого поколения для защиты трафика. В TLS 1.3 возможно обновление ключей в рамках сессии, то есть, могли бы быть и TRAFFIC_SECRET_n следующих поколений, но это тема для другой записки. Формат файла подразумевает и другие поля, которые тоже тут не рассматриваются – все они устроены так же, но сдержат секреты других типов, которые могут появиться в ходе соединения TLS 1.3, так что анализаторы трафика должны обрабатывать их автоматически.

Для TLS 1.2 файл с экспортируемыми секретами, генерируемый библиотекой Go, будет будет использовать другой формат:

CLIENT_RANDOM [%RANDOM%] [%SECRET%]

Это обусловлено тем, что в TLS 1.2 используется другая схема получения сессионных ключей, в ней нет таких этапов, как в TLS 1.3, а защита трафика включается позже.

***

Некоторые другие записки по этой же теме:

TLS для DevOps
Секретные ключи в трафике и симметричные шифры
TLS в виртуальных машинах и извлечение ключей хостингом

Технические детали устройства TLS – можно узнать в техническом описании.



Комментировать »