Ресурсы: техническое описание TLS, LaTeX - в картинки (img), криптографическая библиотека Arduino, шифр "Кузнечик" на ассемблере AMD64/AVX и ARM64
В “Яндекс-картах” запустили сервис “Геоаналитика”. Сообщают, что будут визуализировать “автомобильный и пешеходный трафик”, вместе с социально-демографическими данными, сведения о “поисковых запросах” и “насыщенности различными типами бизнесов” с геолокацией.
В 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 – можно узнать в техническом описании.
Комментировать »
Интересный практический пример неверной настройки DNS в зоне vk.com, как его можно видеть и сейчас, и уже в течение нескольких недель. Скриншот выдачи сервиса проверки audit.statdom.ru (подробные объяснения – ниже):

Зона vk.com делегирована на авторитативные NS с именами, находящимися в той же зоне (так называемые “субординатные” NS), а именно: ns1, ns2, ns3, ns4.vk.com (всё в vk.com, не лучшее решение, но сейчас о другом). При этом в самой зоне vk.com для имён NS указаны AAAA-записи – это DNS-записи, содержащие IPv6-адреса. Вообще, чтобы избежать циклов при рекурсивном опросе DNS, для имён авторитативных серверов, которые сами определены в делегируемой зоне, используются так называемые glue-записи: серверы имён вышестоящей зоны возвращают IP-адреса для имён, на которые эта зона делегирована.
То есть, если домен example.com делегирован на ns1.example.com и ns2.example.com, то авторитативные серверы зоны первого уровня com. будут возвращать в дополнительном блоке DNS-ответа IP-адреса для ns1.example.com и ns2.example.com, чтобы резолвер мог к ним обратиться. (Понятно, что иначе резолвер, для определения адреса ns1.example.com, должен обратиться к DNS-серверам example.com, а чтобы обратиться к DNS-серверам example.com – нужно узнать адрес ns1.example.com, ну и так далее.)
Так вот, для vk.com в glue- указаны только А-записи (IPv4-адреса), но не указаны AAAA-записи (IPv6-адреса). Между тем, как отмечено в предыдущем параграфе, в самой зоне IPv6-адреса для NS указаны: каждый NS из списка делегирования снабжён v6-адресом в DNS. Под “данными в самой зоне” тут имеются в виду данные, возвращаемые непосредственно авторитативными NSами (которые ns[1,2,3,4].vk.com).
Вообще говоря, делегирующие ответы – и, тем более, glue-записи – имеют ключевое значение на базовой стадии рекурсивного опроса, но состав записей для NS в самой зоне может быть другим, при условии, что сведения, полученные с серверов уровнем выше, в этот состав вкладываются. То есть, можно допустить, что в самой зоне указаны дополнительные NS, которых нет в списке делегирования (обратная ситуация свидетельствует об очень грубой ошибке и представляет собой угрозу).
Для vk.com дополнительными оказываются адреса IPv6 для авторитативных NS. Адреса выбраны красивые, резолверы, работающие по v6, могли бы их использовать, но DNS-сервис под ними недоступен и отсутствуют glue-записи.
Комментировать »
Не нужно забывать, что ключевую роль в процессе сегментации интернетов сыграло желание слово “Интернет” писать со строчной буквы.
Комментарии (1) »
Гибридная криптосистема с постквантовой стойкостью X25519Kyber768 использует, как нетрудно догадаться, ключи X25519 в дополнение к Kyber. При этом X25519 – типовая криптосистема в современном TLS, так что в одном и том же ClientHello может быть одновременно два ключа: и X25519Kyber768, и просто X25519. И вот, например, Firefox в свежих версиях использует тут один и тот же ключ X25519 – и в гибриде, и в обособленном варианте. Это экономит одну итерацию X25519 (технически, что в гибридном варианте, что нет – это одна и та же криптосистема, никаких отличий). А вот Chrome, в такой же ситуации, использует два разных ключа X25519.
Комментировать »
Снова пишут о том, что пользователи TOR могут быть “деанонимизированы” при помощи анализа параметров трафика с сопоставлением по времени. Почему-то, иногда такая особенность преподносится как новость. Но это весьма старый метод. Например, я писал об этом почти десять лет назад на dxdt.ru:
Внутри сети TOR пользовательский трафик зашифрован, “вложенным” шифрованием. Известно, что параллельный анализ трафика, наблюдаемого на входном и выходном узлах (то есть, трафика, входящего в TOR и выходящего из этой сети), позволяет деанонимизировать источник трафика.
P.S. В той записке есть ссылки на два внешних ресурса: PDF с исходным описанием на сайте издания Spiegel и ссылка на сайт журнала “Доменные имена”, в котором я публиковал статью по теме. Показательно, что ни одна из ссылок нынче не ведёт на документы и тексты: обращение по адресу на сайте издания Spiegel – возвращает HTTP 404, а ссылка на сайт “Доменных имён” – переадресует на главную страницу nic.ru. В последнем случае, это связано с тем, что RU-CENTER вообще удалил сайт журнала – мне до сих пор непонятно по какой такой причине, поскольку, хоть сам журнал и закрыли, но на сайте был весьма полезный архив номеров.
Комментировать »
Использование имеющихся сейчас посквантовых криптосистем в TLS существенно увеличивает объём передаваемых данных. Например, ключ Kyber768, используемый в первом же сообщении (ClientHello), требует более килобайта (1184 байта). При этом, в TLS 1.3 есть штатная возможность передать несколько ключей для разных криптосистем в одном сообщении ClientHello, чтобы сервер выбрал подходящее. Эта возможность постоянно используется на практике.
Например, клиент может сразу передать ключи X25519 (32 байта) и P-256 (32+32 == 64 байта). То есть, две криптосистемы – и лишь 96 байтов расходуется на запись ключей (небольшое количество дополнительных байтов нужно для записи тех структур, в которых передаются ключи, но это можно не учитывать). Если передавать ключи двух постквантовых криптосистем, – скажем, с теми же Kyber768 и стандартизованным вариантом ML-KEM, – то получается уже больше двух килобайт. Это много, но если регулярно переходить от одной поствкантовой криптосистемы к другой, то становится необходимым, рутинным элементом TLS-соединений. Заметьте, что сам перечень поддерживаемых клиентом криптосистем для обмена сессионными секретами передаётся в TLS отдельно. Обычно, в этом перечне указано значительно больше криптосистем, чем передано ключей. Так, браузер может передавать семь поддерживаемых вариантов и ключи только для трёх из них (так сейчас делает Firefox). Чтобы сервер мог выбрать криптосистему, ключи от которой отсутствуют в ClientHello, в TLS 1.3 предусмотрен механизм повторного согласования – HelloRetryRequest: сервер, в этом случае, запрашивает повторное ClientHello, где будет только ключ той криптосистемы, которая выбрана (это всё можно самостоятельно увидеть на тестовом сервере TLS 1.3 при помощи современного браузера).
Подобный перебор с постквантовыми криптосистемами ещё больше увеличивает трафик, поэтому уже рассматриваются варианты того, как бы данный момент переложить на DNS. Так, в сообщении Google про ML-KEM в браузере Chrome, на которое я недавно ссылался, упоминается соответствующий черновик RFC – там предлагается публиковать в DNS сведения о предпочитаемых криптосистемах для обмена сеансовыми ключами в TLS. Конечно, тут нужно учитывать возможную защиту DNS-ответов от подмены, то есть, всё это тянет за собой не только и не столько DNSSEC (которая сама не имеет пока что ничего “постквантового”), как DNS-over-TLS/DNS-over-HTTPS.
Развитие постквантового TLS очень бурное. Впрочем, пока что не совсем понятно, для чего вообще такой рост объёмов данных. Сама по себе “постквантовая стойкость” тут ничего не объясняет, как и популярные описания в стиле “зашифруй заранее, пока нет квантового компьютера”. Однако вот уже и DNS охвачена дополнением записей. С одной стороны, размещение предварительных сведений о настройках TLS в DNS выглядит более чем разумно: запрос в систему всё равно необходим для получения IP-адреса; с другой стороны – данное направление развития как-то быстро сводится к надстраиванию новых и новых, всё больших и больших “дополнений”. (Надстраивание происходит в ускоряющемся темпе: не успели год назад внедрить в браузеры Kyber, как его уже переименовали в ML-KEM и переделали.) Эти “дополнения” вытесняют привычную работу с DNS, заменяя её на другой процесс, который следует называть “обнаружением сервисов” (Service Discovery) – дело в том, что с появлением ECH даже и IP-адреса будут извлекаться из доступной сети по-другому.
Комментировать »
Google пишет, что в ближайших версиях Chrome отключит использование Kyber768, заменив его на ML-KEM. Речь про использование в гибридной криптосистеме с постквантовой стойкостью для обмена ключами TLS 1.3. То есть, вместо X25519+Kyber768 будет ML-KEM+X25519 (здесь “минус” это дефис, а “плюс” – это плюс). Связано решение с тем, что криптосистему, в постквантовой части, стандартизировал NIST, и вариант из стандарта (кто бы мог подумать!) не совместим с тем вариантом, который использовался до стандартизации под именем Kyber.
В частности, при стандартизации отказались от одного из “промежуточных” преобразований с хеш-функцией, которое, в теории, могло бы предотвращать утечки состояния генератора (псевдо)случайных чисел. Про это всё, естественно, написано в документе NIST. Формулировка выглядит занимательно для тех, кто следит за темой модификации криптосистем в стандартах. В цитате далее (из приложения к стандарту NIST) под словосочетанием “этот шаг” (this step) имеется в виду шаг алгоритма, на котором вычислялось значение SHA-256 от инициализирующего значения: “The purpose of this step was to safeguard against the use of flawed randomness generation processes. As this standard requires the use of NIST-approved randomness generation, this step is unnecessary and is not performed in ML-KEM”. Пересказ смысла: поскольку в стандарте NIST прописано требование использовать только генераторы случайных чисел, разрешённые NIST, то и дополнительная защита от “испорченных генераторов” (то есть, оборачивание значения в хеш-функцию) более и не требуется. Логично, чего уж там. Строго говоря, ничто не мешает применить хеш-функцию для маскировки состояния раньше, до передачи значения в KEM. (Тут, конечно, речь только про дополнительный шаг уровня реализации, а SHA-3, требуемая непосредственно внутри Kyber, осталась.)
Так что постквантовые криптосистемы не просто развиваются, но ещё и вот начали тасоваться их названия, порядок байтов, способы конкатенации и использования хеш-функций. Возможно, я через некоторое время добавлю ML-KEM+X25519 на свой тестовый сервер TLS 1.3.
Комментировать »
Минутка специфического интернет-технологического юмора:
A (печатая в консоли, случайно склеивает два IP-адреса, вот так: 192.168.11.12192.168.12.11.).
B (наблюдая за процессом, пишет в чат): Это был адрес в формате IPv010.
A: Почему десять?
B: Потому что два IPv4 склеились – то есть, четыре плюс четыре.
A: Тогда должно быть IP-8.
B: Вот я и пишу: IPv010.
Комментарии (1) »
Иногда спрашивают: почему (некоторые) УЦ TLS не поддерживают подтверждение права управления доменом с использованием WHOIS-запросов? Вот появился очередной практический пример, иллюстрирующий, почему тут не нужно использовать WHOIS ни в каком виде: исследователи зарегистрировали домен, ранее служивший хостнеймом для whois-сервиса зоны .MOBI, и, как утверждается, получили потенциальную возможность подтверждать право управления доменом по запросам от УЦ, подставляя произвольный адрес e-mail в ответ (“потенциальную” – потому что сертификат исследователи заказывать не стали).
Подтверждение (валидация) права управления доменом (DCV – Domain Control Validation) – основа процесса выпуска TLS-сертификатов публичным УЦ. Понятно, что и ответы из WHOIS должны дополнительно валидироваться, и актуальность хостнейма сервера – контролироваться. Однако, каждый новый поддерживаемый метод DCV создаёт риски, а особенно велики эти риски, когда метод подразумевает использование дополнительных протоколов. Вообще, для автоматического выполнения DCV сейчас есть только один полностью подходящий способ: публикация TXT-записи с заданным значением в DNS. Но и тут имеется куча оговорок, конечно. При этом, уже и близкий метод – HTTP-запрос, – существенно хуже, пусть и использует DNS для передачи A-записей.
Комментировать »
Посмотрел, на какой домен можно было бы перенести dxdt.ru (поскольку RU-CENTER усиленно шлёт письма про привязку ЕСИА). Я ранее зарегистрировал несколько подходящих имён в других зонах верхнего уровня (например, .blog), однако и на этом направлении просматриваются проблемы, пусть и другого рода: вполне вероятно, что в скором времени интернет-санкции расширят очередной раз, а в результате – регистратуры (не регистраторы даже) заблокируют домены администраторов с неподходящим “подсанкционным” адресом (как уже было и с хостингами, и со многими иностранными регистраторами). Я недавно писал, что оператор реестра, – регистратура, – не только может отключить доступ регистраторов (уже происходит), но и заблокировать/удалить имена по своему выбору.
Комментарии (6) »
Новый