Что такое TLS-рукопожатие и как оно устроено


Оглавление (нажмите, чтобы открыть):

Что такое SSL/TLS и как проапгрейдиться до версии TLS-протокола 1.3

Протокол TLS шифрует интернет-трафик всех видов, тем самым делая безопасными общение и продажи в интернете. Мы расскажем о том, как протокол работает и что нас ждет в будущем.

Из статьи вы узнаете:

Что такое SSL

SSL или слой защищенных сокетов было оригинальным названием протокола, который разработала компания Netscape в середине 90-х. SSL 1.0 никогда не был публично доступным, а в версии 2.0 были серьезные недостатки. Протокол SSL 3.0, выпущенный в 1996, был полностью переделан и задал тон следующей стадии развития.

Что такое TLS

Когда следующую версию протокола выпустили в 1999, ее стандартизировала специальная рабочая группа проектирования сети Интернет и дала ей новое название: защита транспортного уровня, или TLS. Как говорится в TLS-документации, «разница между этим протоколом и SSL 3.0 не критичная». TLS и SSL формируют постоянно обновляемую серию протоколов, и их часто объединяют под названием SSL/TLS.

Протокол TLS шифрует интернет-трафик любого вида. Самый распространенный вид — веб-трафик. Вы знаете, когда ваш браузер устанавливает соединение по TLS — если ссылка в адресной строке начинается с «https».

TLS также используется другими приложениями — например, в почте и системах телеконференций.

Как работает TLS

Шифрование необходимо, чтобы безопасно общаться в интернете. Если ваши данные не шифруются, любой может проанализировать их и прочитать конфиденциальную информацию.

Самый безопасный метод шифрования — это асимметричное шифрование. Для этого требуется 2 ключа, 1 публичный и 1 приватный. Это файлы с информацией, чаще всего очень большие числа. Механизм сложный, но если попросту, вы можете использовать публичный ключ, чтобы шифровать данные, но вам нужен приватный ключ, чтобы расшифровывать их. Два ключа связаны с помощью сложной математической формулы, которую сложно хакнуть.

Можно представить публичный ключ как информацию о местоположении закрытого почтового ящика с отверстием, и приватный ключ как ключ, который открывает ящик. Любой, кто знает, где находится ящик, может положить туда письмо. Но чтобы прочитать его, человеку нужен ключ, чтобы открыть ящик.

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

Процесс, согласно которому клиент и сервер договариваются о ключе сессии, называется рукопожатием. Это момент, когда 2 общающихся компьютера представляются другу другу.

Процесс TLS-рукопожатия

Процесс TLS-рукопожатия довольно сложный. Шаги внизу отображают процесс в общем, чтобы вы понимали, как это работает в целом.

  1. Клиент связывается с сервером и запрашивает безопасное соединение. Сервер отвечает списком шифров — алгоритмическим набором для создания зашифрованных соединений — которым он знает, как пользоваться. Клиент сравнивает список со своим списком поддерживаемых шифров, выбирает подходящий и дает серверу знать, какой они будут использовать вдвоем.
  2. Сервер предоставляет свой цифровой сертификат — электронный документ, подписанный третьей стороной, который подтверждает подлинность сервера. Самая важная информация в сертификате — это публичный ключ к шифру. Клиент подтверждает подлинность сертификата.
  3. Используя публичный ключ сервера, клиент и сервер устанавливают ключ сессии, который они оба будут использовать на протяжении всей сессии, чтобы шифровать общение. Для этого есть несколько методов. Клиент может использовать публичный ключ, чтобы шифровать произвольное число, которое потом отправляется на сервер для расшифровки, и обе стороны потом используют это число, чтобы установить ключ сессии.

Ключ сессии действителен только в течение одной непрерывной сессии. Если по какой-то причине общение между клиентом и сервером прервется, нужно будет новое рукопожатие, чтобы установить новый ключ сессии.

Уязвимости протоколов TLS 1.2 и TLS 1.2

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

Например, протокол TLS 1.2 стал особенно уязвимым к атакам типа активного вмешательства в соединение, в которых хакер перехватывает пакеты данных посреди сессии и отправляет их после прочтения или изменения их. Многие из этих проблем проявились за последние 2 года, поэтому стало необходимым срочно создать обновленную версию протокола.

TLS 1.3

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

Как включить поддержку TLS 1.3 в браузерах Google Chrome и Firefox

Firefox и Chrome поддерживают TLS 1.3, но эта версия не включена по умолчанию. Причина в том, что она существует пока только в черновом варианте.

Mozilla Firefox

Введите about:config в адресную строку браузера. Подтвердите, что вы осознаете риски.

  1. Откроется редактор настроек Firefox.
  2. Введите в поиске security.tls.version.max
  3. Поменяйте значение на 4, сделав двойной щелчок мышью на нынешнее значение.

Google Chrome

  1. Введите chrome://flags/ в адресную строку браузера, чтобы открыть панель с экспериментами.
  2. Найдите опцию #tls13-variant
  3. Нажмите на меню и поставьте Enabled (Draft).
  4. Перезапустите браузер.

Как проверить, что ваш браузер использует версию 1.2

Напоминаем, что версия 1.3 еще не используется публично. Если вы не хотите
использовать черновой вариант, вы можете остаться на версии 1.2.

Чтобы проверить, что ваш браузер использует версию 1.2, проделайте те же шаги, что и в инструкциях выше, и убедитесь, что:

  • Для Firefox значение security.tls.version.max равно 3. Если оно ниже, поменяйте его на 3, сделав двойной щелчок мышью на нынешнее значение.
  • Для Google Chrome: нажмите на меню браузера — выберите Settings — выберите Show advanced settings — опуститесь до раздела System и нажмите на Open proxy settings…:
  • В открывшемся окне нажмите на вкладку Security и проверьте, чтобы для поля Use TLS 1.2 стояла галочка. Если не стоит — поставьте и нажмите OK:

Изменения войдут в силу после того, как вы перезагрузите компьютер.

Быстрый инструмент для проверки версии протокола SSL/TLS браузера

Зайдите в онлайн-инструмент проверки версии протокола SSL Labs. Cтраница покажет в реальном времени используемую версию протокола, и подвержен ли браузер каким-то уязвимостям.

Переход на https, не жертвуя скоростью загрузки

Быстрая загрузка сайта это критически важный аспект для хорошего отношения пользователей к сайту. Настолько важный, что несколько лет назад Google объявил, что они будут использовать скорость загрузки страницы в качестве фактора поискового ранжирования. Недавно, Google также объявил, что они будут продвигать сайты, использующие Transport Layer Security (TLS) в поисковом ранжировании. TLS шифрует трафик вебсайта, предохраняя от мониторинга передачи данных «шпионскими» службами. Тем не менее, добавление этой меры предосторожности делает и сайт более сложным, и общение с посетителями, потенциально замедляя взаимодействие с сайтом и негативно влияя на удобство пользователей. В этой статье я покажу как использовать TLS, чтобы сайт оставался быстрым и гибким.

Соглашения и отказ от ответственности

Прежде чем мы начнем, кратко отмечу, что TLS чаще можно услышать под названием SSL. SSL был разработан компанией Netscape в середине 90-х как протокол шифрования. TLS протокол произошел из SSL и продолжает развиваться и улучшаться, в то время как SSL постепенно сдает позиции. В прошлом, SSL и TLS были взаимозаменяемыми понятиями. Но в последней версии SSL, SSLv3, были найдены уязвимости. Все версии SSL были не достаточно безопасны и никто не должен использовать никакие версии SSL. Чтобы не вводить вас в заблуждение я больше не буду упоминать термин SSL, а буду говорить только о TLS.

Дополнительно, в то время как TLS помогает защищать посетителей сайта от злоумышленников, он не может магически сделать ваш сайт «безопасным» от утечек вызванных скриптами внедраяемых злоумышленниками или от SQL внедрений. Если вы храните персональные данные пользователей или собираете коммерческие данные на сайте, вам нужно более тщательно подбирать методы защиты.

Наконец, любое руководство или статья о том как защитить сайт очень чувствительны ко времени публикации. Атакующие постоянно совершенствуют свои методы и придумывают новые. Советы по оптимизации TLS, которые давали даже два года назад, сделали бы ваш сайт незащищенным (например, использование RC4. Вам все время надо быть начеку и пользоваться советами только из проверенных источников.

TLS сферы где нужен TLC

Есть две области TLS, которые могут повлиять на скорость:

  1. Шифрование данных. Данные посылаемые туда и обратно между браузером и вашим сервером должны шифроваться и дешифроваться. Если использовать неправильные настройки, то скорость загрузки страницы может значительно уменьшиться в сравнении с незашифрованным трафиком.
  2. Установка безопасного соединения. Существует несколько этапов, которые должны быть пройдены, прежде чем браузер установит безопасное соединение с сайтом: Сертификаты должны быть подтверждены, выбран необходимый алгоритм и ключи должны быть обменены. Это называется рукопожатие TLS, которое оказывает существенное влияние на скорость загрузки сайта.

Мы должны подарить каждому из этих этапов заботу и ласку (Tender Loving Care (TLC)), чтобы оптимизировать производительность. Давайте детально обсудим каждый шаг

Оптимизация Шифрования Данных

Когда используется TLS, вы добавляете еще 2 шага к процессу коммуникации браузера и сервера. Отправитель должен зашифровать данные перед отправкой, а получатель должен дешифровать их перед обработкой. И поскольку эти две операции происходят постоянно со всем трафиком, то нужно, чтобы этот обмен был настолько эффективным, насколько это возможно.

Существует большое количество шифров, которые могут использоваться для выполнения этого шифрования / дешифрования. Некоторые из них, такие как 3DES, изначально были разработаны для аппаратного обеспечения и могут медленно выполняться при использовании программного обеспечения на вашем компьютере или в браузере телефона. Другие, такие как AES, настолько популярны, что производители процессоров, такие как Intel, добавили специальные инструкции к своим чипам, чтобы заставить их работать быстрее.

Десять лет назад шифрование данных TLS привело к значительным накладным расходам. Сегодня закон Мура и специальная поддержка определенных шифров в процессорах существенно устранили эти накладные расходы, если вы выберете правильный шифр. Консенсус от разработчиков и администраторов безопасности, которые запускают большие веб-сайты TLS, заключается в использовании AES с 128-битными ключами. Из приведенной ниже диаграммы видно, что AES, работающий на процессоре, который поддерживает встроенные инструкции AES (обозначается ярлыком AES-NI), на сегодняшний день является самым быстрым шифром, который вы можете использовать.

Указание того, какой шифр и варианты использования могут быть довольно сложными и запугивающими. К счастью, Mozilla создала отличную страницу с примерами конфигураций шифров для обеспечения быстрых и безопасных соединений. Эти примерные конфигурации работают со всеми браузерами, и по умолчанию они используют более быстрые алгоритмы, такие как AES. Они постоянно обновляются, когда появляются новые угрозы безопасности, и я настоятельно рекомендую следовать их указаниям.

Как уже упоминалось, чтобы получить максимальную отдачу от AES, вашему веб-серверу необходимо будет использовать процессор, который поддерживает специальные инструкции AES, известные как AES-NI. Большинство серверных процессоров, сделанных за последние 5 лет, таких как линейка Intel Xeon, поддерживают AES-NI. Однако старые виртуализированные серверы и облачные серверы часто не поддерживают эти инструкции. Класс M1 экземпляров EC2 от Amazon не поддерживает AES-NI, тогда как текущий класс экземпляров M3 от Amazon поддерживает. Если вы используете размещенную службу, обратитесь к своему хостинг провайдеру с вопросом о том, какие параметры TLS они поддерживают, и поддерживает ли ваш хостинг AES-NI.

Короче говоря, настраивая ваш веб-сервер на использование AES-шифров и завершая ваши TLS-соединения на машине с процессором с поддержкой инструкций AES-NI, вы можете эффективно смягчить снижение производительности шифрования данных.

Контрольный список по оптимизации

  • Включите AES в качестве предпочтительного шифрования, следуя рекомендациям Mozilla.
  • Убедитесь, что веб-сервер работает в системе с процессором, поддерживающим инструкции AES-NI.

Оптимизация согласования (рукопожатия) TLS

Согласование TLS — это процесс, который выполняет браузер и сервер, чтобы решить, как установить связь и создать защищенное соединение. Некоторые из вещей, которые происходят во время рукопожатия:

  • Идентификация сервера и, возможно, клиента
  • Рассказывая друг другу, какие шифры, подписи и другие варианты поддерживает каждая сторона, и соглашаясь на использование подходящих для обеих сторон вариантов
  • Создание и обмен ключей, которые будут использоваться позднее во время шифрования данных

Рукопожатие TLS показано на этой технической диаграмме:

Не волнуйтесь. Несмотря на то, что на диаграмме много деталей, выгода заключается в том, что полное рукопожатие TLS включает в себя 2 маршрута туда и обратно между клиентом и сервером. Из-за разницы между задержкой и пропускной способностью, более быстрое подключение к Интернету не ускоряет эти маршруты. Это рукопожатие обычно занимает от 250 миллисекунд до половины секунды, но может длиться и дольше.

Вначале, половина секунды может показаться не слишком долгой. Основная проблема с качеством связи с TLS-рукопожатием — это не то, сколько времени требуется на обмен данных. Поскольку рукопожатия TLS являются частью создания безопасного соединения, они должны произойти до того, как любые данные могут быть обменены. Посмотрите на диаграмму водопада ниже:

Рукопожатие TLS, показанное фиолетовым для каждого шага здесь, добавляет 750 мс задержки ко времени, которое требуется для получения начальной HTML-страницы. В этом примере загрузка HTML-страницы через TLS занимает в два раза больше времени, чем получение этой же страницы по незашифрованному соединению! Хуже того, браузер не может ничего сделать, пока не получит эту начальную HTML-страницу. Он не может загружать и другие ресурсы параллельно, например, файлы CSS или изображения, поскольку он не получил эту начальную HTML-страницу, в которой говорится о других ресурсах. Это верно для каждой защищенной веб-страницы, которую вы посещаете: браузер не получает этот первый ответ HTML. К сожалению, рукопожатие TLS увеличивает время, в течение которого браузер не может ничего сделать, замедляя производительность вашего сайта.

Кроме того, помните, что рукопожатие TLS происходит в начале каждого нового HTTP-соединения. Поскольку браузеры загружают ресурсы параллельно, это означает, что посещающий браузер создаст несколько подключений TLS и должен дождаться завершения нескольких рукопожатий даже при посещении одной страницы!

К сожалению, в процессе рукопожатия TLS не так много лишних или ненужных данных, которые мы можем оптимизировать. Основным аспектом, который мы можем оптимизировать, является шаг «подтверждения идентичности сервера». Для этого браузер смотрит на то, что называется цепочкой сертификатов.

Цепочка сертификатов

Когда вы посещаете https://www.example.com, откуда вы знаете, что действительно видите www.example.com? Сертификаты TLS решают эту проблему. Вы получаете сертификат, сообщающий вашему браузеру «да, это www.example.com. Доверяй мне». Но откуда вы знаете, что можете доверять сертификату, отправленному сервером?

Именно здесь нужна цепочка сертификатов. Ваш сертификат будет подписан цифровой подписью каким-либо сертификатом другого лица, что, по сути, говорит: «example.com классный, я поручился за него, вот мой сертификат». Это называется промежуточным сертификатом. Браузеры имеют встроенный список из тысяч сертификатов, которым они доверяют. Если браузер доверяет этому промежуточный сертификат, мы закончили. Однако, возможно, браузер не доверяет сертификату вашего веб-сайта или промежуточному сертификату.

Что происходит тогда? Просто! Затем браузер посмотрит, кто подписал промежуточный сертификат, и кто подписал его, и так далее . В основном браузер будет «ходить» по этой цепочке сертификатов, видя, кто ручается за кого, пока не найдет сертификат того, кому он доверяет, из этого встроенного списка, упомянутого выше.

Цепочка сертификатов выглядит примерно так:

Здесь мы видим сертификат для моего сайта app.zoompf.com. Мой сертификат был подписан сертификатом «DigiCert Secure Server CA». Браузер не доверяет этому сертификату, так как он не находится в его предварительно построенном списке. Однако сертификат «DigiCert Secure Server CA», в свою очередь, был подписан сертификатом «DigiCert Global Root CA», который находится в этом списке и, таким образом, проверен. Поэтому в этом случае длина моей цепи сертификата равна 3.

Вы можете оптимизировать производительность своего сайта, сделав эту цепочку сертификатов максимально короткими, поскольку проверка каждого сертификата в цепочке занимает дополнительное время. Дополнительные сертификаты также означают больше данных, которые необходимо обменивать при установлении защищенного соединения. Браузеру может потребоваться дополнительные запросы для загрузки других немедленных сертификатов или проверки того, что каждый сертификат в цепочке по-прежнему действителен и не был отозван.

Когда будете покупать сертификат TLS, спросите продавца:

  • Какой сертификат будет использоваться для подписания вашего сертификата и насколько длинной будет цепочка сертификатов?
  • Включат ли они свой промежуточный сертификат в комплекте с вашим сертификатом, чтобы браузеру не пришлось ждать загрузки других сертификатов при хождении по цепочке сертификатов?
  • Поддерживают ли они сшивание OCSP, чтобы сократить время, необходимое для проверки отозванных сертификатов?

Я рекомендую приобрести сертификат у крупного, известного поставщика. Они, как правило, предлагают лучшую поддержку и функции, такие как OCSP. Также более вероятно, что их корневым сертификатам доверяют браузеры и, следовательно, имеют более короткую длину цепочки сертификатов. Вы можете узнать больше о том, как протестировать цепочку сертификатов здесь.

Чек лист по оптимизации

  1. Уменьшите длину цепочки сертификатов.
  2. Проверьте, чтобы все последующие сертификаты поставлялись с вашим сертификатом.
  3. Получите сертификат, который поддерживает OCSP.

Избегайте полных рукопожатий TLS

По сути, рукопожатие TLS касается клиента и сервера, которые проверяют друг друга, соглашаясь на общий набор шифров и параметров безопасности, а затем продолжают разговор, используя эти параметры. Кажется глупым, что клиент и сервер, которые недавно общались, должны проходить этот полный процесс снова и снова. Представьте себе этот сценарий: вы посещаете такой блог, как TLS. Для загрузки всего содержимого было сделано несколько соединений TLS с несколькими рукопожатиями. Через несколько минут вы нажмете ссылку, чтобы прочитать другую страницу на этом сайте, что заставляет ваш браузер выполнять несколько рукопожатий TLS снова и снова.

В этом случае возобновляется сеанс TLS. В принципе, возобновление сеанса TLS позволяет клиенту сказать: «Привет, сервер, мы недавно общались и сделали это, используя следующие параметры TLS . Можно ли снова начать говорить, используя такие же варианты? » Это огромное улучшение производительности. Для установления безопасного соединения для полного соединения TLS требуется 2 раунда. Повторение сеансов TLS позволяет нам сделать это в 1 раунд.

Самое замечательное в возобновлении сеанса состоит в том, что это в основном бесплатный короткий отрезок. Когда клиент запрашивает сервер, «можем ли мы использовать эти предварительно согласованные настройки?», Он делает это как часть первого раунда в настройке полного рукопожатия TLS. Если сервер согласен, отлично, выполняется короткое рукопожатие, и никакое дальнейшее установление связи не требуется. Если по какой-либо причине сервер не согласен с запросом возобновления сеанса, то рукопожатие TLS продолжается как обычно и завершается в 2 раунда. Нет причин, чтобы отказываться от возобновления сеанса.

Существует два разных механизма для возобновления TLS. Первый — идентификаторы сеанса, а второй — сессии. Оба делают то же самое. Разница между ними заключается прежде всего в том, какая сторона должна отслеживать ранее согласованные варианты. Все веб-браузеры поддерживают оба, но некоторые веб-серверы, такие как Microsoft IIS, поддерживают только идентификаторы сеансов. Идентификаторы сеансов являются немного более старым механизмом и могут потенциально подвергать ваш сайт атакам типа «отказ в обслуживании». Включение идентификаторов сеансов или сессий осуществляется с помощью конфигурации вашего веб-сервера и довольно просто. Проконсультируйтесь с вашим администратором о включении этих параметров.

Чеклист по оптимизации

  1. Включите возобновление TLS на своих веб-серверах.
  2. Если возможно, избегайте использования идентификаторов сеансов, чтобы уменьшить подверженность атакам «Отказ в обслуживании».

Другие опции TLS

Есть еще несколько вариантов и нюансов в TLS, которые мы отметим: Какой асимметричный алгоритм вы должны использовать? Какой протокол обмена ключами вы должны использовать? Какой размер ключа следует использовать для вашего симметричного шифра? Должны ли вы использовать совершенную прямую секретность? Это важные решения с точки зрения безопасности, и у каждого разные потребности. С точки зрения производительности, они в значительной степени спорны. Лучше оставить выбор за тем, кто управляет вашим сервером, или следовать советам Mozilla на странице, указанной выше.

Минимизация TLS общего времени рукопожатия

Как мы видели, рукопожатия TLS, при необходимости, могут повлиять на вашу производительность:

  • Они могут задерживать загрузку важных ответов, таких как загрузка HTML страницы.
  • Они могут происходить несколько раз для одной страницы.
  • Мы не можем их хорошо оптимизировать.

Хотя возобновление сеанса может сократить время рукопожатия TLS пополам, все же лучше избегать рукопожатий TLS. Вы можете сделать это, минимизируя количество HTTP-соединений, которые браузер делает при посещении вашего веб-сайта. К счастью, многие традиционные меры по оптимизации производительности, которые вы должны в любом случае делать, могут помочь. Это делает оптимизацию производительности фронтенда еще более важной на сайтах, защищенных TLS. Давайте сосредоточимся на 4 мерах по оптимизации, которые особенно важны для сайтов, использующих TLS.

1. Постоянное соединение


Постоянные соединения позволяют HTTP выполнять несколько запросов по одному HTTP-соединению. Постоянные соединения позволяют браузеру быстрее загружать страницу, поскольку она может быстрее выполнять запросы. Но он также может сократить количество рукопожатий TLS. Рассмотрим этот водопад, на который мы смотрели раньше:

Посмотрите, как практически каждый HTTP-запрос имеет фиолетовый раздел? Этот фиолетовый раздел является рукопожатием TLS. Почему это происходит? Поскольку веб-сервер явно закрывает HTTP-соединение и, следовательно, базовое соединение TLS с каждым ответом. Мы можем увидеть это в ответе: Connection: close (Соединение закрыто), как показано ниже:

Это ужасно для производительности в целом, но особенно плохо для сайта с использованием TLS. Ваш сайт должен использовать постоянные соединения.

2. Шардинг (разбивка) домена

Шардинг доменов — это метод, позволяющий обмануть посещаемый браузер, чтобы быстрее загружать ресурсы с вашего сайта. Он работает, имея один веб-сервер с разными именами хостов. Например, ваш сайт может быть назван example.com, но настроен для разрешения имен static1.example.com и static2.example.com на один и тот же сервер. Так как браузеры разрешают только ограниченное количество HTTP-подключений к одному имени хоста одновременно, использование нескольких имен хостов приводит к тому, что браузер загружает больше контента параллельно.

Проблема с шардингом домена заключается в том, что браузер не знает, что example.com, static1.example.com и static2.example.com — это все тот же сервер. Он будет создавать новые HTTP-соединения для каждого имени хоста и каждый раз выполнять полное рукопожатие TLS. В нашем примере мы потенциально делаем 3 рукопожатия TLS из-за наших раздельных имен хостов. Кроме того, информация о возобновлении сеанса для соединений по одному имени хоста не может использоваться соединениями с другим именем хоста, хотя под по сути все эти имена относятся к одному и тому же серверу.

Итоговым результатом является то, что увеличение количества рукопожатий TLS, вызванных шардингом домена, может свести на нет любые преимущества, полученные при параллельной загрузке большего количества контента. Фактически, шардинг TLS-защищенного веб-сайта может на самом деле сделать его медленнее. Это особенно верно, если вы следуете следующим двум рекомендациям, которые уменьшат количество запросов, которые необходимо осуществить.

3. Объединение CSS и JavaScript файлов

Объединение нескольких файлов CSS или JavaScript в один или два первичных файла — это огромная оптимизация производительности. Браузеры могут загружать один файл размером 100 КБ быстрее, чем 10 10-килобайтных файлов. Преимущество для сайтов TLS заключается в том, что если вы делаете меньше запросов, у вас меньше шансов получить дополнительные HTTP-соединения, для которых потребуется возобновление или полное рукопожатие TLS.

4. Кэширование ресурсов

Самый быстрый запрос — это тот, который браузеру не нужно делать. Кэширование — лучшая оптимизация производительности, которую вы можете сделать. Если бы я только что посетил ваш сайт, и я смотрю на вторую страницу, нет причин загружать ваш логотип во второй раз. Если вы не используете кеширование, браузер должен проверить ваш веб-сайт, если он в порядке, чтобы использовать изображение логотипа, которое оно загрузило ранее. Это называется условным запросом, и это плохо для производительности. Из-за разницы между пропускной способностью и задержкой, даже если вы фактически ничего не загружаете с сервера, просто отправляя запрос, чтобы спросить, нормально ли использовать логотип, требуется почти столько же, сколько просто загрузить логотип снова.

Условные запросы являются плохими для TLS. Вы заставляете браузер создавать больше HTTP-соединений и, таким образом, выполнять больше рукопожатий TLS, просто чтобы проверить, не изменился ли контент. Кэширование ваших статических ресурсов, таких как изображения, CSS и JavaScript, будет иметь большой эффект и может предотвратить эти дополнительные подключения.

Чеклист по оптимизации

  • Включить постоянные подключения (keep-alive). Убедитесь, что ваше приложение или CMS не закрывают досрочно HTTP-соединения.
  • Используйте инструменты, такие как WebPageTest, чтобы узнать, действительно ли шардинг доменов улучшит производительность вашего веб-сайта с поддержкой TLS.
  • Скомбинируйте несколько JavaScrpt и CSS файлов в один, там где это возможно.
  • Закэшируйте статические ресурсы на 5 минут, даже если у вас нет системы управления версиями файлов.
  • Если у вас есть инфраструктура и процессы на месте, используйте долгосрочное кеширование с системой управления версиями файлов, которая изменяет URL-адреса ваших ресурсов при их изменении.
  • Проверьте свой сайт, чтобы убедиться, что вы правильно выполняете оптимизацию производительности.

Заключение

Google теперь поддерживает сайты, которые защищены с помощью TLS в рейтингах поисковых систем. TLS может повлиять на производительность, и эта статья показала вам шаги, которые вы можете предпринять для минимизации проблем.

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

MNorin.com

Блог про Linux, Bash и другие информационные технологии

TLS и SSL: Необходимый минимум знаний

TLS и SSL упоминаются в последнее время все чаще и чаще, более актуальным становится использование цифровых сертификатов, и даже появились компании, готовые бесплатно предоставлять цифровые сертификаты всем желающим, чтобы гарантировать шифрование трафика между посещаемыми сайтами и браузером клиента. Нужно это, естественно, для безопасности, чтобы никто в сети не мог получить данные, которые передаются от клиента серверу и обратно. Как же это всё работает и как это использовать? Чтобы это понять, надо, пожалуй, начать с теории, а потом показать на практике. Итак, SSL и TLS.

Что такое SSL и что такое TLS?

SSL — Secure Socket Layer, уровень защищенных сокетов. TLS — Transport Layer Security, безопасность транспортного уровня. SSL является более ранней системой, TLS появился позднее и он основан на спецификации SSL 3.0, разработанной компанией Netscape Communications. Тем не менее, задача у этих протоколов одна — обеспечение защищенной передачи данных между двумя компьютерами в сети Интернет. Такую передачу используют для различных сайтов, для электронной почты, для обмена сообщениями и много еще для чего. В принципе, можно передавать любую информацию таким образом, об этом чуть ниже.

Безопасная передача обеспечивается при помощи аутентификации и шифрования передаваемой информации. По сути эти протоколы, TLS и SSL, работают одинаково, принципиальных различий нет. TLS, можно сказать, является преемником SSL, хотя они и могут использоваться одновременно, причем даже на одном и том же сервере. Такая поддержка необходима для того, чтобы обеспечить работу как с новыми клиентами (устройствами и браузерами), так и с устаревшими, которые TLS не поддерживают. Последовательность возникновения этих протоколов выглядит вот так:

SSL 1.0 — никогда не публиковался
SSL 2.0 — февраль 1995 года
SSL 3.0 — 1996 год
TLS 1.0 — январь 1999 года
TLS 1.1 — апрель 2006 года
TLS 1.2 — август 2008 года

Принцип работы SSL и TLS

Принцип работы SSL и TLS, как я уже сказал, один и тот же. Поверх протокола TCP/IP устанавливается зашифрованный канал, внутри которого передаются данные по прикладному протоколу — HTTP, FTP, и так далее. Вот как это можно представить графически:

Прикладной протокол «заворачивается» в TLS/SSL, а тот в свою очередь в TCP/IP. По сути данные по прикладному протоколу передаются по TCP/IP, но они зашифрованы. И расшифровать передаваемые данные может только та машина, которая установила соединения. Для всех остальных, кто получит передаваемые пакеты, эта информация будет бессмысленной, если они не смогут ее расшифровать.

Установка соединения обеспечивается в несколько этапов:

1) Клиент устанавливает соединение с сервером и запрашивает защищенное подключение. Это может обеспечиваться либо установлением соединения на порт, который изначально предназначен для работы с SSL/TLS, например, 443, либо дополнительным запросом клиентом установки защищенного соединения после установки обычного.

2) При установке соединения клиент предоставляет список алгоритмов шифрования, которые он «знает». Сервер сверяет полученный список со списком алгоритмов, которые «знает» сам сервер, и выбирает наиболее надежный алгоритм, после чего сообщает клиенту, какой алгоритм использовать

3) Сервер отправляет клиенту свой цифровой сертификат, подписанный удостоверяющим центром, и открытый ключ сервера.

4) Клиент может связаться с сервером доверенного центра сертификации, который подписал сертификат сервера, и проверить, валиден ли сертификат сервера. Но может и не связываться. В операционной системе обычно уже установлены корневые сертификаты центров сертификации, с которыми сверяют подписи серверных сертификатов, например, браузеры.

5) Генерируется сеансовый ключ для защищенного соединения. Это делается следующим образом:
— Клиент генерирует случайную цифровую последовательность
— Клиент шифрует ее открытым ключом сервера и посылает результат на сервер
— Сервер расшифровывает полученную последовательность при помощи закрытого ключа
Учитывая, что алгоритм шифрования является асимметричным, расшифровать последовательность может только сервер. При использовании асимметричного шифрования используется два ключа — приватный и публичный. Публичным отправляемое сообщение шифруется, а приватным расшифровывается. Расшифровать сообщение, имея публичный, ключ нельзя.

6) Таким образом устанавливается зашифрованное соединение. Данные, передаваемые по нему, шифруются и расшифровываются до тех пор, пока соединение не будет разорвано.

Корневой сертификат

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

Запрос на подпись (CSR, Certificate Sign Request)

Для получения подписанного серверного сертификата необходимо сгенерировать запрос на подпись (CSR, Certificate Sign Request) и отправить этот запрос авторизационному центру, который вернет подписанный сертификат, устанавливаемый непосредственно на сервер, чуть ниже посмотрим, как это сделать на практике. Сначала генерируется ключ для шифрования, затем на основании этого ключа генерируется запрос на подпись, CSR-файл.

Клиентский сертификат

Клиентский сертификат может быть сгенерирован как для использования в устройствах, так и для использования пользователями. Обычно такие сертификаты используются при двусторонней верификации, когда клиент верифицирует, что сервер действительно тот, за кого себя выдает, и сервер в ответ делает то же самое. Такое взаимодействие называется двусторонней аутентификацией или mutual authentication. Двусторонняя аутентификация позволяет повысить уровень безопасности по сравнению с односторонней, а также может служить заменой аутентификации с использованием логина и пароля.

Цепочка действий по генерации сертификатов

Давайте посмотрим на практике, как происходят действия, связанные с генерацией сертификатов, с самого начала, и при этом на практике.

Первое, что делается — это генерация корневого сертификата. Корневой сертификат подписывается самим собой. А потом уже этим сертификатом будут подписываться другие сертификаты.

Таким образом мы сгенерировали сначала приватный ключ, затем запрос подписи, а затем своим ключом подписали свой же запрос и получили собственный цифровой сертификат, выданный на 10 лет. Пароль (challenge password) при генерации сертификата можно не вводить.

Приватный ключ ОБЯЗАТЕЛЬНО необходимо хранить в надежном месте, имея его можно подписать от вашего имени любой сертификат. А полученный корневой сертификат можно использовать для идентификации того, что сертификат, например, сервера подписан именно нами, а не кем-то еще. Именно такие действия выполняют авторизационные центры, когда генерируют собственные сертификаты. После создания корневого сертификата можно приступать к генерации сертификата сервера.

Просмотр информации о сертификате

Содержимое сертификата можно просмотреть таким образом:

Мы видим, кто выдал этот сертификат и когда заканчивается срок его годности.

Серверный сертификат

Для подписи сертификата для сервера нам нужно выполнить следующие действия:

1) Сгенерировать ключ
2) Сгенерировать запрос на подпись
3) Отправить CSR-файл в авторизационный центр или подписать самостоятельно

В серверный сертификат может включаться цепочка сертификатов, которыми подписан сертификат сервера, но ее можно также хранить в отдельном файле. В принципе, выглядит всё примерно так же, как и при генерации корневого сертификата

Таким образом сертификат сервера подписан и мы будем знать, какой организацией выдан этот сертификат. После подписи готовый сертификат можно использовать по назначению, например, установить на веб-сервер.

Установка SSL/TLS-сертификата на сервер с nginx

Для установки SSL/TLS-сертификата на веб-сервер nginx надо выполнить несколько простых шагов:

1) Скопировать файлы .key и .pem на сервер. В различных операционных системах сертификаты и ключи могут храниться в разных директориях. В Debian’е, к примеру, это директория /etc/ssl/certs для сертификатов и /etc/ssl/private для ключей. В CentOS это /etc/pki/tls/certs и /etc/pki/tls/private

2) Прописать необходимые настройки в конфигурационный файл для хоста. Вот как это примерно должно выглядеть (это просто пример):

3) Перезапустить nginx

4) Зайти браузером на 443 порт сервера — https://www.mycompany.com и проверить его работоспособность.

Установка SSL/TLS-сертификата на сервер с Apache

Установка SSL/TLS-сертификата на Apache выглядит примерно так же.

1) Скопировать файлы ключа и сертификата на сервер в соответствующие директории

2) Включить модуль ssl для Apache командой «a2enmod ssl», если он еще не включен

3) Создать виртуальный хост, который будет слушать 443 порт. Конфиг будет выглядеть примерно так:

При этом надо сделать еще кое-что. Найти в файле httpd.conf, или apache2.conf, или ports.conf, в зависимости от системы, такой участок конфига:

Если такого условия нет, его надо добавить в конфиг. И еще одно: Надо добавить строку

Эта строка может находиться в файле httpd.conf, apache2.conf или ports.conf

4) Перезапустить веб-сервер Apache

Создание клиентского сертификата

Клиентский сертификат создается примерно так же, как серверный.

Если необходим клиентский сертификат в формате PKCS12, создаем его:

Теперь можно использовать клиентский сертификат для работы с нашим сервером.

Настройка nginx на использование клиентских сертификатов

Чаще всего, как я уже сказал, используется односторонняя аутентификация, обычно проверяется только сертификат сервера. Давайте посмотрим, как заставить веб-сервер nginx проверять клиентский сертификат. Необходимо в секцию server добавить опции для работы с клиентскими сертификатами:

После этого надо перезагрузить настройки или сервер целиком и можно проверять работу.

Настройка Apache на использование клиентских сертификатов

Apache настраивается также через добавление дополнительных опций в секцию виртуального хоста:

Как видите, опции примерно такие же, как и для nginx, поскольку процесс проверки организован единообразно.

«Прослушка» информации о сертификате при помощи openssl

Для проверки взаимодействия сервера с клиентскими сертификатами можно проверить, устанавливается ли соединение с использованием TLS/SSL.

На стороне сервера запускаем прослушку порта при помощи openssl:

На стороне клиента обращаемся к серверу, например, culr’ом:

В консоли со стороны сервера можно наблюдать процесс обмена информацией между сервером и клиентом.

Можно также использовать опции -verify [глубина проверки] и -Verify [глубина проверки]. Опция с маленькой буквы запрашивает у клиента сертификат, но он не обязан его предоставлять. С большой буквы — если сертификат не предоставлен, возникнет ошибка. Запустим прослушку со стороны сервера таким образом:

Со стороны сервера ошибка выглядит так:

Со стороны клиента так:

Добавим с клиентской стороны сертификат и доменное имя (можно для проверки вписать в файл /etc/hosts имя хоста для адреса 127.0.0.1):

Теперь соединение пройдет успешно и можно устанавливать серверный сертификат на веб-сервер, клиентский отдать клиенту, и работать с ними.

Безопасность

При использовании SSL/TLS одним из основных методов является метод MITM (Man In The Middle), «человек посередине». Этот метод основывается на использовании серверного сертификата и ключа на каком-то узле, который будет прослушивать трафик и расшифровывать информацию, которой обмениваются сервер и клиент. Для организации прослушивания можно использовать, например, программу sslsniff. Поэтому корневой сертификат и ключ обычно желательно хранить на машине, которая не подключена к сети, для подписания приносить запросы на подпись на флэшке, подписывать и так же уносить. И, естественно, делать резервные копии.

В общих чертах именно так и используются цифровые сертификаты и протоколы TLS и SSL. Если есть вопросы/дополнения, пишите в комментарии.

Ключи, шифры, сообщения: как работает TLS

Версия от 28/07/2020

Оглавление

Введение

SSL и TLS представляют собой развитие одной и той же технологии. Аббревиатура TLS (Transport Layer Security) появилась в качестве замены обозначения SSL (Secure Sockets Layer) после того, как протокол окончательно стал интернет-стандартом. Такая замена вызвана юридическими аспектами, так как спецификация SSL изначально принадлежала компании Netscape. И сейчас нередко названия SSL и TLS продолжают использовать в качестве синонимов, но каноническим именем является TLS, а протоколы семейства SSL окончательно устарели и не должны использоваться.

TLS/SSL изначально разработали для защиты коммерческих транзакций, проводимых через Интернет. То есть, основной целью являлось получение относительно безопасного канала для осуществления покупок или управления банковским счётом — хотя, ни первое, ни второе ещё не пользовались какой-то популярностью у рядовых пользователей во времена становления SSL. Зато в современном Интернете на TLS/SSL полагаются не только и не столько в деятельности «по продаже товаров», но и при решении гораздо более общей задачи сохранения «приватности» и конфиденциальности важной информации. Одним из самых распространённых применений TLS является HTTPS. HTTPS стремительно вытесняет незащищённую версию (HTTP): доля зашифрованного веб-трафика растёт, скорее всего, в скором будущем весь веб-трафик будет зашифрован. В новой версии HTTP/2 защита информации средствами TLS должна использоваться по умолчанию. Благодаря такому положению дел, TLS — один из самых изученных, исследованных протоколов современного Интернета. Вместе с тем, история этого протокола показывает, насколько мало бывает практического толка от исследований: например, в 2010 году корпорация Microsoft исправила дефект в реализации SSL своего веб-сервера IIS — CVE-2010-3332; а соответствующая уязвимость была продемонстрирована в 2003 году. То есть, семь лет результаты исследования считались чистой теорией, не заслуживающей практического исправления. Впрочем, начиная, примерно, с 2014 года, интерес к поиску уязвимостей в TLS сильно возрос, а обнаруженные уязвимости стали привлекать внимание «самых широких слоёв» интернет-пользователей. Благодаря этому, процесс исправления дефектов приобрёл некоторую оперативность и непрерывность.

Впервые SSL внедрили в качестве проприетарной технологии, реализованной в браузере Netscape Navigator, одном из первых веб-браузеров. Версия 1 протокола не была опубликована, а так и осталась внутренней разработкой Netscape, развивавшейся в 1994-95 годах. SSLv2 — следующую, вторую версию протокола — опубликовали, однако спецификация так и не вышла из состояния черновика (draft). Более того, хоть в SSLv2 и скорректировали отдельные дефекты и уязвимости v1, протокол оказался ненадёжным, содержащим серьёзные архитектурные огрехи. SSLv2 давно (более 15 лет назад) и без оговорок признан небезопасным, поэтому сейчас не должен использоваться. Если постараться, то в Сети всё ещё можно найти архаичные серверы, которые поддерживают SSLv2. Несмотря на рост популярности TLS, вытеснение дефектных технологий идёт медленно. Однако если ваш сервер или клиентское ПО всё ещё поддерживает SSLv2, можно смело сказать, что у вас просто нет безопасного канала, вы не поддерживаете TLS вовсе. Более того, на практике было продемонстрировано, что наличие сервера с SSLv2, который использует те же ключи, что и современный TLS-сервер, ставит под угрозу сессии TLS (даже если это разные физические серверы, а трафик к ним доставляется независимо).

SSLv3 — это развитие SSLv2, но с весьма существенными доработками. SSLv3 представлен в 1996 году. Этот протокол получил полноценную спецификацию RFC, но значительно позже своего появления, и в статусе исторического документа: RFC 6101. На время SSLv3 пришлось становление TLS как интернет-технологии. Именно на базе SSLv3 и появился протокол TLS.

Сейчас существует четыре версии TLS, все они описаны в RFC: TLS 1.0, TLS 1.1, TLS 1.2 и вышедшая в 2020 году версия TLS 1.3. TLS 1.0 во многом повторяет SSLv3, за исключением ряда деталей, которые, впрочем, являются весьма важными. (В криптографических протоколах детали важны как ни в каких других протоколах Интернета.) Ключевым отличием TLS от SSL является наличие поддержки целого ряда расширений, позволяющих реализовать современные методы защиты информации. TLS 1.1 и 1.2 достаточно близки к 1.0, но в версии 1.2 появились заметные улучшения, например, используется другая основа псевдослучайной функции и введена поддержка шифров в режиме аутентифицированного шифрования.

Несмотря на то, что номер следующей версии получил лишь прибавку единицы в «младшем разряде», TLS 1.3 весьма и весьма существенно отличается от всех предыдущих версий TLS. В частности, радикально изменена логика установления соединения, а сам протокол стал архитектурно стройнее, благодаря тому, что из спецификации удалены многие сообщения (элементы протокола), а оставшиеся — заметно переработаны. По причине фундаментальных различий версий до 1.3 и 1.3, в данном тексте устаревающие версии TLS 1.0, 1.1, 1.2 рассматриваются, по возможности, отдельно, при этом TLS 1.3 описывается даже более детально, чем предыдущие версии. Есть основания полагать, что в общемировом Интернете TLS 1.3 быстро станет основной версией. Так, уже в июле 2020 года поддержку TLS 1.3 для веба предоставляют Google, Facebook и Cloudflare, а также основные ветки браузеров Chrome и Firefox.

Рекомендованными для применения версиями в 2020 году являются TLS 1.3 и 1.2, допускается использование TLS 1.1, однако готовится RFC, который отнесёт версии ниже 1.2 в разряд нерекомендуемых. TLS 1.0 повсеместно поддерживается много лет — данный протокол совместим даже с древним браузером IE 6. Пока рекомендаций по исключению TLS 1.1 нет, эта версия поддерживается практически всеми сколь-нибудь распространёнными программными сервисами веба, а также всевозможных других интернет-приложений. Поддержка TLS 1.2 в 2020 году является повсеместной: все современные браузеры поддерживают эту версию, а проблемы могут возникнуть только с аномально старыми сборками и, иногда, на стороне сервера, при использовании действительно древних приложений.

TLS 1.0 можно назвать версией 3.1 SSL. Собственно, именно так и сделано в спецификациях при описании способа наименования версий: SSL 3.1 — это TLS 1.0; 3.2 — TLS 1.1; 3.3 — TLS 1.2; 3.4 — TLS 1.3. В шестнадцатеричной записи: 0x0301, 0x0302, 0x0303, 0x0304.

С 2015 года SSLv3, следом за публикацией очередных уязвимостей, перешёл в статус прямо нерекомендуемого. Этот статус вполне официальный, каким только официальным он может быть в рамках технологических традиций Интернета: в июне 2015 года выпущен документ RFC 7568, требующий исключить SSLv3 из разряда поддерживаемых клиентами и серверами протоколов. Теперь остались только версии TLS.

Самая современная версия TLS — 1.3. Активная работа в рамках IETF над новой версией TLS началась в 2014 году. Одной из причин разработки нового стандарта стал резко возросший интерес научно-технического сообщества к архитектуре TLS; также сыграло роль обнаружение нескольких существенных дефектов в самом протоколе, что гораздо опаснее наличия дефектов в конкретных реализациях. С момента публикации RFC TLS 1.2 прошло около шести лет — за это время информационный ландшафт в Интернете успел сильно измениться. RFC TLS 1.3 опубликован в августе 2020 года, этому предшествовало большое количество черновиков (draft). Интересно, что протокол был реализован на практике в нескольких черновых вариантах и поддерживался до публикации RFC, но, так как draft-версии отличались друг от друга в существенных моментах, такая поддержка требовала указания специальной версии протокола (c префиксом 0x7F, например: 0x7F1C — draft-28). Так, в браузере Chrome была реализована версия draft-17. Это же относится и к сервисам, поддерживавшим TLS 1.3 до выхода RFC. Спецификация draft-28 практически не отличалась от финального RFC (собственно, единственное значимое отличие касалось только указываемого номера версии: для RFC-версии нужно указывать 0x0304), поэтому соответствующие библиотеки могли быть быстро переведены на RFC-версию.

Версия TLS 1.3 не только несовместима с предыдущими, но и построена на другой инженерной идеологии. Различие обусловлено переосмыслением модели угроз, в рамках которой проектируется новый протокол: TLS попытались сделать и более быстрым (по крайней мере, потенциально), и более защищённым, и более скрытным. Что касается последнего аспекта, то речь тут идёт о совершенно новом для TLS направлении: сведении к минимуму утечек так называемой метаинформации, то есть, данных о том, какие сообщения передаются внутри сессии, в каком состоянии сессия находится в данный момент времени. Существенные усилия были направлены на то, чтобы даже хорошо оснащённая третья сторона не могла узнать ничего более, кроме как о факте установления TLS-соединения.

Предназначение TLS

TLS ставит своей целью создание между двумя узлами сети защищённого от прослушивания и подмены информации канала связи, пригодного для передачи произвольных данных в обоих направлениях, а также проверку того, что обмен данными происходит между именно теми узлами, для которых канал и планировался. Эти задачи называются, соответственно, обеспечением конфиденциальности, целостности и подлинности соединения (аутентификации). Из фундаментальных задач защиты информации, TLS не охватывает только одну: обеспечение доступности информации — и эта задача находится далеко за рамками данного протокола.


Предполагается, что TLS работает поверх существующего между узлами «потокового» соединения (с которым обычно связан «сокет» — откуда старое название SSL, Secure Sockets Layer). Сейчас, в большинстве случаев, TLS будет работать поверх TCP. Именно TCP отвечает за установление соединения, разбивку данных на пакеты, гарантированную доставку этих пакетов (при наличии соединения, естественно) и за разные другие телекоммуникационные моменты. TLS предполагает, что между узлами установлено надёжное соединение, поэтому, например, протокол не охватывает повторную отправку потерянных пакетов данных. (Для работы в условиях негарантированной доставки и неустойчивой связи существует особый, родственный протокол — DTLS, который мы здесь не рассматриваем.) TLS использует установленный канал связи для передачи TLS-сообщений, одного из базовых «строительных блоков» протокола. Эти сообщения кардинальным образом отличаются от пакетов данных (IP-пакетов в TCP/IP) и представляют собой структуру более высокого уровня. TCP позволяет надёжно обмениваться данными, но содержимое пакетов (за исключением специальных случаев) может быть легко прочитано кем-то, кто имеет доступ к каналу связи. Хуже того, этот кто-то может заменить пакеты или изменить передаваемые в них данные. Именно для защиты от этих угроз и используется TLS.

Другими словами, модель угроз TLS предполагает, что атакующий может как угодно вмешиваться в канал связи, в том числе активно подменять пакеты и вообще — прерывать связь. Ключевые задачи TLS: 1) обеспечить конфиденциальность, то есть реализовать защиту от утечек передаваемой информации; 2) обеспечить обнаружение подмены, то есть реализовать сохранение целостности передаваемой информации; 3) обеспечить аутентификацию узлов, то есть дать механизм проверки подлинности источника сообщений. Кроме того, в TLS 1.3 существенное внимание уделено задаче сокрытия метаинформации (это подзадача из первого пункта, обеспечения конфиденциальности), под метаинформацией понимается совокупность таких сведений о TLS-соединении, которые позволяют косвенно судить о передаваемых в защищённом режиме данных. Например, к метаинформации относятся сведения об открытых криптографических ключах узлов, о времени соединения, об адресах, именах узлов и так далее.

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

TLS использует концепцию клиент-сервер, которая, в логике данного протокола, во многом совпадает с логикой клиент-сервер TCP: например, и там, и там соединение инициирует клиент.

Логика TLS

TLS работает с записями (records). Записи находятся в фундаменте протокола. Это нижний транспортный уровень TLS. Сообщения TLS, относящиеся к верхним уровням, могут быть разбиты на несколько записей. Это достаточно важный момент: в некоторых случаях TLS-сообщения требуют сборки из нескольких записей, что существенно влияет на логику обработки состояний протокола.

Если рассматривать сеанс TLS на уровне условного сокета (TCP), то каждая передаваемая TLS-запись представляет собой блок, состоящий из короткого заголовка и, собственно, самих данных. Обратите внимание, что в TLS используется сетевой порядок байтов (старший байт идёт первым, слева направо — «тупоконечное» представление). Разберём заголовок TLS-записи. Заголовок имеет длину 5 байтов, и следующий формат:

Тип — это тип записи (фактически, тип определяет то, как будет интерпретироваться содержимое записи). Определено четыре типа: 20 (0x14) — сообщение Change Cipher Spec (CCS), в версии 1.3 данное сообщение передаётся только как «фиктивное», и не имеет логической роли в самом протоколе; в более ранних версиях — CCS играет важную роль, обозначая момент перехода к защищённому обмену сообщениями; 21 (0x15) — сообщение Alert (это не обязательно предупреждение, есть вполне «фатальные alert-ы»); 22 (0x16) — сообщение Handshake (установление соединения); 23 (0x17) — Application Data (запись содержит данные приложения — то есть, полезную нагрузку); трактовка типа Application Data существенно различается в версии 1.3 и предыдущих версиях.

При передаче информации, основные преобразования с шифрами и кодами аутентификации как раз происходят в блоке данных записи с типом 23 (0x17) Application Data, в TLS 1.3 зашифрование информации узлами начинается существенно раньше, чем в младших версиях: зашифрованы уже сообщения Handshake (тип 0x16). До версии 1.3 — записи, отличные от Application Data, обычно передаются в открытом виде, но, тем не менее, тоже могут быть зашифрованы, в зависимости от текущего состояния TLS-соединения;

Версия протокола — это версия, записанная в двух байтах, как указано выше: 03 00 — это SSLv3, 03 01 — TLS 1.0; 03 02 — TLS 1.1; 03 03 — TLS 1.2; TLS 1.3 в этом поле предписывает использовать значение 03 03, то есть, версию 1.2, само поле при этом игнорируется.

Длина данных — количество байтов, содержащих данные (сами байты данных следуют после заголовка). Так как используется сетевой порядок байтов, для определения длины нужно значение первого слева байта (h) умножить на 2 8 и прибавить значение второго (младшего, l) байта, вот так: h * 256 + l. Пустой блок данных (длина нуль) допускается протоколом, но иногда вызывает сбои в клиентах, написанных с ошибками. Максимальная допустимая длина данных записи в TLS 1.3 — 2 14 байтов.

Пример заголовка записи TLS 1.1 (значения байтов — в шестнадцатеричной записи):

Раскодируем: это сообщение Handshake (0x16); версия 3.2 (0x03,0x02)- то есть TLS 1.1; длина данных — 0x03FE байтов (1022 байта).

Заголовок всегда передаётся в открытом виде. В том числе, и при использовании TLS 1.3. Однако в TLS 1.3 предусмотрено сокрытие реального типа записи (для защищённых записей) — подробнее этот момент разобран в отдельном подразделе.

За заголовком должно следовать определённое число байтов (>=0), которые представляют собой содержимое данной записи. Максимальное значение в версиях до 1.3 — 18432 байта. 18432 = 16384 + 2048. То есть, 16 килобайт + два раза по килобайту. Такое значение может показаться странным. Действительно, «базовая» версия записи, описанная в спецификации, предполагает блок данных в 2 14 байтов, то есть 16 килобайт. Но такой размер относится только к записям, содержащим открытый текст (TLSPlaintext). Например, к сообщениям, управляющим установлением соединения (Handshake). Здесь, действительно, максимальная длина — 16К.

Для защищённых записей ситуация меняется. Во-первых, в TLS до версии 1.3 было возможно использование сжатия данных. Собственно, спецификация предписывала, что сжиматься должны все данные защищённой записи. Но на практике это довольно давно означает не совсем то, о чём можно подумать (для TLS это нередкая ситуация): на практике, сжатие не используется (или, если хотите, используется только «тривиальное сжатие»). Дело в том, что TLS всех версий среди перечня алгоритмов сжатия содержит алгоритм null, означающий, что никакого сжатия в реальности не производится. Этот алгоритм служит вариантом по умолчанию (раньше можно было встретить алгоритм DEFLATE, но он давно относится к нерекомендованным из-за обнаруженных уязвимостей). Тем не менее, реально сжатые данные могут, в ряде случаев, оказаться длиннее, из-за особенностей алгоритма сжатия (это выглядит контринтуитивным, но для любого алгоритма сжатия можно подобрать входные данные таким образом, что результат кодирования «со сжатием» окажется длиннее исходных данных). TLS отводит на такое увеличение длины 1024 байта (хорошо реализованные алгоритмы используют значительно меньше). В TLS 1.3 сжатие прямо запрещено, поэтому данное «дополнение» не применяется.

Во-вторых, для проверки целостности зашифрованных данных к ним приписывается код аутентификации сообщения (MAC) и дополнительная информация (вроде векторов инициализации шифров) — на это в TLS старых версий отводится ещё 1024 байта. Итого — 2048, хотя данный момент и вносит некоторую сумятицу в организацию протокола. Естественно, универсальные и, потому, фиксированные 16K в качестве максимального предела смотрелись бы лучше. В реальности, редкая запись TLS дотягивает и до 16K — обычно длина заметно меньше.

В TLS 1.3 ситуацию упростили: для защищённых данных дополнительно допускается только 256 байтов для кода аутентификации (MAC), сжатие запрещено. То есть, максимальный размер: 16384 + 256 = 16640. При этом в 16384 байта входят байты дополнения (record padding) — байты со значением 0, которые могут приписываться в конец блока защищаемых данных для того, чтобы скрыть их длину, а также для выравнивания размера записи.

Код аутентификации сообщения — важнейший элемент защиты информации в TLS. В версиях до 1.3 обычно используется HMAC, с той или иной хеш-функцией. Типичный выбор: SHA-1 или SHA-256. Код аутентификации приписывается к блоку данных. Один из архитектурных дефектов версий TLS до 1.3 состоит в том, что соответствующие спецификации предписывают сперва вычислять MAC, а потом шифровать сообщение. То есть, вычисленный код аутентификации присоединяется к открытому тексту сообщения, а потом все вместе зашифровывается. При этом принимающая сторона должна сперва расшифровать полученные данные, а потом — проверить MAC. Хорошо известно, что такой метод легко приводит к возникновению «криптографических оракулов», на использовании которых основано несколько эффективных атак против TLS (эти атаки подробно рассмотрены в специальном разделе). Современный подход: код аутентификации добавляется после зашифрования открытого текста, то есть MAC вычисляется для уже зашифрованного сообщения и прикрепляется к нему («сперва шифр, потом — MAC»). Для внедрения современного подхода в спецификации добавлено специальное расширение, позволяющее клиенту и серверу договориться о том, в какой последовательности они генерируют коды аутентификации — RFC 7366. Современная версия TLS 1.3 использует шифры только в режиме аутентифицированного шифрования (а именно — AEAD). Этот режим не нуждается в отдельном MAC, так как целостность данных гарантирует сам алгоритм шифрования (подробное описание дано ниже, в разделе, посвящённом шифрам). Пример: AES в режиме GCM, этот вариант является предпочтительным, поддерживается всем современным ПО, и имеет большое распространение.

Используемые криптосистемы в TLS объединяются в типовые шифронаборы (Cipher Suites, иногда используется русскоязычный термин «криптонаборы»). Чтобы начать обмен информацией по защищённому каналу, клиент и сервер должны согласовать используемый шифронабор. Очевидно, что параметры шифров и обмена сопутствующей информацией должны быть совместимы между собой. Согласование проводится на этапе установления соединения (Handshake). Композиции шифронаборов существенно отличаются в TLS 1.3 и в предшествующих версиях. Так, в TLS 1.2 и младше в шифронабор входят:

  • криптосистема, используемая для аутентификации (аутентифицируются сервер и сеансовый секрет);
  • шифр, который послужит для защиты передаваемых данных в симметричном режиме;
  • хеш-функция, являющаяся основой для HMAC.

В TLS 1.3 криптосистемы, служащие для аутентификации узлов и получения общего секрета, отделены от, собственно, шифров, что потребовало изменения организации реестра и механизма нумерации шифронаборов (а каждый из них обозначается двухбайтовым индексом). Кроме этих индексов, существуют стандартные обозначения (символьные имена) для шифронаборов. Например, выбор в TLS 1.1 типового шифронабора TLS_RSA_WITH_AES_128_CBC_SHA означает, что будет использована криптосистема RSA для передачи сеансового ключа, AES со 128-битным ключом в режиме CBC в качестве симметричного шифра (то есть, защищаемые данные приложения будут зашифрованы симметричным шифром AES), SHA-1 в качестве хеш-функции HMAC. Для TLS 1.3 ситуация отличается. Шифронаборов здесь меньше, а их имена, соответственно, содержат только указания на шифр и хеш-функцию, например: TLS_AES_256_GCM_SHA384 — шифр AES в режиме GCM и хеш-функция SHA-384. Шифронаборы строго фиксированы, состав закреплён в RFC, каждому приписан свой индекс, а реестр ведёт IANA.

Шифронаборы имеют важнейшее значение для безопасности TLS. Выбор нестойкой комбинации означает, что достаточной защиты конкретная реализация TLS не обеспечивает. Поэтому, в TLS 1.3 число допустимых шифронаборов резко сокращено — рекомендовано только четыре (2020). Применительно к вебу: браузеры используют встроенный комплект шифронаборов, обычно это 10-15 вариантов, которые могут использоваться с разными версиями TLS; на сервере поддерживаемые шифронаборы настраиваются администратором. Реестр IANA в настоящий момент содержит свыше 300 (трёх сотен, да) шифронаборов (в число которых входят и так называемые псевдошифры, которые используются в качестве сигналов). Среди шифронаборов встречается экзотика вроде TLS_KRB5_WITH_RC4_128_SHA и безнадёжно устаревшие варианты, например — TLS_RSA_EXPORT_WITH_RC4_40_MD5. Современные серверы и клиенты не должны использовать подобного. Наличие того или иного шифронабора в реестре IANA означает, что этому шифронабору присвоен индекс (номер) и обозначение, не более того: нужно понимать, что данный реестр не имеет никакого отношения к тому, какие шифры и криптосистемы рекомендованы или не рекомендованы для использования. В 2020 году добротным вариантом считается, как минимум, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA256, допустимый для TLS 1.2: то есть, генерация общего секрета проводится по протоколу Диффи-Хеллмана на эллиптических кривых, для аутентификации данных на этапе установления соединения используется криптосистема электронной подписи ECDSA (тоже работающая на эллиптических кривых), полезная нагрузка зашифровывается AES с 256-битным ключом в режиме GCM, а в качестве хеш-функции служит SHA-256 (здесь используется при генерации сеансовых ключей).

Первоначальное соединение (Handshake)

(TLS Handshake иногда в современных русскоязычных статьях называют «рукопожатием», что является прямым, и не очень удачным, переводом английского термина; этот вариант мы не станем использовать.)

Клиент и сервер должны договориться об используемых шифрах и методах аутентификации, согласовать ключи и другие параметры сеанса связи. Набор согласованных параметров называется криптографическим контекстом. Согласование происходит при установлении соединения, путём обмена специальными сообщениями — handshake-сообщениями. Такой обмен в TLS осуществляется поверх обмена записями. Каждое Handshake-сообщение содержит специальный заголовок, состоящий из четырёх байтов. Первый байт обозначает код типа сообщения, три следующих байта — длину сообщения.

В TLS 1.3 установление соединения организовано таким образом, что уже на втором шаге используется защищённый режим, то есть, разбор Handshake версии 1.3 требует, как минимум, использования протокола Диффи-Хеллмана и симметричных шифров. К TLS 1.2 и раньше — этот момент не относится. Поэтому мы сначала подробно разберём установление соединения в 1.2, потом рассмотрим протокол Диффи-Хеллмана (применительно к TLS) и симметричные шифры, после этого перейдём к анализу Handshake версии 1.3. (Заметьте, что для понимания принципов построения TLS 1.3 — необходимо понимание версии 1.2, особенно с учётом того, что 1.3 отличается весьма существенно.)

Сообщения Handshake TLS 1.2 (и ранее)

Handshake-сообщения отправляются в виде TLS-записей, которые мы обсудили выше. Это означает, что заголовку сообщения предшествует заголовок записи, где тип сообщения определён кодом 22 (0x16) — см. выше. Несколько Handshake-сообщений могут быть переданы в одной записи — это распространённый случай, например, так нередко поступает Miscrosoft IIS. А самое интересное, что одно сообщение может быть разбито на несколько записей, передаваемых последовательно — спецификация допускает и это, например, можно «нарезать» сообщения на записи длиной в один байт полезной нагрузки каждое. К счастью, последний вариант скорее теоретический, на практике встречается исчезающе редко. (А экстремальный метод «запутывания» состоит в передаче перед разрезанным на несколько записей сообщением пустых записей, то есть TLS-записей, состоящих из одного заголовка, где в качестве длины указан нуль; такой вариант также допускается спецификацией.) Все эти случаи должны корректно поддерживаться добротной реализацией TLS. Таким образом, находящийся ниже протокола установления соединения уровень TLS-записей нужно рассматривать как некий потоковый псевдосокет, куда сообщения записываются как есть, и где они могут быть разрезаны на блоки для передачи. Единственное, что запрещает спецификация TLS — это нарушение порядка при доставке записей (в отличие от IPv4). Всё это верно и для TLS 1.3.

Спецификация предполагает, что любой клиент и сервер TLS по умолчанию уже согласовали шифронабор null, без MAC и с «нулевым» сжатием. То есть клиент и сервер могут обмениваться сообщениями в виде открытого текста без аутентификации. Установление соединения всегда начинает клиент. В типичной конфигурации, TLS здесь оказывается схож с TCP, так как, например, при работе с сервером по HTTPS — TCP-соединение также инициирует клиент. Благодаря историческому совпадению принципов построения технологий, клиент HTTPS, TLS, TCP — один и тот же узел. Можно предложить конфигурации протоколов, когда это не так, но в наиболее распространённой ситуации веба — подобные конфигурации едва ли возможны.

Первым сообщением в протоколе установления TLS-соединения всегда является сообщение ClientHello (тип 01). Сообщение содержит следующие данные:

  1. версию протокола — максимальную версию, которую готов поддерживать клиент;
  2. 32 байта случайных значений — ClientRandom. Изначально, в спецификации рекомендовалось использовать первые 4 байта для передачи UNIX-таймстемпа, а оставшиеся 28 — заполнять результатом работы криптографического генератора псевдослучайных чисел. Однако сейчас многие браузеры и веб-серверы генерируют все 32-байта случайным образом. Забегая чуть вперёд: предполагалось, что наличие таймстемпа в handshake-сообщениях может помочь при обнаружении проблем с подменой времени на том или ином узле. Однако данный метод сейчас никак не используется, поэтому часто все байты ClientRandom случайны. Такой подход закреплён и в TLS 1.3;
  3. идентификатор TLS-сессии — SessionID: TLS позволяет возобновлять ранее установленные сессии, используя сокращённый вариант протокола установления соединения. Идентификатор сессии как раз содержит номер такой сессии, параметры которой (возможно) сохранены на сервере (подробнее мы рассмотрим этот вариант ниже). В TLS 1.3 данное поле может быть пустым, а если присутствует, то играет другую роль: обнаружив в ClientHello поле SessionID, сервер включает его значение в свой ответ без изменений, при этом как номер сессии SessionID в 1.3 не используется, но может служить инструментом имитации сессий версии 1.2;
  4. список шифронаборов, которые поддерживает клиент — Cipher Suites. Порядок шифронаборов в списке отражает их степень предпочтения клиентом (предпочтительные передаются первыми), этот порядок — всего лишь рекомендация, и сервер далеко не всегда ей следует;
  5. список поддерживаемых методов сжатия — Compression Methods, порядок, опять же, соответствует степени предпочтения, но обычно в этом поле лишь одно значение — null, так как сжатие не рекомендуется использовать. В TLS 1.3 — сжатие прямо запрещено, но, по «историческим причинам», данное поле сохраняется, с фиксированным значением null;
  6. данные нескольких расширений протокола.
Мастер Йода рекомендует:  Создаем изометрический пиксельный плакат для билборда

Каждое из полей в сообщении ClientHello также имеет свой формат, а полю предшествуют данные о его длине и, в случае расширений, дополнительный заголовок. Заголовок обычно содержит тип расширения и длину его данных. Такая структура позволяет реализациям корректно разбирать сообщения. Например, список шифронаборов может быть представлен в следующем виде (шестнадцатеричная запись):

Расширения ClientHello позволяют использовать различные нововведения, которые появились позже, чем структура данного сообщения. Так, например, в расширениях могут быть перечислены эллиптические кривые, которые готов использовать клиент. Самым распространённым расширением является SNI (Server Name Indication), позволяющее браузеру указать имя веб-сервера, с которым он пытается установить соединение. SNI необходимо для того, чтобы на одном IP-адресе могли корректно откликаться по HTTPS веб-серверы, размещённые под разными доменами.

Разберём ClientHello в деталях. В качестве примера возьмём специальный образец ClientHello, сгенерированный утилитой опроса TLS-серверов в исследовательских целях. В качестве сервера используется sbrf.ru.

Согласно спецификации, после отправки ClientHello, клиент ожидает ответа сервера. В ответ может прийти либо сообщение об ошибке, в виде Alert, либо сообщение ServerHello.

Alert — короткие сообщения, содержащие информацию об уровне ошибки и о её типе. Сообщение Alert, например, может сигнализировать о сбое установления соединения. Рассмотрим такой вариант подробнее:

Если же сервер смог успешно обработать ClientHello, то он отвечает сообщением ServerHello. Это сообщение так же имеет заголовок из четырёх байтов: тип сообщения (один байт) и длина (три байта). ServerHello (здесь мы рассматриваем версии до 1.3) содержит следующие поля:

1) версию протокола, которую будут использовать клиент и сервер;

2) 32 байта случайных значений — ServerRandom. С этой строкой ситуация такая же, как и с Client Random: первые четыре байта могут быть таймстемпом, а могут и не быть. Интересным свойством данной метки времени является то, что она может послужить некоторым справочным материалом при последующем анализе записанного трафика: если сервер отвечает достоверным значением времени, то, учитывая, что полный набор сообщений Handshake содержит сообщение, криптографически удостоверяющее целостность данных (см. ниже про сообщение Finished), получаем подписанную сервером квитанцию о времени соединения по его часам, с точностью до секунды — иногда эти данные помогают правильно составить запрос в адрес администрации сервера об извлечении записей из логов;

3) идентификатор сессии — SessionID, присвоенный новой сессии сервером (в случае TLS 1.3 — данное поле обязательно повторяет SessionID клиента);

4) выбранный сервером шифронабор — Cipher Suite, этот шифронабор будет использоваться в дальнейшем и клиентом, и сервером. Сервер выбирает шифронабор из предложенных клиентом в ClientHello, но не обязательно следует приоритету клиента: распространена как раз обратная ситуация, когда сервер исключительно сам определяет предпочтительный шифронабор;

5) выбранный сервером метод сжатия — скорее всего, это null;

6) некоторый набор расширений.

В современных реализациях TLS раздел «Расширения» (Extensions) имеет очень большое значение, так как в нём передаются параметры, определяющие схему работы и клиента, и сервера. Предназначение ServerHello — согласовать параметры соединения. TLS использует хорошо известную схему «запрос-ответ-подтверждение» (за исключением варианта ускоренного установления соединения), а сообщения ClientHello и ServerHello запускают схему. Эти сообщения не содержат никакой секретной информации, соответственно — передаются в открытом виде (в TLS 1.3 ситуация поменялась — практически сразу же сообщения Handshake передаются в зашифрованном виде, тем не менее, ServerHello и ряд расширений всё равно открыты). Данные сообщения, особенно — ClientHello, повсеместно используются в системах DPI для обнаружения факта установления (или попытки установления) TLS-соединения.

В рамках каждой сессии TLS, клиент и сервер согласовывают следующие параметры (RFC 5246):

1) роли узлов: какой узел является клиентом, а какой — сервером. Распределение этих ролей происходит «естественным образом», при установлении соединения — клиент всегда начинает сессию;

2) алгоритм PRF (псевдослучайная функция, PseudoRandom Function) — используется для генерации сеансового ключа на основе данных, переданных в ClientHello и ServerHello, поэтому клиент и сервер должны использовать согласованный алгоритм;

3) шифр — для успешного зашифрования потока данных внутри сессии оба узла должны использовать один и тот же алгоритм, в согласованном режиме. Узлы согласуют тип шифра (потоковый, блочный), сам шифр, режим использования шифра, размер ключа, размер блока (для блочных шифров), инициализирующие векторы, а также дополнительные параметры (если они требуются, например, в случае с AEAD-режимами);

4) алгоритм вычисления кода аутентификации сообщения (MAC) — аналогично шифрованию, в рамках сессии необходимо использовать согласованный алгоритм аутентификации. Для AEAD-режима шифрования MAC не используется;

5) алгоритм сжатия — также должен быть общим, однако в современной реализации сжатие, фактически, не используется, что означает общий алгоритм null;

6) основной секрет (MasterSecret) — массив из 48 секретных байтов, известный серверу и клиенту. Основное предназначение данного массива — генерация сеансового ключа, в тех шифронаборах, где применимо. Это 384-битное значение MasterSecret позволяет вычислить секретные ключи сессии, то есть, если это значение стало известно третьей стороне, то она сможет расшифровать трафик сессии. В TLS 1.3 используется более сложная схема, состоящая из секретов разных уровней, которые соответствуют стадиям работы протокола;

7) случайные данные клиента (ClientRandom) — 32 байта случайных значений, передаются в ClientHello;

8) случайные данные сервера (ServerRandom) — 32 байта случайных значений, передаются в ServerHello.

Эти параметры позволяют построить контекст для работы криптосистем, которые будут обрабатывать защищённые TLS-записи на стороне сервера и клиента. Помимо ClientHello и ServerHello, установление соединения подразумевает обмен несколькими другими сообщениями.

За отправкой ServerHello, со стороны сервера следует набор других сообщений, состав и содержание которых зависят от выбранного сервером режима работы.

Certificate. Ключевым аспектом для современных реализаций TLS является использование TLS-сертификатов (ранее они назывались SSL-сертификатами, сейчас рекомендуется вариант с TLS), мы рассмотрим их подробнее ниже. Сертификаты передаются сервером в сообщении Certificate. Это сообщение присутствует практически всегда. Серверный сертификат содержит открытый ключ сервера. В теории, спецификация позволяет установить соединение без отправки серверных сертификатов. Это так называемый «анонимный» режим, однако он практически не используется, как и режимы TLS без шифрования. Так, свыше 99% веб-серверов, поддерживающих TLS, передают TLS-сертификаты. В типичной конфигурации, сообщение Certificate будет включать несколько TLS-сертификатов, среди которых один серверный сертификат и так называемые «промежуточные сертификаты», позволяющие клиенту выстроить цепочку валидации. Серверный сертификат — это сертификат, по имени соответствующий серверу и содержащий серверный открытый ключ электронной подписи (RSA или ECDSA). Спецификация предписывает строгий порядок следования сертификатов в сообщении: первым должен идти серверный сертификат, а последующие — в порядке удостоверения предыдущего. Однако на практике серверы нередко отправляют сертификаты в произвольном порядке. На клиентской стороне браузеры тоже достаточно свободно относятся к порядку сертификатов, пытаясь выстроить из них корректную цепочку применяя различные перестановки. Такое положение дел прямо нарушает спецификацию TLS версий 1.0, 1.1, 1.2, но такова реальность: несмотря на все строгости криптографии — реализации допускают вольности (последние нередко ведут к уязвимостям). Хотя, достаточно сложно найти веские причины для строго порядка следования сертификатов. В TLS 1.3 данное требование смягчили, сделав допустимым произвольный порядок промежуточных сертификатов (серверный всё равно ожидается первым).

ServerKeyExchange. Это сообщение, содержащее серверную часть данных, необходимых для генерации общего сеансового ключа. Сообщение может отсутствовать, а в TLS 1.3 оно не используется, так как новая схема Handshake для обмена криптографическими параметрами предусматривает расширения Hello-сообщений. В версии TLS 1.2 и ранее ServerKeyExchange обычно содержит параметры протокола Диффи-Хеллмана (DH), однако исторический вариант предусматривает и передачу временного ключа RSA. Если используется классический вариант DH, то в сообщении ServerKeyExchange передаётся значение модуля (простое число) и серверный открытый ключ. В варианте на эллиптических кривых (ECDH) — идентификатор самой кривой и, аналогично DH, открытый ключ сервера. Параметры подписываются сервером (за исключением экзотических вариантов обмена, вроде анонимного DH), клиент может проверить подпись при помощи открытого ключа сервера из TLS-сертификата. В зависимости от используемой криптосистемы, подпись может быть DSA (сейчас практически не встречается), RSA или ECDSA. Подпись на параметрах DH очень важна, так как позволяет защитить соединение от атаки типа «человек посередине». В разных версиях TLS подпись вычисляется для разных наборов данных. В TLS 1.0, 1.1 (при использовании RSA, что является основным вариантом) — от объединения значений двух хеш-функций — MD5 и SHA-1, взятых от параметров обмена DH. В TLS 1.2 — от значения хеш-функции, заданной в используемом шифронаборе, вычисленного для объединения ServerRandom, ClientRandom и параметров обмена DH (ECDH). В современной (2020) ситуации сообщение ServerKeyExchange можно увидеть в большинстве TLS-сессий (для версий, отличных от 1.3).

CertificateRequest. В TLS возможна обоюдная (двухсторонняя) аутентификация узлов, использующая TLS-сертификаты. Сертификаты могут быть выпущены для самых разных имён и, соответственно, они пригодны для аутентификации клиента. Обычно, клиентские сертификаты используются при доступе к банковским, платёжным системам, к корпоративным веб-шлюзам различного назначения, а также к государственным информационным системам через веб-интерфейс. Сервер может запросить клиентский сертификат при помощи сообщения CertificateRequest. Сообщение содержит список поддерживаемых сервером типов сертификатов и типов криптосистем — здесь указываются криптосистемы, относящиеся к процедуре валидации клиентского сертификата: алгоритмы подписи, хеш-функции. Также в составе CertificateRequest могут быть переданы имена удостоверяющих центров, ключи которых сервер будет использовать для проверки клиентского сертификата.

ServerHelloDone. В TLS 1.2 и раньше — это сообщение обозначает окончание пакета, возглавляемого ServerHello. Сообщение имеет нулевую длину (в TLS-записи ServerHelloDone соответствует 4 байта, так как присутствует заголовок записи) и служит простым флагом, обозначающим, что сервер передал свою часть начальных данных и теперь ожидает ответа от клиента.

Итак, сервер отвечает на ClientHello последовательностью сообщений TLS Handshake, максимум — пятью сообщениями. Типичный для TLS 1.2 случай: передача сервером четырёх сообщений — ServerHello, Certificate, ServerKeyExchange (с параметрами алгоритма Диффи-Хеллмана), ServerHelloDone. После передачи ServerHelloDone сервер ожидает ответа клиента. Клиент должен ответить своим набором сообщений:

Certificate — это сообщение содержит клиентский сертификат, если он был запрошен сервером. Если у клиента сертификата нет, а сервер его запрашивает, то клиент либо пропускает данное сообщение (SSLv3), либо отвечает пустым сообщением с типом Certificate (TLS). Клиентский сертификат требуется для двухстороннней аутентификации. Все современные браузеры, работающие на десктопе, поддерживают клиентские сертификаты. Клиентский сертификат, в ряде случаев, может заменить пару «логин/пароль» для аутентификации на том или ином онлайн-ресурсе (для аутентификации требуется секретный ключ, соответствующий сертификату).

ClientKeyExchange — клиентская часть обмена данными, позволяющими узлам получить общий сеансовый ключ. Содержание этого сообщения зависит от того, какой шифронабор выбран. В версиях TLS до 1.3 есть два основных типа — RSA и несколько вариантов протокола Диффи-Хеллмана. В случае использования RSA, клиент генерирует 48-байтовый случайный секрет (при этом первые два байта содержат версию используемого протокола), зашифровывает его открытым RSA-ключом сервера (этот ключ передаётся в составе серверного TLS-сертификата или в сообщении ServerKeyExchange) и передаёт зашифрованные данные на сервер. Сервер может расшифровать значение, используя соответствующий секретный ключ. Данная схема прямо запрещена в TLS 1.3, да и для других версий является скорее исторической, так как обладает целым рядом недостатков. Например, если секретный серверный ключ (от сертификата) станет известен третьей стороне, то она сможет расшифровать ранее записанный TLS-трафик. Тем не менее, обмен сеансовым ключом при помощи RSA продолжает использоваться в некоторых реализациях TLS (кроме 1.3). Современный метод — использование протокола Диффи-Хеллмана. В этом случае, ClientKeyExchange содержит открытый ключ DH. Этот ключ генерируется клиентом либо в соответствии с параметрами, переданными сервером в ServerKeyExchange, либо в соответствии с параметрами, указанными в серверном TLS-сертификате, если последний поддерживает DH. Случай с передачей параметров классического DH в составе сертификата — сейчас является экзотическим, таких сертификатов в «дикой природе» не встречается. Серверные параметры DH (или ECDH) подписываются серверным ключом, клиент проверяет подпись, используя открытый ключ сервера.

CertificateVerify — если клиент передал в ответ на запрос сервера свой сертификат, то серверу требуется некоторый механизм, позволяющий проверить, что клиент действительно обладает секретным ключом, связанным с сертификатом. Для этого клиент подписывает массив переданных и принятых ранее сообщений Handshake. Такая подпись, если её значение удастся успешно проверить открытым ключом из сертификата, удостоверит факт наличия секретного ключа у клиента. Сообщение передаётся только если был передан клиентский сертификат в сообщении Certificate. В TLS 1.3 аналог этого сообщения перенесён на сторону сервера и служит механизмом ранней аутентификации криптографических параметров (подробнее схема рассматривается ниже, в описании Handshake версии 1.3).

Клиентские сертификаты используются редко. Поэтому в типичном случае клиент, на данном этапе, передаёт одно сообщение — ClientKeyExchange. Это сообщение является, согласно спецификации, обязательным.

Следом за сообщением ClientKeyExchange, если оно было единственным, либо за CertificateVerify, клиент должен передать сообщение ChangeCipherSpec. Важный момент: это сообщение не является сообщением Handshake. Да, в спецификации TLS встречаются такие, не совсем прозрачные, моменты, когда вроде бы логичное течение протокола прерывается специальными «вставками». При разработке TLS 1.3 от этой сомнительной практики отказались, но ChangeCipherSpec всё равно рекомендуется передавать, правда, в качестве фиктивного сообщения, которое просто игнорируется узлами (сообщение нужно для того, чтобы «обмануть» неверно настроенные промежуточные узлы, замаскировав соединение версии 1.3 под предыдущие версии).

ChangeCipherSpec — это специальное сообщение-сигнал, обозначающее, что с данного момента клиент переходит на выбранный шифр, а следующие TLS-записи будут зашифрованы. ChangeCipherSpec (CCS) имеет собственный тип и, соответственно, передаётся в отдельной TLS-записи. Таким образом, CCS имеет весьма важное значение в TLS (но только раньше версии 1.3), отделяя открытую часть сеанса связи от защищённой.

Со стороны клиента установление соединения завершается отправкой сообщения Finished.

Finished. Это сообщение передаётся в зашифрованной TLS-записи, так как следует за сигналом ChangeCipherSpec, который обозначает момент перехода к защищённому обмену информацией. Finished является первым защищённым сообщением в рамках нового сеанса TLS. Вспомните, что к моменту его отправки, если всё прошло успешно, сервер и клиент уже согласовали все необходимые параметры сессии: шифронабор, сеансовый ключ, алгоритм кода аутентификации сообщения. Предназначение сообщений Finished — получить криптографически стойкое подтверждение, что сервер согласовал эти параметры именно с тем узлом, с которым предполагалось, то же самое — и для клиента, который получит сообщение Finished от сервера.

Клиентское Finished содержит отпечаток — значение хеш-функции, — от всех предыдущих сообщений Handshake, отправленных, на данный момент, и клиентом, и сервером. Получив это сообщение в защищённой TLS-записи, сервер может вычислить значение хеш-функции от известных ему предшествовавших сообщений и сравнить результат. Таким образом подтверждается подлинность сообщений и, соответственно, оказываются криптографически защищены выбранный шифронабор и другие параметры соединения. Впрочем, данная защита не лишена недостатков: например, так как сообщения ClientHello и ServerHello не содержат подписей, Finished никак не защищает сессию от атак, основанных на подмене параметров до отправки ChangeCipherSpec. Этот дефект протокола использован в нашумевшей в 2015 году атаке Logjam (об атаках на TLS/SSL мы подробно поговорим ниже). В TLS 1.3 аутентификация параметров сессии начинается раньше: а именно — сервер незамедлительно удостоверяет первую часть сообщений Handshake, включая выбор криптосистем, при помощи серверного сообщения CertificateVerify.

В ответ на Finished со стороны клиента, сервер, в случае успешного установления соединения, отправляет свою пару ChangeCipherSpec и Finished. На стороне клиента полученное серверное сообщение Finished также используется для проверки, что сообщения Handshake не подверглись модификации активным атакующим, который перехватил канал. Состав Finished сервера отличается от клиентского варианта, так как включает клиентское сообщение Finished (и отличную от клиентской дополнительную символьную строку).

Третьей стороне, активно перехватывающей канал связи, для того, чтобы успешно произвести подмену сообщений Handshake, потребуется вычислить сеансовый ключ и другие секретные параметры (если они использовались), после чего сфабриковать корректное сообщение Finished. Это вычислительно трудная задача, обычно неразрешимая на практике, если выбраны правильные настройки протокола и корректная реализация. Однако, в случае использования нестойких шифронаборов, атакующий может на лету вычислить секретный сеансовый ключ и — успешно подделать сообщение Finished.

После того как клиент и сервер обменялись парами ChangeCipherSpec и Finished, защищённое соединение успешно установлено и данные могут передаваться в защищённой форме.

Посмотрим на ServerHello (TLS 1.1) и последующие сообщения сервера в деталях, примером послужит ответ сервера на сообщение ClientHello, которое разбиралось выше. В этом примере несколько сообщений TLS передаются в одной TLS-записи.

Сокращённый формат Handshake в TLS 1.2 (и раньше)

Установление TLS-соединения — многоступенчатый процесс, достаточно сложный и требующий проведения заметного количества вычислительных операций, особенно жадными в плане процессорного времени оказываются операции проверки подписей и других действий с асимметричными криптосистемами. Каждая итерация, связанная с отправкой запроса и получением ответа, вносит дополнительную задержку, а для массовых сервисов миллисекунды ожидания превращаются в весьма ощутимые затраты на оборудование. Для экономии ресурсов существует сокращённая версия Handshake.

В составе ServerHello сервер передаёт SessionID — идентификатор новой сессии. Этот идентификатор может быть использован клиентом позже, в составе ClientHello (см. выше). Предполагается, что на стороне сервера (и клиента) сохранены необходимые параметры, которые могут быть быстро восстановлены, возобновив тем самым сессию.

В случае использования сокращённой схемы, сразу после получения ClientHello, содержащего валидный идентификатор сесcии SessionID, сервер отвечает сообщениями ServerHello, ChangeCipherSpec и Finished (этот вариант, кстати, напоминает Handshake TLS 1.3). После того как клиент пришлёт свои CCS и Finished, сессия возобновляется и узлы могут начать обмен данными в защищённом режиме.

Сокращённый сценарий содержит существенно меньше сообщений, позволяет не использовать вычислительно затратные операции проверки подписей и генерации общего секрета, кроме того, из-за меньшего количества сообщений заметно снижается задержка при установлении соединения (экономится время, требуемое на отправку пакетов от клиента к серверу и обратно). Современные браузеры широко используют сокращённый Handshake. Сессии могут сохраняться на серверах в течение нескольких минут, нескольких часов, а возможно — дольше.

Сейчас используются и другие способы возобновления сессий. Например, RFC 5077 вводит понятие тикета сессии (TLS Session Ticket) — это расширение, в рамках которого сервер передаёт клиенту зашифрованное представление серверного контекста TLS. Клиент может восстановить сессию, передав в составе расширения ClientHello сохранённый тикет.

Общие замечания

После того как клиент и сервер установили соединение (по полной или сокращённой схеме), они обмениваются TLS-записями с типом Application Data, каждая такая запись содержит блок данных, зашифрованный симметричным шифром, а также код аутентификации сообщения. Код аутентификации защищает сообщение от изменения. Клиент и сервер самостоятельно ведут учёт полученных и переданных блоков.

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

Повторное проведение Handshake

Во время работы в рамках TLS-сессии клиент и сервер могут столкнуться с необходимостью повторно провести Handshake. Такой случай предусмотрен протоколом. Хрестоматийная ситуация, когда это может потребоваться, следующая: после того как установлено TLS-соединение, клиент, использующий HTTP, запрашивает документ по некоторому URL, однако этот URL требует дополнительной авторизации с использованием клиентского сертификата. Клиентский сертификат может быть передан только в составе сообщения Handshake, поэтому сервер отправляет клиенту сообщение HelloRequest, требующее повторного обмена сообщениями Handshake (уже с клиентским сертификатом). Клиент может инициировать новую сессию в любой момент, передав сообщение ClientHello (в TLS 1.3 эта возможность исключена). Так как узлы уже согласовали TLS-соединение, обмен сообщениями повторного Handshake будет проводиться в защищённом виде. В примере с клиентским сертификатом это означает, что сертификат не будет виден прослушивающей канал стороне.

Предупреждения (Alert)

Спецификация TLS предусматривает обмен сообщениями с типом Alert. Это предупреждения и сообщения об ошибках. Например, в случае, если сервер не смог корректно разобрать сообщение ClientHello, он отвечает сообщением Alert, содержащим код ошибки Parse Error. Сообщения Alert иногда могут быть использованы в составе атак на TLS-узлы: так, при помощи отправки этих сообщений можно «подвешивать» сессию, когда перехватывающему устройству требуется время на, например, вычисление ключа.

После того, как узлы согласовали криптографический контекст и обменялись сообщениями ChangeCipherSpec — сообщения Alert передаются в зашифрованном виде. То есть, с этого момента содержание предупреждения не может быть прочитано прослушивающей трафик стороной, но сам тип записи — Alert — всё равно передаётся в открытом виде (до TLS 1.3), что, соответственно, может приводить к утечке информации о состоянии узлов и соединения.

Сеансовые ключи

Асимметричные криптосистемы (с открытым ключом) не подходят для быстрой передачи потоков данных. Поэтому TLS использует внутри сессии симметричные шифры. Обычно это блочные шифры, работающие в режиме, сходном с потоковым (например, GCM). Есть несколько основных способов выработки общих секретных данных для сеансового ключа. О симметричных сеансовых ключах узлы договариваются в процессе установления соединения (Handshake). Основные методы генерации общего секрета в TLS рассмотрены выше, осталось обсудить некоторые подробности. Прежде всего: симметричных ключей используется пара — один для передаваемых сообщений, второй — для принимаемых. Серверному ключу для передаваемых сообщений (Write) соответствует клиентский ключ для принимаемых (Read), и наоборот. В TLS 1.3 используются несколько уровней ключей (для Handshake, для защиты трафика), каждый из которых включает пару значений.

Основа ключей — общий секрет Master Secret — генерируется из нескольких переменных составляющих: так называемый Premaster Secret, ClientRandom и ServerRandom. В TLS 1.2 и раньше, Premaster Secret — согласуется в рамках Handshake, это либо последовательность случайных байтов, зашифрованная открытым ключом сервера, либо значение, полученное в результате обмена по протоколу Диффи-Хеллмана. Master Secret — это массив из 48 байтов, получаемый в результате применения клиентом и сервером к только что описанным составляющим псевдослучайной функции, определённой спецификацией. Псевдослучайная функция (PRF) TLS 1.2 построена на базе хеш-функции SHA-256 (либо может быть использована более «мощная» хеш-функция, указанная в составе шифронабора), предыдущие версии используют конструкцию на базе сочетания MD5 (которая давно не считается криптографически стойкой) и SHA-1 (которую перестали считать достаточно стойкой в 2015 году). При этом способ использования MD5 и SHA-1 для генерации сеансового ключа не приводит к возникновению уязвимостей, связанных с недостаточным качеством этих функций.

RFC 5246 определяет Master Secret для TLS 1.2 следующим образом:

Master Secret — это ещё не сеансовый ключ. Дело в том, что разные шифры требуют разных ключей и дополнительных данных (например, инициализирующих векторов). Эти ключи и данные вычисляются на основе Master Secret с использованием той же псевдослучайной функции. Делается это следующим способом (TLS 1.2):

  1. для выбранного шифронабора определяется количество байтов, необходимое для получения ключа и инициализирующей информации;
  2. нужное число байтов (Key Block) получается на оcнове Master Secret, ServerRandom, ClientRandom при помощи последовательных вызовов всё той же псевдослучайной функции;
  3. полученный Key Block разбивается на подмножества, нужные для инициализации и работы шифра, а также для вычисления кода аутентификации сообщений (MAC). При этом могут различаться ключи и векторы инициализации сервера и клиента (но полный набор криптографических параметров известен обоим узлам).

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

Зашифрование полезной нагрузки осуществляется на уровне TLS-записей.

Большинство методов получения исходных данных сеансового ключа так или иначе оперируют публичным ключом сервера. На практике этот ключ использует почти 100% TLS-сессий. Публичный ключ передаётся сервером в сертификате. Помимо рассмотренных выше вариантов RSA и Диффи-Хеллмана, возможны экзотические схемы получения общего секрета:

1. PSK — pre-shared key. Схема основана на использовании общего секретного ключа и симметричной криптосистемы, при условии, что ключ был согласован заранее;

2. временный ключ RSA — исторический метод, предполагавший создание сеансового ключа RSA. Сейчас данный метод не используется, однако его поддержка послужила основой для атаки FREAK, опубликованной в 2014 году;

3. SRP — протокол SRP (Secure Remote Password), RFC 5054. Протокол, позволяющий сгенерировать общий симметричный секретный ключ достаточной стойкости на основе известного клиенту и серверу пароля, без раскрытия этого пароля через незащищённый канал;

4. Анонимный DH — анонимный вариант протокола Диффи-Хеллмана, в котором не используется подпись на серверных параметрах. Такая схема подвержена атаке типа «человек посередине», встречается крайне редко (дополнительная защита от атак может быть обеспечена при помощи сохранения отпечатка ключа);

5. DH с сертификатом — вариант DH (Диффи-Хеллмана), в котором параметры (модуль, генератор и открытый ключ сервера) определены в серверном сертификате. Этот метод является историческим, требует специального сертификата и на практике не встречается. Основное его отличие от используемых сейчас вариантов (нередко называемых также «эфемерным Диффи-Хеллманом», хотя подобного термина следует избегать) состоит в том, что серверный открытый ключ протокола Диффи-Хеллмана оказывается зафиксирован: именно он входит в сертификат и подписывается удостоверяющим центром. Это означает, что схема не обладает прогрессивной секретностью. Сервер всякий раз использует один и тот же секретный ключ Диффи-Хеллмана, а раскрытие этого ключа позволяет расшифровать ранее записанный трафик TLS.

Протокол Диффи-Хеллмана

Современный метод генерации общего сеансового секрета — это протокол Диффи-Хеллмана (DH). Использование DH, прежде всего, позволяет добиться прогрессивной секретности (Perfect Forward Secrecy, PFS), когда раскрытие серверного ключа асимметричной криптосистемы (RSA или ECDSA) не приводит автоматически к раскрытию ранее записанного трафика.

Протокол Диффи-Хеллмана — важнейший элемент современных реализаций TLS, также этот протокол имеет огромное значение для множества других защищённых протоколов Интернета, и для прикладной криптографии в целом. Протокол не является шифром или алгоритмом электронной подписи. На его основе можно построить и асимметричную криптосистему, и схему электронной подписи, но в TLS он используется с другой целью: этот протокол позволяет участникам обмена информацией договориться об общем секретном ключе через открытый канал связи. Задача Диффи-Хеллмана, лежащая в основе классической версии протокола, прямо связана с алгебраической задачей дискретного логарифмирования в конечной группе ― на вычислительной сложности этой задачи и построена защита протокола от перехвата секретного ключа.

Основная идея протокола DH может быть сформулирована достаточно просто. Две стороны, желающие получить общий секрет, очевидно, могут сгенерировать собственные, локальные, секреты, например, то или иное число. Предположим, что у нас есть некоторая однонаправленная функция — то есть, можно легко вычислить значение функции для заданного аргумента, но обратить вычисления и узнать аргумент по значению — сложно. Тогда можно было бы устроить алгоритм таким образом, чтобы договаривающиеся об общем секрете стороны передавали по открытому каналу друг другу значения функции от секретных аргументов, проводили над этими значениями и аргументами собственные вычисления и, в результате применения некоторых преобразований, могли бы каждая прийти к одному и тому же значению. Просматривающая коммуникации третья сторона же видела бы только значения однонаправленной функции, без возможности обратить её и узнать секрет. Успешная реализация такого протокола и есть схема Диффи-Хеллмана.

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

Вернёмся к использованию DH в TLS. Сейчас (2020 год) распространены два варианта протокола. В классическом случае, DH работает на “обычной” конечной группе, задаваемой простым числом P, которое называется модулем. «Обычная» — довольно условное определение: имеется в виду, что классический DH работает в арифметике остатков, где числа берутся по модулю некоторого достаточно большого простого числа. Такие операции более привычны, чем второй вариант DH, который использует группу точек эллиптической кривой. (Под «группой» понимается алгебраическая структура — множество с бинарной операцией, подчиняющейся некоторому набору аксиом. Конечная группа — это группа с конечным числом элементов.)

Рассмотрим подробнее классический вариант DH. Здесь группа, в которой будут проводиться операции вычисления общего секрета TLS, задаётся единственным числом – модулем. Это обязательно большое простое число. Большое — означает, что разрядность его записи превышает 1000 бит, а современная рекомендация для классического варианта — не менее 2048 бит. В TLS 1.2 сервер передаёт это число (значение модуля) в составе сообщения ServerKeyExchange, если используется классический алгоритм DH. Модуль полностью определяет группу, поэтому каких-то дополнительных параметров передавать не нужно. На практике веб-серверы используют ту или иную типовую группу (заданную типовым модулем). Модуль не является секретным — он передаётся в открытом виде. Таким образом, известны группы, используемые большинством веб-серверов, поддерживающих DH. Вообще говоря, уникальные группы DH рекомендуется генерировать при начальной настройке TLS, это несложно сделать стандартными утилитами. Тем не менее, не так давно наиболее распространённая типовая группа имела разрядность в 1024-бита, что не слишком много. Вместе с задающим группу модулем, сервер передаёт другой открытый параметр — генератор (см. ниже), — а также свою часть обмена Диффи-Хеллмана — открытый ключ (принцип его вычисления рассмотрен ниже).

Второй вариант протокола Диффи-Хеллмана — «эллиптический», он основан на свойствах эллиптических кривых. (Элементарный обзор некоторых основ практического математического аппарата, который стоит за криптографией на эллиптических кривых, дан в «Приложении А». Базовые операции эллиптического DH мы рассмотрим чуть раньше.) Математические операции протокола DH в обоих случаях эквивалентны, отличие кроется в используемых группах: «эллиптический» вариант работает на группе точек эллиптической кривой. Такая группа может быть построена при помощи заданной на кривой операции, называемой сложением точек. Следует понимать, что здесь важно не название, а свойства операции, с таким же успехом её можно было назвать умножением точек. Собственно, различают два эквивалентных подхода к обозначению групповых операций: мультипликативный (умножение) и аддитивный (сложение). Обычно, применительно к TLS (и прикладной криптографии), в случае классического протокола DH — используют мультипликативный вариант и говорят об умножении и возведении в степень (экспонента); в случае «эллиптического» — аддитивный, и говорят о сложении точек и нахождении кратного (умножение на скаляр). Это чисто терминологическое отличие, никак не связанное со стойкостью и другими особенностями протокола.

Итак, операция сложения точек ставит в соответствие двум точкам кривой — третью, называемую их суммой. На этой операции строится алгоритм удвоения точки и умножения на скаляр (целое положительное число, не являющееся, соответственно, точкой на кривой). Также вводится нейтральный элемент — в его роли выступает бесконечно удалённая точка. Эллиптическая кривая, в общем смысле, обладает непрерывностью, но в случае с протоколом Диффи-Хеллмана она рассматривается только в «целых» точках, множество которых задано определённым образом. Прикладная особенность группы точек эллиптической кривой состоит в том, что решение задачи дискретного логарифмирования (обратной задачи для основы протокола DH) здесь сложнее, чем в «обычной» группе, это позволяет использовать ключи меньшей разрядности. Впрочем, для понимания математического принципа протокола Диффи-Хеллмана детали работы с эллиптическими кривыми не требуются.

Протокол DH на «обычной» группе работает следующим образом. Для того чтобы получить общий секретный ключ, стороны сначала выбирают общие параметры Диффи-Хеллмана ― это модуль, задающий группу (простое число), а также некоторый элемент этой группы, называемый генератором — соответственно: P и G (то есть, два целых числа). Параметры DH открыты и считаются известными третьей стороне. На следующем шаге каждая из сторон выбирает собственное секретное целое число a (и, соответственно, b) и вычисляет значение A = G a mod P (соответственно, B = G b mod P). То есть, все операции проводятся по модулю P («взятие остатка»), что, собственно, и отображает их результаты в элементы группы. Далее стороны обмениваются по открытому каналу значениями A, B и вычисляют A b mod P и B a mod P, соответственно. Полученные значения равны, так как, из свойства степеней, A b = (G a ) b = B a = (G b ) a = G ab . Таким образом, стороны получили общий секретный ключ G ab .

Если вернуться к описанной выше основной идее протокола, то операция возведения в степень (по модулю) выступает в роли однонаправленной функции, значения которой передаются по открытому каналу. Свойство групповой операции (в данном случае, эквивалентное более привычному свойству степеней), позволяет сторонам, осуществляющим обмен значениями, прийти к одинаковому результату (G ab ). В случае TLS, сервер передаёт в сторону клиента параметры Диффи-Хеллмана и свой открытый ключ (A), удостоверяя эти значения собственной электронной подписью (либо RSA, либо ECDSA). Подпись вычисляется от ключа, открытая часть которого указана в сертификате сервера. Прослушивающая канал сторона знает значения P, G, A и B. Но для того, чтобы определить значение секретного ключа, необходимо вычислить a или b, решив относительно x уравнение вида A = G x mod P. Стоящая за решением этого уравнения классическая задача и называется задачей дискретного логарифмирования в конечной группе. В общем случае, эта задача вычислительно сложна для групп достаточно большой разрядности (1024 бита и выше, для «классического» протокола DH), поэтому возведение в степень оказывается однонаправленным.

Фундаментальная причина сложности данной операции сходна с общими проблемами деления (или вычитания, тут всё зависит от используемой терминологии) в группах: грубо говоря, деление представляет собой операцию поиска среди элементов группы такого, который при умножении на известный делитель давал бы делимое (поиск обратного элемента). Ситуация эквивалентна привычному делению из курса начальной школы: чтобы разделить 15 на 3 нужно найти такое число, которое при умножении на 3 давало бы 15. Если известны некоторые свойства группы, позволяющие построить её арифметическую структуру; или группу удаётся рассмотреть в составе «большей» структуры (некоторого кольца), то операцию деления можно оптимизировать, используя тот или иной «быстрый» пошаговый алгоритм, отбрасывающий из перебора заведомо неподходящие элементы. Хорошо известным примером такой оптимизации является школьное «деление столбиком». Именно поэтому в случае с современными вариантами DH работает квантовый алгоритм Шора, использующий квантовое представление структуры группы (кольца, если говорить строго), измерение которого даёт результат, позволяющий уже классическим методом очень быстро выполнить дискретное логарифмирование.

Практическая применимость протокола Диффи-Хеллмана основывается на том, что знание секретного значения позволяет быстро вычислить нужную экспоненту. Действительно, предположим, что требуется вычислить A = G m . На первый взгляд, для этого необходимо умножить G на себя m-1 раз: G*G*. *G. Казалось бы, атакующая сторона тут оказывается в таком же положении, как и стороны, использующие протокол: атакующий может начать умножать G (это открытый параметр) и продолжать вычисления до тех пор, пока не получит искомое значение A (которое перехватил). Таким образом можно определить значение m. Однако реальная ситуация отличается. Дело в том, что зная секретный параметр m, вычислить G можно гораздо быстрее. Простейший пример: предположим, что нам нужно вычислить G 5 , показатель 5 заранее известен. G 5 = G*G*G*G*G. Это четыре операции умножения, но c другой стороны, значение G 2 можно записать, и использовать несколько раз. Получаем: G 2 *G 2 *G, а это уже только три умножения (учитывая G*G). То есть, зная значение показателя, можно применить быстрые алгоритмы (Монтгомери и др.) и получить огромный выигрыш в числе операций, по сравнению с атакующим, который должен проверить все показатели.


Для протокола DH, работающего на эллиптической кривой, вместо модуля P задаётся сама кривая (с дополнительными параметрами); вместо возведения в степень — используется умножение на скаляр (то есть, вычисляется кратное для точки: если мы умножаем точку A на значение 5, это означает, что на кривой вычисляется точка 5A = A+A+A+A+A). В TLS используются именованные кривые, параметры которых заранее известны сторонам. Генератором, в эллиптическом случае, является точка кривой. Однако логика протокола от этих особенностей не зависит. Операции DH на эллиптической кривой просто будут записаны в аддитивной форме: Ab = (Ga)b = Ba = (Gb)a = Gab. Обратите внимание на скобки в предыдущем выражении: они указывают на «ассоциативность», обобщение которой и позволяет перенести схему Диффи-Хеллмана на другие математические объекты, если для них такая «ассоциативность» выполняется. Конечно, должен работать и описанный в предыдущем абзаце механизм ускорения вычислений при известном секрете. Для группы точек эллиптической кривой он работает, сводя основную часть вычислений к некоторому количеству удвоений точки.

Итак, практическая полезность DH строится на сложности задачи дискретного логарифмирования в конечной группе. Известно, что при наличии больших, но вполне доступных, вычислительных мощностей (не квантовых), для 1024-битной «классической» (не «эллиптической») группы можно уже сейчас предвычислить арифметическую структуру, потратив пару лет работы суперкомпьютера и сохранив результаты в специальных таблицах. После этого вычислять дискретный логарифм в конкретной группе можно достаточно быстро (за часы, а возможно, просто на лету), особенно, если вы используете специализированную многопроцессорную систему. Это означает, что можно расшифровать записанный ранее трафик TLS-сессий (а также других протоколов, использующих DH). Дело в том, что сеансовый ключ, если вы умеете отыскивать дискретный логарифм, элементарно вычисляется из ключа DH, который передаётся в открытом виде. Предвычислить нужную структуру можно только для заранее известной группы, поэтому для атакующего важно, чтобы TLS-серверы использовали типовые параметры. При этом, для тех, у кого ресурсов мало (кто не является специализированным агентством, например), группа остаётся вполне стойкой. (Для групп точек эллиптической кривой подобных алгоритмов быстрого дискретного логарифмирования на настоящий момент в открытой печати не опубликовано. С фундаментальной точки зрения это, скорее всего, обусловлено тем, что для произвольных эллиптических кривых не удаётся найти некоторых аналогов простых чисел, которые помогли бы доступным, в плане вычислений, способом вложить группу кривой в другое множество с дополнительной структурой, где значение логарифма отыскать проще. Необходимо отметить, что это верно не для всякой эллиптической кривой и не для всяких параметров: в целом ряде случаев такое вложение можно вычислить на практике.)

Разновидность DH на группе точек эллиптической кривой называется ECDH. Это рекомендуемый сейчас вариант алгоритма, он получает всё большее распространение в современных реализациях TLS. Так как отыскание дискретного логарифма в группе точек эллиптической кривой вычислительно сложнее, можно использовать ключи с меньшей разрядностью. Высокую секретность, согласно современным представлениям, обеспечивает группа эллиптической кривой с разрядностью 192 и более бит. Также алгоритм позволяет безопасно использовать общую кривую, а не генерировать новую для каждого сервера. По крайней мере, современная ситуация такова, что рекомендовано использовать хорошо известные кривые из утверждённого списка (в TLS 1.2, 1.1 возможно использование собственных параметров, они будут передаваться в сообщениях Handshake; в TLS 1.3 — набор зафиксирован спецификацией). Распространённый случай – кривая secp256r1, предлагающая разрядность 256 бит. Если группу классического DH в TLS легко поменять – модуль и генератор непосредственно передаются в сообщении сервера и могут быть любыми, – то для типовых эллиптических кривых всё сильно сложнее: все параметры здесь фиксированы заранее, клиент и сервер могут договориться только выборе кривой из ограниченного списка.

В TLS версий до 1.3 параметры DH всегда задавал сервер. Эти параметры, как сказано выше, подписываются серверным ключом, что необходимо для того, чтобы параметры не могли быть заменены в момент передачи. Хотя сообщение Finished защищает весь обмен Handshake, активный атакующий мог бы подменить параметры DH на свои собственные, перехватив соединение и, в дальнейшем, сгенерировав для клиента и сервера разные, но корректные сообщения Finished — протокол DH сам по себе не защищён от атаки типа человек посередине (схема, сходная с только что описанной, применяется в атаке Logjam). Поэтому подпись на данных параметрах крайне важна. В зависимости от типа сертификата, в качестве криптосистемы подписи может использоваться либо ECDSA (современный вариант), либо RSA, а устаревший алгоритм DSA сейчас не встречается. В TLS 1.3 протокол DH используется уже в начальной фазе установления соединения, поэтому параметры подписываются в составе прочих сообщений, а подпись передаётся сервером в сообщении CertificateVerify. Другое важное отличие 1.3 в том, что здесь параметры DH согласуются узлами, причём, инициатива принадлежит клиенту: он передаёт список поддерживаемых групп (а это и эллиптические, и «мультипликативные», классические варианты) в расширении ClientHello, так же, в другом расширении, передаются и открытые ключи клиента. Сервер выбирает подходящие параметры.

Широко используются аббревиатуры ECDHE и DHE, то есть, варианты записи, оканчивающиеся буквой E. Эта буква обозначает то, что протокол DH используется для выработки временного сеансового ключа, от английского ephemeral («эфемерный»). То есть, E — подчёркивает то, что ключ не является постоянным (однако, как уже отмечено выше, не следует использовать для обозначения этого свойства прямой русский перевод — «эфемерный»: в русскоязычном варианте ключ называется «временным» или «сеансовым»). Почему потребовалось отдельно выделять «временные ключи»? Причина в том, что в TLS определены варианты соединений, использующих постоянный серверный открытый ключ DH, заданный в сертификате. Сейчас такие схемы на практике не встречаются, поэтому ключ, полученный в результате обмена сообщениями DH, всегда будет временным. Это, однако, не означает, что данный ключ каким-либо образом автоматически исчезает после закрытия соединения: во-первых, ключ может не удаляться из памяти сервера или направляться в долговременное хранилище, по тем или иным причинам; во-вторых, ключ можно восстановить из записи трафика, при условии, что третьей стороне известен (или она может вычислить) соответствующий секретный параметр Диффи-Хеллмана. Кроме того, ничто не препятствует серверу просто не обновлять «временный» ключ, каждый раз используя одно и то же значение при установлении соединения — то есть, сделав ключ статическим.

Пример серверного сообщения ServerKeyExchange, содержащего параметры DH (в «классическом» варианте) и подпись на этих параметрах. (Вариант на эллиптической кривой рассматривался в анализе дампа трафика выше.)

TLS 1.3: первоначальное соединение (Handshake)

В TLS 1.3 от предыдущих версий унаследованы только базовые принципы установления соединения: сохранились роли узлов (соединение инициирует клиент), не изменилась последовательность ClientHello — ServerHello, присутствует сообщение-сигнал Finished. Однако на этом сходство заканчивается. В TLS 1.3 сокращено и общее число сообщений Handshake, и число сообщений, передаваемых в открытом виде: узлы практически сразу переходят на зашифрованный обмен. Поэтому из схемы установления соединения удалён сигнал ChangeCipherSpec — он больше не требуется (как ни странно, cам «сигнал» при этом остался и может передаваться узлами, см. ниже). Изменилась роль сообщения CertificateVerify — при передаче со стороны сервера оно удостоверяет сообщения первой части Handshake.

Схема полного Handshake TLS 1.3 выглядит следующим образом:

Здесь символом ‘*’ отмечены необязательные сообщения (передаются в зависимости от контекста), а в фигурных скобках даны сообщения Handshake, которые передаются в зашифрованном виде. Квадратные скобки обозначают данные полезной нагрузки, которые также передаются в зашифрованном виде, но с использованием другого набора ключей шифрования. Обратите внимание: уже первый ответ сервера — содержит зашифрованные данные. В TLS предыдущих версий — практически все существенные Handshake-сообщения передаются в открытом виде.

В протоколе установления соединения TLS 1.3 выделяются три фазы: выработка начального значения общего криптографического секрета (ключей), определение параметров соединения, аутентификация (сервера и клиента).

К первой фазе относятся ClientHello и ServerHello (а также их расширения, обозначенные на схеме символом ‘+’). Результатом обмена сообщениями в первой фазе является получение первого секрета (в терминах спецификации исходный секрет называется handshake_traffic_secret). На основе этого секрета, используя также сами сообщения, переданные к этому моменту, стороны получают первый набор симметричных ключей. Эти ключи используются для зашифрования сообщений Handshake, начиная с серверного EncryptedExtensions. Например, серверный сертификат в TLS 1.3 передаётся в зашифрованном виде. Это означает, что сторона, прослушивающая канал связи, но не имеющая ключей, не сможет определить, что за сертификат был предоставлен сервером (и был ли он предоставлен вообще — истинная длина сообщений может быть скрыта при помощи дополнения их нулевыми байтами, это также определено спецификацией 1.3). Первая фаза завершается передачей ServerHello и обязательных расширений.

Вторая фаза включает серверные сообщения EncryptedExtensions и, при необходимости аутентификации клиента, CertificateRequest. Новое сообщение — EncryptedExtensions — добавлено в TLS 1.3.

В третьей фазе, представленной группами сообщений обоих узлов Certificate, CertificateVerify и Finished, происходит аутентификация сервера и клиента. Как и в предыдущих версиях TLS, аутентификация может быть полностью исключена (анонимный режим), однако типичный сценарий использования подразумевает аутентификацию, по крайней мере, сервера клиентом. При этом, в TLS 1.3 сервер может перейти к отправке данных полезной нагрузки (Application Data на схеме) непосредственно после серверного Finished — это возможно потому, что к этому моменту сервером уже получен первый набор симметричных ключей.

В TLS 1.3 появился новый механизм опознавания используемой версии протокола. Поля, содержавшие номер версии в предыдущих версиях, сохранены в статусе «исторических», их значения зафиксированы. Версия же 1.3 (её номер: 0x0304) передаётся в специальном расширении сообщений ClientHello/ServerHello. Данное расширение называется supported_versions, а его наличие является одним из признаков того, что клиент (или сервер) будут использовать версию TLS 1.3. Со стороны клиента, в ClientHello, supported_versions содержит список версий протокола, которые готов поддерживать клиент. Сервер передаёт в этом расширении номер выбранной версии. Как описано выше, экспериментальные реализации TLS 1.3 при указании версии использовали специальный префикс 0x7F в supported_versions, это касается и сервера, и клиента.

Сравним новую схему с TLS 1.2. Кроме уже упомянутого выше отсутствия сигнала ChangeCipherSpec, отсутствуют сообщения ClientKeyExchange и ServerKeyExchange, а также сообщение ServerHelloDone. При этом параметры, необходимые для построения криптографического контекста, из ClientKeyExchange и ServerKeyExchange перекочевали в расширения ClientHello и ServerHello: это key_share, supported_groups, а также signature_algorithms, psk_key_exchange_modes и pre_shared_key. В типичной ситуации, непосредственно для выработки криптографического контекста используются расширения supported_groups и key_share: первое содержит идентификаторы групп, используемых для протокола Диффи-Хеллмана; второе — открытый ключ или несколько открытых ключей (взятых в группах, перечисленных в supported_groups). Так как установление соединения TLS 1.3 проводится в защищённом режиме, расширения, содержащие криптографические параметры, необходимы. Более того, их наличие (вместе с supported_versions) — является необходимым признаком TLS 1.3. Криптографические операции TLS 1.3 рассмотрим подробно ниже, в специальном разделе.

Сообщение-сигнал ServerHelloDone (оно в предыдущих версиях имело нулевую длину и обозначало окончание первой партии серверных сообщений Handshake) заменено на серверное Finished.

Даже полный формат Handshake в 1.3 оказывается короче на одну итерацию: если взглянуть на предыдущую версию, то там, после получения ответа сервера (заканчивающегося ServerHelloDone), клиент должен был отправить свою порцию сообщений, завершающуюся Finished, и дождаться ответного серверного Finished, только после этого переходить к передаче полезной нагрузки. В новой версии — серверное сообщение Finished приходит в первом же ответе сервера, соответственно, клиент может сразу переходить к отправке полезной нагрузки (после своего Finished, конечно), не дожидаясь ещё одного пакета от сервера. Это экономит время, необходимое для доставки пакетов от клиента к серверу (и, вообще говоря, обратно). Такая же схема была предложена (и реализована) раньше под названием TLS False Start (RFC 7918), в версии 1.3 она, в доработанном виде, вошла в спецификацию самого протокола TLS. Для сервисов, устанавливающих тысячи TLS-соединений в секунду, уменьшение задержки в каждом сеансе на 30-100 мс, соответствующих времени передачи данных, очень существенно. Такая экономия ресурсов ускоряет работу сервиса для всех клиентов, а не только для поддерживающих TLS 1.3.

ClientHello 1.3

Среди нововведений версии 1.3 — запрет «пересогласования» соединения (renegotiation). Клиент больше не может отправить сообщение ClientHello внутри открытой TLS-сессии — это приведёт к прекращению сессии, так как является нарушением спецификации. Соответственно, отправка ClientHello возможна только при инициировании новой сессии. Зато на стороне сервера появилось сообщение HelloRetryRequest, которое может быть отправлено в сторону клиента, и означает предложение повторного согласования сессии. При помощи HelloRetryRequest сервер может «мягко» сбрасывать несоответствующие требованиям запросы клиентов, ожидая, что в ответ клиент передаст скорректированное сообщение ClientHello.

Это новая для TLS концепция. В частности, HelloRetryRequest позволяет бороться с некоторыми видами активных атак при помощи сookie-сигнала, так как отправка cookie позволяет проверить, что клиент действительно отвечает по адресу, указанному в качестве адреса-источника запроса. Cookie в TLS 1.3 передаются в составе расширения HelloRetryRequest и имеют логическое сходство с известными куки-файлами в HTTP (или с менее известными cookie-сигналами из расширений TCP, где они используются для борьбы с SYN-флудом и другими видами флуда). Cookie представляет собой некоторый идентификатор (тикет), который сервер передаёт клиенту для того, чтобы клиент в следующем сообщении вернул данный тикет. Спецификация 1.3 предписывает использование конкретного cookie только в рамках одного TLS-соединения.

Схема согласования криптографического контекста в 1.3 делает шифронаборы, указываемые в ClientHello, несовместимыми с предыдущими версиями TLS. Однако клиент, готовый поддерживать предыдущие версии, может передавать в ClientHello и «новые», и «старые» варианты — формат идентификатора сохранился, это двухбайтовое значение. Понятно, что для установления соединения версии 1.3 — потребуется хотя бы один совместимый шифронабор.

Текущий список шифронаборов (июль 2020) невелик: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, TLS_AES_128_CCM_8_SHA256. Здесь есть режим GCM, который широко используется с AES сейчас. Есть режим CCM (Counter with CBC-MAC) — это режим счётчика (как и GCM), в котором аутентификация построена на коде CBC-MAC (разновидность кода аутентификации, по схеме построения совпадающая с режимом шифрования CBC). А также потоковый шифр ChaСha20, со схемой аутентификации Poly1305 (этот комплект криптопримитивов достаточно широко используется Google, например, он поддерживается браузером Chrome). Все упомянутые криптопримитивы уже используются в TLS на практике.

TLS 1.3 разрешает исключительно аутентифицированное шифрование, которое не требует использования дополнительной хеш-функции для вычисления кода аутентификации сообщения (в схемах аутентифицированного шифрования некоторый аналог хеш-функции встроен в саму схему). Тем не менее, хеш-функция требуется для вычисления сессионных симметричных ключей. Поэтому в шифронабор TLS 1.3 входит указание на тип хеш-функции: как видно из приведённого в предыдущем абзаце списка, это SHA-256 и SHA-384.

Таким образом, если устанавливается TLS-соединение без использования криптосистем подписи в целях аутентификации, то указание на такие криптосистемы вовсе не передаётся узлами. Соответственно, оказывается невозможным использование сертификатов для аутентификации узлов (в первую очередь, сервера). Если сертификаты используются, то необходимо указание совместимой с ними криптосистемы.

Перечень поддерживаемых криптосистем электронной подписи передаётся в обособленном расширении ClientHello — SignatureAlgorithms. Аналогичное по назначению расширение уже было введено в спецификации TLS 1.2, однако в TLS 1.2 объявляемые в составе ClientHello шифронаборы тоже содержат указание на криптосистему электронной подписи, то есть, присутствует некоторое дублирование. В 1.3 также введено ещё одно расширение, уточняющее перечень схем подписи по отношению к сертификатам — это расширение SignatureAlgorithmsCerts, определяющее криптосистемы подписей в сертификатах. (Возможно использование только единственного расширения SignatureAlgorithms, которое является обязательным.)

Спецификация указывает несколько криптосистем: два варианта подписей, базирующихся на задаче RSA, широко распространённую ECDSA и новую криптосистему EdDSA, которая тоже работает на эллиптической кривой. RFC для последней опубликован в начале 2020 года. EdDSA — довольно прогрессивная криптосистема, построенная на задаче дискретного логарифмирования (схема подписи Шнорра, математически сходная с ECDSA) и работающая на эллиптических кривых в форме Эдвардса (откуда название). Кривые Эдвардса, при некоторых дополнительных условиях, оказываются очень эффективны при использовании в составе криптосистем электронной подписи. (Кривые Эдвардса также рекомендованы к использованию в российском стандарте электронной подписи ГОСТ Р 34.10-2012.)

Рассмотрим пример ClientHello TLS 1.3. Это сообщение браузера Chrome версии 68:

Итак, сервер может определить, что данное ClientHello является сообщением версии 1.3 по наличию необходимого расширения SupportedVersions. С другой стороны, сообщение выглядит как ClientHello предыдущей версии, TLS 1.2, с тем отличием, что содержит расширения, неизвестные для сервера, поддерживающего старую версию. Неизвестные расширения допускаются в TLS: клиент и сервер должны их игнорировать. Тем не менее, не следует делать вывод, что процедуры установления соединения (Handshake) в TLS 1.3 и TLS 1.2 совместимы — это не так. Формат ClientHello позволяет клиенту сразу же провести контролируемое понижение версии и выполнить установление соединения по схеме TLS 1.2, но если сервер поддерживает версию 1.3, то уже следующий шаг протокола будет радикально отличаться от 1.2 — и по составу сообщений, и по их структуре, а главное отличие состоит в моменте перехода на защищённый обмен данными.

Расширения ClientHello/ServerHello в TLS 1.3. Некоторые расширения, введённые в предыдущих версиях, сохранились и в 1.3, фактически, с теми же ролями. Как уже отмечено в пояснениях к примеру ClientHello, есть три важнейших расширения, которые и превращают сессию в сессию версии 1.3: SupportedVersions, SupportedGroups, KeyShare. Первое определяет версию протокола, второе и третье — необходимы для согласования криптографического контекста. Рассмотрим ряд других расширений (версии 1.3) подробнее.

PSKKeyExchangeModes и PreSharedKey. Эти расширения предназначены для создания сессий, использующих ранее распределённые между узлами (секретные) ключи. Определяют, соответственно, поддерживаемые режимы («прямой» режим, или режим с дополнительным использованием протокола DH) и идентификатор ключа. Очевидно, что секретный ключ не может передаваться в открытом виде, поэтому расширение PreSharedKey содержит только данные, позволяющие другой стороне найти нужный ключ у себя. Кроме того, PreSharedKey определяет срок действия ключа и ряд других параметров (криптосистему и пр.).

EarlyData. TLS 1.3 позволяет узлам возобновить соединение по максимально быстрой схеме, когда полезные данные передаются клиентом в первой же итерации. Например, клиент может сразу отправить HTTP-запрос GET. Сигналом, что клиент действует именно таким способом, служит наличие расширений EarlyData и PreSharedKey. Второе нужно для того, чтобы сервер мог выбрать ранее согласованный сторонами секрет и сгенерировать ключ, необходимый для расшифрования поступившего от клиента запроса — полезные данные всегда передаются в защищённом виде, то есть, внутри записей Application Data.

Cookie. Данное расширение, во-первых, позволяет серверу запросить у клиента подтверждение намерения установить соединение; во-вторых — позволяет оптимизировать управление сессиями на стороне сервера. Cookie может передаваться сервером вместе с HelloRetryRequest и содержит некоторую последовательность байтов, которую должен повторить клиент в своём следующем сообщении ClientHello (тоже в составе расширения Cookie). То есть, роль данного сообщения сходна со многими другими применениями различных «куки». Так, с его помощью сервер может существенно снизить затраты на обслуживание «зависших» сессий, тем самым избежав ситуации отказа, в случае одновременного открытия многих сессий злонамеренными узлами. В целом, так как TLS является протоколом уровня приложений и находится выше транспортного уровня, защита с помощью Cookie может оказаться не слишком эффективной. Например, в случае с TCP, если запросы от «завешивающих» сессию узлов доходят до TLS-сервера, это может означать, что где-то на более низких уровнях борьбы с атакой допущена ошибка. TCP-сессия существует независимо от TLS, поэтому, даже если серверу не требуется «держать» открытым состояние TLS-сессии, это не означает автоматически, что будет закрыта сессия TCP. Тем более, что занять сессию TCP — атакующий мог ещё до того, как были переданы какие-либо данные уровня приложений. Тем не менее, ключевым отличием здесь является то, что объёмы вычислительных ресурсов, необходимых для обслуживания открытия TCP-сессии и TLS-сессии — несравнимы: TLS требует в тысячи раз больше (понятно, что TCP придётся обслуживать так или иначе). Соответственно, Cookie особенно полезны, когда используется безсессионый транспорт (например, UDP), так как в этом случае на транспортном уровне отсечь атаки с массовым открытием TLS-сессий невозможно (за отсутствием понятия сессии).

Кроме перечисленных выше расширений, в TLS 1.3 есть ряд других. Например, расширение CertificateAuthorities позволяет информировать другой узел о списке поддерживаемых доверенных удостоверяющих центров. Предусмотрено специальное расширение-сигнал для сервера о том, что клиент поддерживает аутентификацию клиента, а также ряд других расширений, которые мы не рассматриваем.

ServerHello 1.3

ServerHello — ответное сообщение сервера. На ClientHello сервер может ответить либо ServerHello, либо HelloRetryRequest. ServerHello в TLS 1.3 решает те же задачи, что и в версии 1.2, однако способ решения отличается. При помощи этого сообщения сервер выбирает шифронабор из предложенных клиентом, передаёт данные, необходимые для построения общего криптографического контекста. Так как в новой версии шифрование включается практически сразу, ServerHello обязательно содержит (в составе передаваемых расширений) параметры, позволяющие узлам незамедлительно получить общий секрет, который послужит прообразом симметричного ключа шифрования. Сервер вычисляет общий секрет сразу же, так как уже следующие за ServerHello сообщения должны передаваться в зашифрованном виде. Это важное, и весьма существенное, отличие от предыдущих версий TLS.

Как уже описано выше, в TLS 1.3 используются симметричные ключи нескольких уровней (или «этапов»). Ключи, применяемые для защиты сообщений Handshake, отличаются от ключей, используемых для защиты, собственно, трафика. Однако ключи следующих этапов — связаны с ключами этапов предыдущих. Вычисление каждого поколения использует дополнительные данные, поэтому только по секретным ключам Handshake восстановить ключи защиты трафика вычислительно сложно. Для определения общего секрета используется протокол Диффи-Хеллмана, клиентские параметры которого сервер уже получил в ClientHello. Источником дополнительных входных значений служат также сообщения Handshake, полученные и подготовленные к передаче сервером. Серверные параметры DH — передаются в составе ServerHello: в этом состоит ещё одно архитектурное отличие от предыдущих версий, в которых серверные DH-параметры передавались в специальном сообщении ServerKeyExchange (см. выше). Перенос параметров внутрь ServerHello, конечно, обусловлен тем, что использование протокола Диффи-Хеллмана стало обязательным.

С параметрами DH связан следующий момент: клиент может указать несколько вариантов поддерживаемых групп, но сами параметры передать не для всех из них. То есть, в терминах ClientHello, расширение SupportedGroups содержит больший перечень групп, чем перечень параметров в KeyShare. Это обычная ситуация в случае браузеров: как можно видеть в примере ClientHello Chrome выше — данный браузер передаёт только один (рабочий) параметр в KeyShare, это X25519, при этом список поддерживаемых групп SupportedGroups включает три элемента. Если сервер смог найти среди поддерживаемых групп те, которые совместимы с серверными настройками, но для этих групп клиент не передал параметров DH, то сервер может ответить вместо ServerHello сообщением HelloRetryRequest. Предполагается, что клиент, в таком случае, ответит новым ClientHello, передав параметры в нужной серверу группе. (Подобное использование HelloRetryRequest относится и к другим случаям, когда параметров в совместимом ClientHello серверу недостаточно для установления соединения.)

Основной особенностью сообщения HelloRetryRequest является то, что это сообщение по структуре полностью повторяет ServerHello, имеет такой же код типа. Отличить два сообщения клиент может только по значению поля Random. Это довольно интересная особенность TLS — использование значения Random в качестве сигнала. Есть и другая особенность: при наличии HelloRetryRequest — сервером используется другой механизм вычисления хеш-функции от переданных и принятых в рамках установления сессии сообщений. Схема отличается в одной детали, которая позволяет серверу «выгрузить» сохранение состояния на сторону клиента, при помощи расширения Cookie (которое, в данном случае, разрешается). Несомненно, это ещё один пример из ряда «неочевидных» решений, используемых в TLS, тем не менее, его внедрение обусловлено заботой об оптимизации производительности протокола.

Рассмотрим пример сообщения HelloRetryRequest (а на следующем шаге — ServerHello TLS 1.3). Это сообщение, полученное от одного из серверов facebook.com; соответствующее ClientHello не содержало ни одного подходящего для сервера значения в списке ключей ClientKeyShare (заголовок TLS-записи не приводится):

Итак, HelloRetryRequest повторяет структуру ServerHello, но последнее, тем не менее, отличается по интерпретации клиентом. Перейдём к ServerHello TLS 1.3. Здесь приводится ServerHello, полученное от сервера Google, обслуживающего веб-сервис под доменом gmail.com. Соответствующее ClientHello содержало ключи для всех трёх «эллиптических вариантов» DH, сервером выбрана группа X25519. Разбор сообщения (заголовок TLS-записи не приводится):

Попробуем поместить ServerHello версии 1.3 и ServerHello предыдущих версий в единый логический контекст, чтобы выявить основные различия. Сразу же можно заметить, что в версии 1.3 клиент предлагает серверу возможные параметры DH. В предыдущих версиях — инициатива была за сервером, клиент мог только ответить сообщением ClientKeyExchange. Благодаря изменению ролей, узлы уже после передачи ServerHello получают общий секрет. Надо отметить, что в TLS 1.3 клиент также может переложить задачу выбора параметров алгоритма Диффи-Хеллмана на сервер, для этого служит описанный выше механизм HelloRetryRequest: клиент просто передаёт пустой список групп, а в ответ получает рекомендацию сервера. Естественно, это обходится в дополнительную итерацию. Передача случайных значений Random, списков шифронаборов — тут сохраняется логика предыдущих версий. В предыдущих версиях также присутствовали и расширения, однако в 1.3 роль их стала значительно важнее, хотя бы потому, что именно наличие определённых расширений (SupportedVersions и др.) делает ServerHello сообщением версии 1.3.

Защищённые сообщения Handshake в TLS 1.3

ServerHello, при штатном ходе установления соединения, является единственным сообщением сервера, которое передаётся в открытом виде. Уже следующее сообщение — EncryptedExtensions — зашифровано. Зашифрованные сообщения в TLS 1.3 передаются строго внутри TLS-записей с типом Application Data (0x17). Это ещё одно важное отличие от предыдущих версий. Мы подробно рассмотрим формат защищённых записей ниже, в специальном подразделе, а сейчас отметим только один момент: «настоящий» тип записи — Handshake (0x16) — передаётся внутри защищённой записи, и доступен только после того, как эта запись успешно расшифрована.

Используя общий секрет, полученный в рамках обмена Диффи-Хеллмана, а также все переданные к настоящему моменту сообщения, узлы определяют текущие симметричные ключи. Предположим, что сервер выбрал шифронабор TLS_AES_128_GCM_SHA256 (0x1301). Тогда, для успешной защиты сообщений, потребуется пара симметричных ключей: будем обозначать их как sh_write, sh_read (от Server Handshake Write/Read). Длина этих ключей — 128 бит, соответствует разрядности ключей шифра. Обозначения write и read нужны потому, что один ключ используется для записи сообщений в канал, то есть, для отправки их в сторону клиента, а второй — для чтения. На стороне клиента — ключи меняются местами. Схема полностью аналогична описанной выше. Кроме ключей, узлы должны определить векторы инициализации шифров, это начальные значения, необходимые для работы шифра в режиме аутентифицированного шифрования.

Сам алгоритм вычисления ключей и векторов инициализации в TLS 1.3 отличается от предыдущих версий. Для получения нужной «порции битов» используется функция, которая в спецификации называется HKDF-Expand-Label: Функция возвращает нужное количество битов ключа или вектора инициализации — длины их, соответственно, передаются в key_length и iv_length. Рассмотрим другие аргументы: Функция HKDF-Expand-Label устроена несколько сложнее, чем может показаться: внутри скрываются другие функции, которые ставят генерируемую информацию в соответствие с текущим контекстом. То есть, симметричные ключи в TLS 1.3 зависят от множества факторов.

Вернёмся к процессу установления соединения. Следом за ServerHello сервер обязательно передаёт сообщение EncryptedExtensions. Это логический блок, в который помещаются те расширения ServerHello, которые спецификация позволяет передавать в зашифрованном виде. Нередко сообщение EncryptedExtensions не содержит ни одного расширения, однако в таком случае необходимо передать пустое сообщение (то есть, состоящее только из заголовка).

Примеры EncryptedExtensions (обратите внимание, что здесь, по очевидным причинам, приводится расшифрованное сообщение; в реальных сессиях — это сообщение передаётся в защищённой TLS-записи с «историческим» типом 0x17, который передаётся в открытом виде; такой тип используется потому, что в TLS 1.3 он назначается всем защищённым записям, а подлинный тип записи — содержится внутри защищённых данных):

За EncryptedExtensions может последовать либо сообщение CertificateRequest (запрос сертификата клиента), либо Certificate — последнее содержит серверный TLS-сертификат. За исключением того, что эти сообщения зашифрованы, они аналогичны соответствующим сообщениям в предыдущих версиях. Передача Certificate сервером требует передачи и сообщения CertificateVerify.

В сообщении ClientHello клиент передаёт расширение SignatureAlgorithms, содержащее список поддерживаемых криптосистем электронной подписи. Одна из этих криптосистем используется сервером для вычисления значения CertificateVerify — сообщения, решающего сразу две важных задачи: во-первых, это сообщение позволяет клиенту проверить, что у сервера действительно есть секретный ключ от представленного сертификата; во-вторых, оно удостоверяет содержание полученных к этому моменту на стороне сервера других сообщений Handshake. Очевидно, что список поддерживаемых криптосистем подписи должен включать криптосистему, совместимую с сертификатом, так как вычисление подписи не от ключа сертификата — не имеет никакого смысла. То есть, CertificateVerify прежде всего следует рассматривать как основополагающую часть механизма аутентификации сервера клиентом. TLS-сертификат является публичным электронным документом, поэтому всякий может скопировать серверный сертификат и, позже, передавать его подключающимся клиентам. Однако наличие актуальной подписи лишает такой ход смысла.

Подпись CertificateVerify вычисляется от всего набора полученных (к моменту вычисления) сервером сообщений — откуда и возникает инструмент раннего удостоверения подлинности сессии: если между клиентом и сервером находится активный атакующий, который модифицирует сообщения, то клиент обнаружит расхождение подписи, так как проверяет её для своей копии переданных сообщений. Это существенное улучшение ситуации, по сравнению с предыдущими версиями протокола, в которых подобное удостоверение подлинности становилось возможным только в самом конце, после получения сообщения Finished.

В предыдущих версиях TLS аналогичное по значению сообщение передавал только клиент, в случае своей аутентификации сервером. В отношении же самого сервера, в зависимости от используемой схемы генерации общего секрета, предполагалось, что только узел, располагающий секретным ключом, сможет расшифровать переданные клиентом данные, либо о наличии секретного ключа можно судить по подписи на сообщении ServerKeyExchange. При этом, подпись на ServerKeyExchange не защищает прочие сообщения Handshake. (В TLS 1.3 сообщения ServerKeyExchange нет вообще.)

Мастер Йода рекомендует:  Создание и рассылка HTML электронных писем - введение для веб-разработчиков

Сообщение CertificateVerify имеет очевидную структуру: оно состоит из идентификатора криптосистемы подписи и самой подписи. Важнее посмотреть на то, как именно, и какие данные подписываются. Как объяснено ниже, электронная подпись на практике вычисляется для значения хеш-функции от подписываемого блока данных. В случае CertificateVerify, исходными данными служат все сообщения, полученные и переданные сервером к моменту генерирования подписи, а именно: сообщения, начиная от ClientHello и до, включительно, EncryptedExtensions или CertificateRequest; плюс — в цепочку добавляется сообщение Certificate. Обратите внимание, что в цепочку сообщений входят и HelloRetryRequest, если оно отправлялось сервером, и первое ClientHello. От объединения сообщений вычисляется хеш-функция, значение которой помещается в специальную структуру, и уже эта структура поступает на вход криптосистемы электронной подписи.

Клиент проверяет подпись CertificateVerify при помощи открытого ключа, содержащегося в серверном сертификате — этот ключ известен из сообщения Certificate.

Завершает набор серверных сообщений — серверное Finished. Это сообщение, как и в TLS предыдущих версий, содержит отпечаток всех известных серверу сообщений Handshake, которые предшествовали Finished. Finished является HMAC (кодом аутентификации с хеш-функцией), использующей секретный ключ. Этот ключ, в свою очередь, стороны вычисляют на основе имеющегося у них секрета. Обратите внимание, что Finished передаётся в зашифрованной TLS-записи и уже защищено кодом аутентификации используемого режима шифрования. Именно в таком режиме передаётся и Finished предыдущих версий протокола (см. выше). То есть, здесь логика хорошо совпадает, за исключением того, что в TLS 1.3 серверное Finished передаётся на шаг раньше.

Как уже упоминалось, в TLS 1.3 исключены сообщения-сигналы ChangeCipherSpec (CCS), которые в более ранних версиях обозначали момент перехода в защищённый режим обмена данными. Однако, экспериментальное внедрение TLS 1.3 ещё на ранних стадиях (речь про draft-версии) показало, что в ряде случаев TLS-соединение без CCS распознаётся разными системами инспекции трафика (DPI) как подозрительное (или «некорректное»), и, соответственно, разрывается. К сожалению, использование подобных «практик», а также оборудования DPI (и DLP), спроектированного с ошибками, является нормой для корпоративных сетевых сред, поэтому в TLS пришлось внести соответствующие дополнения: сигнал CCS вернулся в качестве фиктивного сообщения, которое никак не учитывается узлами, но позволяет «обмануть» DPI, делая соединение возможным.

Клиентская часть сообщений Handshake так же завершается Finished. После того, как стороны проверили Finished и убедились, что значения корректны, сессия считается установленной, а узлы переходят на новое поколение ключей.

Управление сеансовыми ключами в TLS 1.3

В TLS 1.3 используется многоэтапный подход к управлению симметричными ключами. Его логика строится на следующих предложениях: 1) каждая фаза протокола должна использовать свой набор ключей; 2) значения ключей должны зависеть не только от общего секрета и параметров Random, но и от других свойств конкретной сессии; 3) каждый следующий набор ключей зависит от предыдущего и дополнительной информации.

Основу для общего секрета составляет значение, полученное в рамках обмена DH, также (в дополнение к DH) может использоваться секретное значение, которое узлы согласовали каким-то способом ранее (схемы PSK). Поколения ключей соответствуют ходу соединения, при этом вычисление каждого поколения ключей основано на соответствующем поколении общего секрета. Схема не очень сложная, представляет собой ступенчатый переход от секрета к секрету, с подмешиванием новой информации на каждом шаге. Подмешиваемая информация представляет собой текстовые строки и сообщения протокола, которые преобразуются при помощи специальной функции. Тем не менее, в предыдущих версиях TLS ничего похожего не было. Однако механизм не является сколь-нибудь уникальным или особенным: есть немало криптографических протоколов, где применяется сходный подход, в качестве примера куда более сложного развития этой же идеи можно привести протокол Signal, который, как утверждается в документации, использует мессенджер WhatsApp (и ряд других приложений).

Рассмотрим упрощённую схему генерации ключей. Этапы идут сверху вниз, начиная от «пустого» значения, обозначенного 0 (в протоколе это строка нулевых байтов заданной длины). Центральная вертикальная линия соответствует движению ключевого материала, где к нему последовательно применяется функция генерации ключей (HKDF). Cлева — показаны основные источники входных данных с ключевой информацией. Справа — промежуточные результаты (общие секреты), сообщения Handshake, используемые в качестве дополнительно подмешиваемой информации, и симметричные «этапные» секреты, которые получаются на каждом шаге. Подмешивание информации происходит через последовательное вычисление значений хеш-функций и объединения (конкатенации) входных сообщений. Пример: если на входе имеется пара сообщений (ClientHello, ServerHello), а текущий этап является этапом Handshake (II — на схеме, указан Handshake Secret), то байты сообщений, в том порядке, как они передавались на транспортном уровне, объединяются в одну строку, от этой строки вычисляется хеш-функция, к результату присоединяется строка символов «c hs traffic», которая обозначает этап, а получившийся новый набор байтов, вместе с общим секретом, служит аргументом для генерации набора ключей при помощи функции Derive-Secret(). В реальном протоколе отличаются некоторые детали, в частности, используются специальные «обёртки» вокруг хеш-функций, но алгоритмическая логика — точно такая, как описано. Обратите внимание, что на схеме отражён алгоритм генерации симметричных секретов, но это ещё не сами сеансовые ключи. Ключи, а также соответствующие векторы инициализации, получаются на основе этих секретов в результате применения функции из семейства HKDF, а именно — HKDF-Expand-Label(). Узлы могут периодически заменять ключи защиты трафика приложений, выполняя ещё одну итерацию преобразования (этап III).

Сокращённый вариант установления соединения (Handshake) в TLS 1.3

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

Для использования данной схемы требуется, чтобы стороны заранее согласовали общий секрет (как описано выше). Если такой секрет известен, то клиент может начать соединение отправкой ClientHello, с указанием общего секрета, за которым сразу же следуют данные полезной нагрузки. В случае с HTTPS, такими данными будет, например, запрос HTTP GET — так как это самый распространённый сценарий в работе веб-сервисов. Другими словами, клиент сразу же, не дожидаясь ответа сервера, приступает к отправке запросов уровня приложения. В случае, если сервер успешно принял соединение, он отвечает сообщением ServerHello и другими сообщениями (Certificate и т.д.), заключает фазу открытия сессии сообщением Finished, и сразу же отправляет полезные данные, являющиеся ответом на запрос приложения клиента. В случае HTTPS, это будет HTTP-ответ на клиентский GET-запрос. Несложно заметить, что схема, по задержкам приёма-передачи, полностью эквивалентна обычной схеме HTTP: клиент отправляет запрос и получает ответ на него. При этом часть, относящуюся к TLS, можно считать некоторой дополнительной «обёрткой» над HTTP-схемой, не требующей выделенных сеансов приёма-передачи.

Клиентский запрос в схеме 0-RTT не обладает прогрессивной секретностью: он зашифрован не выделенным сеансовым ключом, а общим секретным ключом, полученным в другом сеансе. Соответственно, если ключ будет скомпрометирован, получившая его сторона сможет расшифровать клиентскую часть Handshake из записанного ранее трафика. Этот аспект относится только к клиентскому запросу, так как дальнейший трафик приложения защищается с использованием сессионных ключей, которые уже могут быть сгенерированы с обеспечением прогрессивной секретности. По этой и ряду других причин, схема 0-RTT в целом считается менее безопасной (это отмечено в спецификации TLS 1.3).

ESNI: защита данных расширения SNI

Расширение SNI (Server Name Indication) используется для передачи серверу имени (логического) ресурса, с которым планирует установить соединение клиент. Как видно из сообщений, разобранных выше, SNI содержит строку символов, в которой записано имя. Эта строка передаётся в открытом виде. SNI оказывается необходимым элементом, если используется следующая, весьма распространённая, конфигурация: один и тот же IP-адрес разделяется несколькими ресурсами под несколькими именами (DNS), при этом для каждого имени — свой TLS-сертификат. Сервер должен отправить клиенту серверный сертификат в самом начале соединения, если таких сертификатов несколько и они различаются по именам, то, в случае простого ClientHello, без указания SNI, сервер не может определить, какой сертификат отправить. При этом процесс валидации сертификата клиентом требует, чтобы имя узла, которое ожидает получить клиент, совпало с именем в сертификате. (Оговорка про IP-адрес здесь важна потому, что если узел использует один IP-адрес для одного имени, то определить подходящий сертификат можно по IP-адресу.)

Так, SNI поддерживается всеми современными браузерами, а это означает, что на начальном этапе установления соединения клиент раскрывает третьей стороне, пассивно прослушивающей трафик, имя узла, с которым пытается соединиться. SNI представляет собой канал утечки метаинформации: несмотря на то, что трафик защищён TLS, прослушивающей стороне известны имена, к которым обращается клиент. Это хорошо известная особенность TLS. Попытки побороть данную утечку предпринимались довольно давно. В ходе разработки версии TLS 1.3 эти попытки активизировались. Однако ввести защиту SNI от прослушивания непосредственно в спецификацию TLS 1.3 не получилось. Это, в основном, связано с тем, что всякая защита SNI требует дополнительных вычислительных затрат: имя, находящееся внутри SNI, нужно для того, чтобы найти подходящий сертификат на стороне сервера; этот сертификат содержит ключ, необходимый для создания защищённого канала, то есть, защитить SNI тем же ключом — не получится; это означает, что нужны дополнительные ключи, которые требуют согласования и, следовательно, обмена сообщениями. Другими словами, выстроить простую и надёжную схему нелегко. Тем не менее, практический механизм защиты SNI в 2020 году всё же появился.

Этот механизм называется ESNI (Encrypted SNI) и использует DNS (доменную систему имён) для хранения дополнительных ключей. Спецификация пока что (июль 2020) находится в статусе черновика, однако поддержка уже реализована в браузере Firefox.

Предложенный вариант ESNI работает следующим образом: в специальной DNS-записи, соответствующей имени сервера, публикуется открытый ключ DH (протокола Диффи-Хеллмана), а также параметры, которые сервер поддерживает для зашифрования поля имени. Клиент, — это может быть браузер, — извлекает из DNS ключ DH, вычисляет собственный открытый ключ DH, общий секрет и, на основе этого секрета, симметричный ключ, которы использует при зашифровании стороки с именем сервера. Зашифрованное таким образом поле SNI клиент передаёт серверу в составе начального сообщения ClientHello, внутри специального расширения ESNI. В расширение также входит значение открытого ключа DH клиента. Сервер, располагая соответствующим секретным ключом DH, может вычислить симметричный ключ и расшифровать имя, переданное клиентом в ESNI.

Таким образом, имя сервера оказывается защищено от просмотра третьей стороной, а необходимые дополнительные ключи — публикуются в DNS. Естественно, запрос к DNS может послужить каналом утечки, аналогичным открытому полю SNI. Предполагается, что, во-первых, клиент использует защищённый способ доступа к DNS (например, DNS-over-TLS); во-вторых, для дополнительной маскировки ключи для зашифрования ESNI могут публиковаться под DNS-именем, которое отличается от скрытого имени сервера (естественно, такое «имя прикрытия» должно быть заранее известно клиенту); в-третьих, ключи для ESNI могут быть распределены способом, отличным от DNS.

Черновик RFC предусматривает выделение для ESNI отдельного типа DNS-записи. Кроме ключей и других криптографических параметров, ESNI-запись в DNS сможет включать и IP-адреса сервера. Это означает, что клиенту достаточно будет одного запроса в DNS для извлечения и ключей, и адреса сервера.

Асимметричные криптосистемы, электронная подпись

Для организации защищённого соединения в TLS также используются асимметричные криптосистемы, криптосистемы электронной подписи. На практике, сейчас это RSA и ECDSA. Как описано выше, RSA может применяться в исторической схеме для передачи сеансового секрета клиентом на сервер (такая схема всё ещё нередко встречается). ECDSA — служит только для получения подписи, то есть, аутентификации. Предполагается, что в ближайшем будущем RSA окажется вытеснена эллиптическими системами, а в качестве второго направления добавятся постквантовые алгоритмы (то есть, криптосистемы, обладающие стойкостью в предположении атаки на квантовом компьютере).

Криптосистема RSA

RSA — самая массовая криптосистема с открытым ключом (асимметричная криптосистема). Повсеместно используется для подписи в составе TLS-сертификатов. Долгое время RSA являлась, фактически, единственной криптосистемой TLS-сертификатов. Лишь несколько лет назад (в 2014 году) наряду с RSA стала заметна доля ECDSA в сертификатах. Логика построения RSA напоминает протокол Диффи-Хеллмана, однако математические объекты используются другие, также отличаются свойства однонаправленной функции. В RSA однонаправленная функция имеет «лазейку» или «чёрный ход», знание которого позволяет легко обратить функцию, вычислить аргумент по значению. RSA основана на возведении в степень по модулю, а стойкость этой криптосистемы связана с задачей разложения числа на простые множители. Можно считать, что секретом в RSA является именно разложение «ключа» на простые множители. Слово «ключ» здесь дано в кавычках, так как на практике ключ включает ещё дополнительный параметр, но этот параметр всегда можно легко вычислить, зная разложение.

Параметрами криптосистемы RSA являются модуль (это всегда составное число) и открытая (часто её называют «шифрующей») экспонента — то есть, показатель степени, в которую возводится значение сообщения. Сообщение, в рамках RSA, это целое число, записываемое в виде последовательности байтов. Модуль в RSA является составным числом: N = pq, где p и q — достаточно большие простые числа, именно их и нужно держать в секрете. (Строго говоря, успехи криптоанализа RSA накладывают на p и q немало дополнительных требований, которые мы не рассматриваем, так как для понимания принципа работы криптосистемы это не важно.) Знание разложения N = pq позволяет построить «лазейку», с помощью которой можно обратить однонаправленную функцию, лежащую в основе RSA.

Помимо модуля, для использования RSA с целью генерирования электронной подписи и расшифровки сообщений, необходимо сгенерировать секретный ключ. Секретным ключом является экспонента, обратная к шифрующей (расшифровывающая). В случае TLS, сервер публикует модуль N и шифрующую экспоненту e, а в секрете сохраняется соответствующая e расшифровывающая экспонента d = e -1 по модулю (p-1)(q-1) (нередко в состав представления секретного ключа входит разложение модуля — p и q, необходимое не только для вычисления d, но и для ускорения вычислительных операций). Таким образом, открытый ключ состоит из N и e, а закрытый — из (N,p,q,d). Открытый ключ обычно публикуется в составе сертификата TLS (сертификаты подробнее рассмотрены в специальном разделе ниже) и служит для проверки подписей, а для их генерации — необходимо знать соответствующий секретный ключ.

RSA позволяет зашифровать сообщение, выступая в роли асимметричного шифра. Учебный пример зашифрования состоит в возведении сообщения, представленного в виде числа, в шифрующую степень и вычислении остатка по модулю N (заданному в составе ключа). C = m e mod N, где C — шифротекст, а m — открытый текст. Соответственно, зная расшифровывающую экспоненту, можно расшифровать C: m = C d mod N. Это соотношение можно проиллюстрировать следующим нестрогим рассуждением, используя тот факт, что e = d -1 (mod (p-1)(q-1)), поэтому: C d = (m e ) d = m e*d = m e*e -1 = m 1 = m (mod N).

Из-за возможности проведения эффективной атаки, RSA нельзя использовать подобным прямым образом, непосредственно зашифровывая сообщение. Допустимым вариантом является, например, шифрование RSA случайного секрета, дополненного специальным образом до разрядности модуля, с последующим вычислением ключа симметричного шифра при помощи хеш-функции от переданного секрета — именно эта схема используется в TLS.

Генерация ключей RSA начинается с генерации пары простых чисел, которые составят модуль. Знание p и q позволяет легко определить обратную к шифрующей экспоненту. Однако задача разложения числа на простые множители (факторизации) является вычислительно сложной. Фактически, для достаточно больших чисел (1024 бит и более), сейчас не известно алгоритмов, позволяющих находить разложение произвольных чисел за разумное время с использованием любых технологически мыслимых вычислительных мощностей. Тем не менее, существует, — пока сугубо теоретическая, но отлично обоснованная, — возможность быстрой факторизации при помощи алгоритма Шора на квантовом компьютере достаточной разрядности (под вопросом находится сама возможность создания подходящего компьютера). «Квантовая атака» касается не только RSA, но также и описанных выше вариантов DH, и криптосистемы электронной подписи ECDSA. При этом, так как применимость квантового компьютера зависит от его доступной разрядности — от числа кубитов, — то, например, ECDSA будет взломана раньше RSA, так как ECDSA использует числа существенно меньшей разрядности (типичные значения: 256 бит против 2048 у RSA).

При использовании для создания и проверки электронной подписи в TLS, RSA работает следующим образом. Сторона, генерирующая подпись, вычисляет значение хеш-функции от подписываемого сообщения (H = Hash(M)), приводит это значение к разрядности используемого модуля N и вычисляет значение подписи при помощи секретной (расшифровывающей) экспоненты: S = H d mod N. Для проверки подписи требуется знать открытую часть ключа: модуль и шифрующую экспоненту e. Значение подписи возводится в степень e, а получившееся значение сравнивается с вычисленным значением хеш-функции сообщения: S e mod N = H, если значения совпали, то подпись верна. Для вычисления корректной подписи (подделки) третьей стороне необходимо знать секретную экспоненту d, что и обеспечивает защиту.

Этот механизм электронной подписи используется для удостоверения параметров протокола Диффи-Хеллмана, переданных сервером в сообщении ServerKeyExchange. Подпись, передаваемая в составе сообщения TLS, является целым числом, имеющим разрядность, соответствующую разрядности модуля ключа. Модуль ключа содержится в сертификате сервера. Так, если модуль имеет разрядность 2048 бит, то для записи подписи потребуется 256 байтов (256*8 = 2048). Подпись, как отмечено выше, вычисляется от значения хеш-функции для объединения параметров (в них входит и серверная часть обмена DH), кроме того, в TLS 1.2 к параметрам добавляются значения ServerRandom и ClientRandom. В процессе вычисления значения подписи параметры преобразуются к требуемому формату.

При прямой передаче сеансового секрета на сервер, RSA применяется самым хрестоматийным образом: открытый ключ извлекается из сертификата сервера, сгенерированный секрет преобразуется к установленному формату, а результат возводится в степень, заданную шифрующей экспонентой. Получившееся зашифрованное сообщение передаётся в ClientKeyExchange (как описано выше). Сервер, которому известно значение секретной экспоненты, расшифровывает полученное сообщение. Предполагается, что если в ход установления соединения вмешалась третья сторона, подменившая сервер, то этой стороне не удастся корректно расшифровать переданный клиентом секрет, соответственно, стороны не смогут прийти к общему набору сеансовых ключей. Интересно, что для обхода данного ограничения перехватывающей стороне не требуется строго сам секретный ключ, значение которого нигде не участвует, а достаточно, чтобы была возможность расшифровать данные, например, отправив запрос серверу. Такая схема иногда используется при делегировании полномочий по инспекции TLS-трафика третьей стороне, без передачи самого секретного ключа (однако в отношении RSA схема вовсе не является полностью безопасной).

Другое историческое применение RSA, как асимметричного шифра в TLS, возможно при выборе сервером варианта протокола установления соединения, использующего временные ключи RSA. В таком случае сервер передаёт модуль и значение открытой экспоненты в составе сообщения ServerKeyExchange. Клиент использует полученный открытый ключ RSA для того, чтобы зашифровать случайные байты ClientKeyExchange, которые послужат для генерации симметричных ключей. Эта экзотическая схема была актуальна для «экспортных» вариантов протокола, когда от реализации требовалось, чтобы для защиты сессии не применялись ключи RSA длиннее 512 бит: сервер использовал «длинный» ключ из сертификата для подписывания «короткого» временного ключа из ServerKeyExchange. Сейчас RSA в TLS не следует использовать в качестве асимметричного шифра, это небезопасно (тем более, с коротким ключом).

Таким образом, операции в криптосистеме RSA сводятся к возведению в степень, осуществляемому в кольце (по модулю N). Если атакующая криптосистему сторона умеет быстро извлекать в данном кольце корни произвольной степени из произвольных значений, либо быстро находить обратный элемент в ряде специальных случаев, то RSA теряет стойкость. С этими направлениями атак связано большое число теоретико-числовых оптимизаций, успешно используемых в криптоанализе RSA.

Важно учитывать, что математическая эквивалентность операций получения электронной подписи и расшифрования в RSA является особенностью данной криптосистемы, не более того. Операции подписывания и зашифрования/расшифрования — это разные операции, их совпадение в RSA не означает, что другие криптосистемы электронной подписи могут прямо служить шифрами (хотя построить шифр на базе такой криптосистемы обычно можно).

Рассмотрим фрагмент трафика установления TLS-соединения, в котором узлы договорились использовать шифронабор с передачей сеансового секрета с помощью шифрования RSA (а именно: TLS_RSA_WITH_AES_128_CBC_SHA). Сертификат, представленный сервером, содержит открытый ключ длиной 2048 бит. Этот ключ используется клиентом для зашифрования. О том, что клиент прислал именно зашифрованный RSA секрет — сервер знает потому, что RSA указана в шифронаборе, соответственно, рассматриваемое сообщение ClientKeyExchange не содержит никакого указания на то, что используется именно RSA, с тем или иным ключом.

Криптосистема ECDSA

ECDSA является эллиптическим вариантом криптосистемы электронной подписи DSA. Последняя (DSA) — сейчас практически не используется. Интересно, что она, в свою очередь, является вариантом схемы подписи Эль-Гамаля, которая представляет собой алгоритм, построенный на базе задачи дискретного логарифмирования, и, таким образом, имеющий прямое родство с протоколом Диффи-Хеллмана.

Фундаментальную идею схемы ECDSA можно изложить следующим образом: предложим такую пару алгоритмов для генерации значения подписи и проверки этого значения, которые будут «сходиться» к одному значению только в том случае, если стороны использовали ключи из связанной однонаправленной функцией пары (это, впрочем, очевидная схема для ЭЦП). В качестве однонаправленной функции используется умножение точки эллиптической кривой на скаляр. При этом подписи «рандомизируются», для чего служит дополнительный параметр — ещё одна точка кривой. При успешной проверке, результат, полученный проверяющей стороной, совпадёт с этой дополнительной точкой — откуда и возникает, достаточно условное, представление о том, что схемы сходятся «в одной точке». ECDSA существенно отличается от RSA, как по составу и свойствам параметров, ключей, так и по алгоритмам генерации подписи и её проверки. ECDSA, вообще говоря, несколько сложнее. Ключевым является тот факт, что обе основные части криптосистемы ECDSA — алгоритм вычисления подписи и алгоритм проверки, — представляют собой две части единого базового соотношения.

Итак, прежде чем использовать ECDSA, стороны должны согласовать общие параметры: выбрать кривую E (она задаётся парой чисел); выбрать конечное поле, над которым будут производиться операции на кривой (кривая, как и в ECDH, используется в целочисленной форме); выбрать соответствующую общую точку на кривой — генератор G. Точка — это пара значений (x,y), которые далее называются координатами. (x,y) — элементы соответствующего поля. Как и в случае с «эллиптическим» вариантом DH, на кривой задана операция сложения точек — это та же самая операция, которая используется и в ECDH (см. выше). На этой операции строится алгоритм удвоения точки и умножения на скаляр. Именно умножение на скаляр является основой криптосистемы (опять же, аналогично ECDH). Так как используется аддитивная запись, то речь идёт именно об умножении, однако в мультипликативном случае ему соответствовало бы возведение в степень, отсюда и возникает «логарифмирование». И, опять же, это не более чем терминологическое соглашение. Если у нас есть точка N на кривой, то умножение на скаляр dN — тоже даёт точку (B) на кривой. Задача вычисления d по известным N, B и есть задача дискретного логарифмирования на эллиптической кривой, уже знакомая из описания протокола Диффи-Хеллмана.

Открытый ключ в ECDSA — это точка Q на кривой, полученная умножением выбранного генератора G на целое положительное число d: Q = dG. Соответственно, d — является секретным ключом. Схема здесь напоминает RSA, только в данном случае в состав открытого ключа не входит некий модуль. Генератор G является публичным значением, но, как было только что отмечено, для того, чтобы определить d, потребуется отыскать соответствующий логарифм, что нереализуемо на практике (при условии правильно выбранных параметров криптосистемы). Открытый ключ, таким образом, представляет собой пару чисел (xq,yq) — так как точке соответствует две координаты. Важно понимать, что эти координаты — это просто пара элементов поля, удовлетворяющих уравнению кривой. То есть, можно рассматривать кривую с операцией умножения точки на скаляр, как некоторую структуру, заданную поверх пар элементов выбранного поля. При этом умножение точки кривой на скаляр — это операция в группе точек кривой, а не в поле. А именно: умножению точки на скаляр d (натуральное число) соответствует (d-1) операций сложения точек, каждая из которых ставит в соответствие двум парам элементов поля, возможно, совпадающим, — третью пару, так как одна точка характеризуется именно парой элементов поля. На практике, так как используется конечное поле, его элементы всегда можно пронумеровать натуральными числами, что позволяет эффективно проводить компьютерные вычисления. Но следует учитывать, что операции в поле и на кривой не будут совпадать с привычными операциями над натуральными числами (которые поля не образуют). Дополнительные сведения о соответствующем математическом аппарате приведены в «Приложении А».

Для вычисления подписи в ECDSA используется хеш-функция, позволяющая получить «сжатое» представление сообщения M: H = Hash(M). Значение H приводится к разрядности выбранных параметров. В описании ниже — n обозначает порядок генератора G в группе кривой, то есть nG = 0 (0 — нейтральный элемент группы точек кривой). Схема существенным образом базируется на «рандомизации» — каждая подпись использует случайный параметр k, который не должен повторяться. Уникальность k является фундаментальным требованием для обеспечения стойкости ECDSA, поскольку повторное использование позволяет вычислить секретный ключ. Это, пожалуй, самая часто упоминаемая в литературе особенность ECDSA, но тем не менее, ошибки тут всё равно встречаются. Именно на некорректном, повторном использовании k основывался нашумевший взлом системы защиты ПО Sony Playstation в 2010 году.

Вычисление подписи (на входе: значение хеш-функции от сообщения — H; секретный ключ — d) выполняется следующим образом (RFC 6979):

  • 1) выбирается уникальное (псевдо)случайное число k (соответствующее интервалу [1,n-1]);
  • 2) вычисляется точка kG (где G — это генератор, заданный в параметрах). Данная точка на кривой является точкой, задающей конкретное значение подписи, связывающей алгоритм проверки подписи с алгоритмом генерации. Точке kG соответствуют координаты (x,y);
  • 3) для x вычисляется значение r = x mod n (то есть, остаток от деления x на порядок генератора G; r — это первая часть значения подписи; если r = 0, что крайне маловероятно, то алгоритм возвращается к шагу 1);
  • 4) вычисляется значение s = k -1 (H + rd) mod n. k -1 — это обратный к k элемент (относительно умножения) по модулю n, его несложно вычислить;
  • 5) пара (r,s) — и есть значение электронной подписи.

Так как от выбора k зависит стойкость реализации ECDSA, для генерации этого параметра предложены различные безопасные схемы, в том числе, детерминированные алгоритмы, работающие наподобие счётчика и, таким образом, сводящие к минимуму вероятность повтора k.

Для проверки подписи необходимо знать параметры криптосистемы, а также открытый ключ Q. Перед проверкой необходимо убедиться, что переданные значения соответствуют криптосистеме (Q является точкой соответствующей кривой, и так далее). Проверка выполняется по следующему алгоритму (на входе — значение хеш-функции H от сообщения, пара (r,s), открытый ключ Q):

  • 1) вычисляется значение v = s -1 mod n;
  • 2) вычисляется значение u1 = Hv mod n;
  • 3) вычисляется значение u2 = rv mod n;
  • 4) определяется точка B на кривой = u1G + u2Q. Здесь G — генератор, заданный в параметрах, а Q — открытый ключ. Умножение — обозначает умножение точки кривой на скаляр;
  • 5) если для координаты x точки B выполняется r = x mod n, то подпись считается действительной.

Согласно шагу 4 алгоритма вычисления значения подписи: s = k -1 (H + rd) mod n. Выполним подстановки (все сравнения по модулю n, вместо знака ≡ для простоты используем знак равенства):

  • k = s -1 (H+rd) = s -1 H+s -1 rd = (Hv) + (rv)d = u1 + u2d;
  • мы нашли, что u1 + u2d = k; здесь k — случайный параметр подписи, а d — секретный ключ, соответствующий Q;
  • преобразования следуют из соотношений, заданных в алгоритме проверки и связывают открытый ключ, случайный параметр k и значение подписи, относительно значения H (хеш сообщения);
  • Q = dG, что позволяет выполнить следующую замену: u1G + u2Q = u1G + u2dG = (u1 + u2d)G = kG (соответствует исходной точке, определённой на шаге 2 алгоритма вычисления подписи);
  • таким образом, если подпись действительно получена от ключа Q, то r = x mod n (ведь x — это координата, соответствующая точке kG).

ECDSA используется как в TLS-сертификатах, так и для удостоверения серверных параметров DH. При этом ECDSA нельзя использовать для зашифрования, а только для получения и проверки электронной подписи.

Рассмотрим фрагмент трафика TLS-сессии — это сообщение ServerKeyExchange, в котором передаются параметры протокола Диффи-Хеллмана на эллиптических кривых (ECDH), подписанные ECDSA.

Параметры криптосистем

Все описанные криптосистемы подразумевают, что стороны согласовали некоторые параметры, определяющие контекст применения:

  • для «классического» варианта протокола Диффи-Хеллмана это модуль, задающий группу, а также генератор в ней;
  • для ECDH (на эллиптической кривой) — параметры кривой, включающие поле, над которым кривая используется, и, опять же, генератор;
  • для RSA — шифрующая экспонента и модуль;
  • для ECDSA — параметры кривой и генератор.

Наибольшее число параметров требуется для эллиптических криптосистем. В TLS для них принято использовать типовые кривые, обозначенные зафиксированными именами, но при установлении соединения в версиях ниже 1.3 можно указать и любую другую кривую. В TLS 1.3 — параметры зафиксированы строго. Очевидно, и сервер, и клиент должны соответствующую кривую поддерживать. Каждому типовому набору соответствует сама кривая и поле, над которым проводятся операции. Реестр имён и индексов ведёт IANA, названия определены в RFC: 4492, 7027 и др. Конкретные параметры — определены в сопутствующих документах NIST, ANSI и в др. В 2020 году соответствующий реестр IANA переименован в «Реестр поддерживаемых групп» («Supported Groups Registry»), что лучше соответствует математической действительности, потому что используемые в TLS криптосистемы работают в группах, просто, в ряде случаев, это группы точек эллиптической кривой.

С именованием кривых существует некоторая исторически сложившаяся путаница. Например, кривая, распространённая в сертификатах, используемых для HTTPS, называется prime256v1, она же — secp256r1, она же — NIST P-256; а параметры этой кривой определены, в частности, в рекомендации NIST 186-4.

Типичные параметры ECDSA, на примере NIST P-256 (источник: SafeCurves, там же представлены сводные данные по всем другим распространённым кривым):

Сертификаты

TLS-сертификаты (SSL-сертификаты — устаревшее название, являющееся синонимом) играют важную роль в современной инфраструктуре TLS. У TLS-сертификата одно предназначение: привязать открытый ключ к некоторому сетевому имени. Например, сопоставить ключ 0xA3VEF7. DA3107 имени example.com. TLS-сертификаты не содержат никакой секретной информации. Они не являются непосредственными носителями ключей шифрования передаваемых данных в TLS (за исключением открытого серверного ключа RSA, который может быть использован для зашифрования сеансового секрета в устаревших режимах работы TLS).

Открытый ключ, который содержится в сертификате, принадлежит искомому серверу, с которым клиент планирует установить соединение. Однако открытый ключ может быть подменён третьей стороной на другой, имитирующий легитимный ключ сервера. Для того, чтобы можно было обнаружить подобную подмену, служит инфраструктура удостоверяющих центров, которая даёт клиенту механизм проверки принадлежности ключа. То есть клиент соглашается верить некоторой третьей стороне (не злоумышленнику, а удостоверяющему центру — УЦ), что эта третья сторона проверила соответствие ключа и сетевого имени (в вебе это обычно домен). Результат такой проверки подтверждается подписью УЦ, которую он ставит на сертификате сервера. Для подписи сейчас используются криптосистемы RSA (повсеместно) и ECDSA (поддержка этой криптосистемы до сих пор ограничена — соответствующие сертификаты доступны не у всех УЦ).

Предполагается, что клиент TLS имеет в своём распоряжении некоторый набор сертификатов удостоверяющих центров (часть из этих сертификатов является корневыми) и может проверить подписи на предоставляемых сервером сертификатах, выстроив цепочку доверия, ведущую от серверного ключа к одному из доверенных корней. На практике, в браузеры встроены многие десятки корней, соответствующих различным УЦ. Для выстраивания цепочки доверия определяющее значение имеет именно корневой ключ, а не сам сертификат, который его содержит. Тем не менее, в сертификате содержатся имена, которые позволяют отличить один ключ от другого и сопоставить отдельные сертификаты друг другу.

В SSL/TLS используются сертификаты формата X.509, это очень старый формат, изначально разрабатывавшийся для телеграфа, но позже адаптированный для использования в Интернете, в частности, в вебе.

Сертификат представляет собой электронный документ, имеющий определённую спецификацией структуру. Так, каждый сертификат содержит поля Issuer и Subject. Поле Issuer определяет имя стороны, выпустившей данный сертификат (поставившей на нём подпись), а поле Subject — имя стороны, для которой сертификат выпущен. В случае веба, в Issuer обычно указано имя из сертификата УЦ (не обязательно корневого), а в Subject, для серверного сертификата, — доменное имя, адресующее сайт. В 2020 году в браузере Google Chrome появилось новшество: для валидации сертификата по имени сервера, это имя должно быть указано не в Subject, а в расширении сертификата под названием SAN (Subject Alternative Name).

Клиент получает сертификаты (в большинстве случаев — это цепочка, но может быть и единственный серверный сертификат) в сообщении Certificate (см. выше), выстраивает их в последовательность, где каждый сертификат удостоверяет следующий, проверяет подписи и соответствие имени из серверного сертификата имени сервера, с которым планирует установить соединение. Проверка имени является важнейшим аспектом, так как злоумышленник может выпустить доверенный сертификат для своего имени сервера, но предъявлять его под именем другого сервера (перехватив сеанс тем или иным способом). В таком случае, полностью валидный сертификат злоумышленника будет отличаться от легитимного только указанным именем и ключом. Например, сертификат выпущен для example.com, а предъявляется для test.ru. (Такое несоответствие также является одной из самых распространённых ошибок настройки TLS-серверов.)


Сертификат выпускается на определённый срок, который указан в самом сертификате. Сертификат может быть отозван, по какой-то причине, раньше окончания срока действия. Браузеры и другие TLS-клиенты должны проверять статус отзыва сертификатов, для этого существует ряд механизмов, однако в повседневной реальности проверка отзыва сертификатов, фактически, не работает — этот момент нужно учитывать при анализе рисков.

Посмотрим на пример TLS-сертификата — это расшифровка полей сертификата, выпущенного для dxdt.ru УЦ WoSign, полученная утилитой openssl x509:

Итак, TLS-сертификаты являются важным элементом TLS, позволяющим проводить аутентификацию. Ключи из сертификатов используются при генерации общего секрета. В теории, возможно установление анонимного TLS-соединения без использования сертификатов (это не запрещено спецификацией, а серверное сообщение Certificate не является строго обязательным), однако массово применяемые на практике методы генерации сеансового ключа основываются на использовании серверного сертификата (а точнее — на использовании открытого ключа из сертификата).

Основные современные претензии к TLS-сертификатам касаются сложившейся административной структуры УЦ. Так, пока что никакая распространённая технология не мешает УЦ выпустить «подменный» сертификат, позволяющий прозрачно перехватывать TLS-соединения, используя атаку типа «человек посередине» (см. ниже в разделе про перехват HTTPS). Но такие технологии разрабатываются и успешно внедряются, к ним относится инициатива Certificate Transparency (поддерживаемая Google), Certificate Pinning или Public Key Pinning, когда в браузерах сохраняются (и обновляются) заведомо корректные для данного узла сертификаты или открытые ключи, а также технология DANE, использующая DNS в качестве дополнительной системы контроля.

Шифры в TLS

Как рассказано выше, TLS использует для защиты информации шифронаборы. Шифронабор (Cipher Suite) позволяет обеспечить не только сокрытие информации, но и её целостность. В состав шифронабора входит симметричный шифр. С его помощью осуществляется зашифрование потока данных, передаваемых через TLS-сокет. Возможно использование TLS без шифрования, однако это не является распространённым случаем.

В терминологии TLS существуют зашифровывающие и расшифровывающие функции. Эти функции работают с криптографическим контекстом соединения, о котором договорились узлы. После того, как узлы обменялись сообщениями ChangeCipherSpec (см. выше), все TLS-сообщения зашифрованы, а в TLS 1.3 шифрование включается даже раньше. Зашифровывающая функция преобразует открытый текст, подготовленный для отправки в составе TLS-записи (строго говоря, после сжатия, но, как рассказано выше, в современной реальности TLS сжатие не используется), в секретный текст (зашифрованный). Расшифровывающая функция выполняет обратное преобразование. Для того, чтобы зашифровывающие и расшифровывающие функции успешно работали на обоих узлах, требуется выработка общего криптографического контекста — это происходит в рамках обмена сообщениями Handshake. В TLS могут использоваться и потоковые, и блочные шифры, последние — в различных режимах. Обычно, зашифровывающие и расшифровывающие функции являются одним симметричным шифром и различаются только составом ключей. TLS 1.3 существенно ужесточает принципы включения шифронаборов в реализации, фактически, в действующей (июль 2020) версии 1.3 допущены только два шифра: AES и ChaCha20.

Шифр — это некоторый набор обратимых преобразований данных, каждое из которых определяется параметром — ключом шифрования. Порядок применения этих преобразований к входным сообщениям принято называть режимом шифрования. Простейшая криптосистема может включать лишь один шифр, то есть, грубо говоря, состоять из одного алгоритма зашифрования и (обратного к нему) алгоритма расшифрования. В симметричных системах, которые используются в TLS, знание шифрующего ключа позволяет легко получить расшифровывающий ключ, то есть расшифровать секретное сообщение. В используемых сейчас массовых симметричных криптосистемах шифрующий и расшифровывающий ключи просто совпадают, поэтому обычно говорят об одном и том же ключе. Другими словами, симметричные системы подразумевают, что обе стороны, обменивающиеся информацией по закрытому каналу, знают некий общий секрет ― например, секретный симметричный криптографический ключ, который позволяет как зашифровывать, так и расшифровывать сообщения. Обратите ещё раз внимание на то, что в TLS используется набор из двух ключей (ключ «записи» и ключ «чтения»), но эти наборы симметричны, на стороне клинта или сервера — ключи просто меняются местами: серверная «запись» становится «чтением» клиента.

Симметричные криптосистемы — первые из придуманных человечеством. Историческими примерами симметричных криптосистем являются так называемые «наивные» шифры — например, шифры простой замены букв текста на естественном языке, где в качестве ключа может выступать та или иная перестановка алфавита. Современные шифры, вроде AES или 3DES, тоже являются симметричными. К симметричным относится и единственная криптосистема, обладающая абсолютной стойкостью — шифр Вернама, с равновероятным одноразовым ключом, равным по длине шифруемому сообщению (одноразовый шифр-блокнот). Шифр Вернама не очень удобен, поэтому нечасто используется на практике. Однако основная идея этого шифра послужила прообразом самых защищённых режимов шифрования в TLS.

В основе логики построения современных шифров лежит задача сокрытия статистических свойств исходного открытого текста. То есть, шифр стремятся спроектировать таким образом, чтобы его вывод был вычислительно неотличим от результата (псевдо)случайной функции (точнее — перестановки, но это комбинаторные детали). Дело в том, что попытка скрывать лишь сами символы открытого текста не даёт никакой секретности. Игрушечным, но весьма показательным примером является шифр простой замены, где буквы открытого текста заменяются на какие-то другие символы (например, на специально выдуманные «иероглифы»). Каждая буква неузнаваема, но прочитать такой шифротекст легко, если известно, на каком языке был записан открытый текст, так как статистические свойства открытого текста прямо наследуются: частотность «иероглифов» соответствует известной частотности букв в тексте на исходном языке. Эта классическая «дешифровка» многократно описана в художественной литературе. Соответственно, современные криптосистемы прежде всего направлены на сокрытие статистических свойств открытого текста, на «размытие» статистики «до уровня случайности». (Важно отметить, что при правильном выборе процедуры генерации ключей, шифр простой замены может быть сделан чрезвычайно стойким, вплоть до невозможности вскрытия персонажами художественного произведения.)

Криптосистемы строятся на базе некоторых «примитивов» — своего рода строительных блоков, которые выполняют базовые операции над данными. К базовым операциям относятся подстановки, перемешивание, сложение и умножение (выполняемые по модулю некоторого числа или ещё каким-то особенным способом). Эти операции проводятся над входными данными, рассматриваемыми как набор символов, обычно, символами являются биты и байты, но возможны и другие варианты: например, слова из четырёх битов или двухбайтовые символы. Для того, чтобы составить самое простое представление о современных симметричных шифрах, можно представить, что шифр — это некоторый «ящик», на входы которого (в режиме зашифрования) поступают открытый текст и ключ, внутри символы открытого текста перемешиваются по схеме, определяемой ключом, и выводятся из «ящика» в качестве шифротекста. Каждый бит открытого текста оказывает существенное влияние на весь шифротекст: благодаря «лавинному эффекту» изменение даже значения одного бита в открытом тексте (или в ключе зашифрования) приводит к массовым изменениям в соответствующем шифротексте. Для расшифрования используется «ящик» на входы которого поступают шифротекст и ключ, символы опять перемешиваются, в результате на выходе получается открытый текст: если ключи совпали, то этот открытый текст совпадёт с исходным открытым текстом. Далеко не всегда для шифрования и расшифрования используется один и тот же «ящик»: алгоритмы могут различаться. Более того, в современных схемах использования, шифр может применяться только в режиме зашифрования, каким бы странным этот момент не казался на первый взгляд.

Ключом в массовых современных симметричных криптосистемах является целое число достаточно большой разрядности ― 128 бит и более. Если криптосистема добротная, то есть, наилучшим алгоритмом атаки (взлома) для неё является полный перебор всего множества ключей, то 128 бит — более чем достаточная степень безопасности. Предположим, что ключ можно угадать с вероятностью 1/2, перебрав половину пространства ключей. (Вероятность 1/2 — это огромный показатель в разрезе криптографической защиты информации. Криптосистема, которую можно взломать с такой вероятностью, никакой стойкостью не обладает.) Тогда, в случае 128-битного ключа, придётся выполнить (2 128 )/2 = 2 127 операций. Это огромное число вариантов, перебрать их за обозримое время невозможно. Проблема состоит в том, что для шифров обычно известны оптимизации, которые позволяют уменьшить число перебираемых вариантов. Например, снизить его для 128-битного ключа до 2 56 . Перебрать 2 56 вариантов для вычислительно незатратного шифра можно очень быстро, даже если использовать в качестве вычислителя кластер из устаревших смартфонов или GPU-ферму с несколькими видеокартами. Наличие такой оптимизации является уязвимостью криптосистемы.

Шифры принято делить на блочные и потоковые. В настоящее время такое деление оказывается довольно условным и имеет, скорее, историческое значение. Блочные шифры отличаются от потоковых тем, что работают с блоками фиксированной длины и требуют разбиения потока байтов на такие блоки; в блочном шифре каждый байт обрабатывается в составе блока байтов (битов). Потоковые шифры, напротив, работают прямо с потоком битов (или байтов, потому что байт, вообще говоря, тоже можно считать блоком), без разбиения. Существуют режимы использования блочных шифров, которые позволяют рассматривать их, фактически, как потоковые. Классический потоковый шифр TLS — RC4, который сейчас считается устаревшим и нестойким. Классические блочные шифры: DES и 3DES, ГОСТ 28147-89. Особенностью блочных шифров является то, что они требуют использования дополнения (padding): в случае, если открытый текст не кратен размеру блока, его нужно дополнить до соответствующего числа битов. С этим аспектом связано немало уязвимостей в реализациях TLS.

Мы рассмотрим два шифра — AES и ChaCha20 (второй — несколько более подробно), эти шифры закрывают основную часть TLS-трафика в современном вебе.

Шифр AES

AES — является современным блочным шифром, повсеместно используемым в TLS. Строго говоря, AES — это название стандарта шифрования США, сам шифр называется Rijndael (произносится: «рай’н-да’л»). Rijndael выиграл конкурс, проводившийся NIST, и стал стандартом (AES) в 2002 году (сам шифр опубликован в 1998). Шифр стандартизован для использования с 128-, 192-, 256-битным ключом и 128-битным блоком.

AES строится из «раундов» (rounds) — повторных выполнений некоторого набора операций по трансформации блока данных; каждое повторение использует свой ключ. Набор ключей генерируется (разворачивается) из исходного ключа, с использованием специального алгоритма. Так, в случае 128-битного ключа (AES-128), на выходе алгоритма разворачивания ключа — 176 байт или 11 128-битных ключей для повторных трансформаций, составляющих шифр. Разворачивание ключа в AES использует циклические сдвиги ключей, подстановки и операции умножения в конечном поле. Процедура разворачивания ключа является составной частью многих шифров, её надёжность и «необратимость» оказывают огромное влияние на стойкость шифра в целом.

Шифр AES оперирует матрицами (таблицами) размером 4х4 элемента. Такая матрица как раз соответствует 16 байтам 128-битного блока: один элемент — один байт. Матрица со значениями байтов называется состоянием шифра, одна трансформация (раунд) последовательно выполняет над матрицей и её элементами несколько преобразований, после чего к матрице применяется ключ данного раунда. Результат преобразований переходит в следующий раунд, где всё повторяется, но со следующим ключом.

Базовые преобразования в AES-128 (названия определены в стандарте):

  • SubBytes — это подстановка байтов, использующая таблицу подстановок (S-box): байт B заменяется на значение из таблицы, адресуемое значением B. Таблица, соответственно, состоит из 256 элементов. Эта же таблица подстановок применяется и в алгоритме разворачивания ключа. Подобные табличные подстановки используются во многих шифрах (например, в российском ГОСТ 34.12-2015 «Кузнечик»). Они имеют огромное значение для обеспечения стойкости шифра, в частности, к так называемому дифференциальному криптоанализу. Подстановки приводят к тому, что изменение значения одного бита незамедлительно влияет на несколько других, соответственно разрядности подстановки;
  • ShiftRows — сдвиг строк. Это преобразование заключается в циклическом сдвиге элементов строк матрицы состояния. При этом первая строка не сдвигается, а вторая, третья и четвёртая — сдвигаются, соответственно, на один, два, три элемента (справа налево). Данное преобразование перемешивает байты между столбцами, связывая шифр в единую схему — отсутствие ShiftRows привело бы к тому, что байты столбцов подвергались бы независимым преобразованиям MixColumns (следующее преобразование);
  • MixColumns — перемешивание элементов матрицы состояния (столбцами). В MixColumns над каждым столбцом матрицы состояний, включающем, соответственно, четыре элемента, проводится линейное преобразование. Столбец умножается на заданное значение, оба операнда в данном умножении рассматриваются как элементы конечного поля. Аналогичные преобразования, приведённые к матричной форме, также используются в большом количестве других шифров: ChaCha, Camellia, Twofish и пр. А операция умножения в конечном поле является основой операции аутентификации в режиме шифрования GCM (отдельно рассмотрен ниже, в специальном разделе).

После того, как выполнены три преобразования матрицы состояний, к ней применяется ключ действующего раунда. Операция называется AddRoundKey. Значение ключа разбивается на четыре блока по четыре байта и каждый из них применяется к столбцам матрицы состояний при помощи операции XOR. Операция AddRoundKey также выполняется перед первым раундом.

Далее операции шифра повторяются, но в AddRoundKey суммирование проводится со следующим ключом. Последний раунд не включает MixColumns. Для разной длины основного ключа, AES предусматривает разное число только что описанных трансформаций (раундов): для 128-битного ключа — 10 раундов; AES-192 — 12 раундов; AES-256 — 14.

Запись AES на псевдокоде выглядит следующим образом (из документа FIPS PUB 197):

Преобразования шифра обратимы, соответственно, можно построить алгоритм расшифрования, который будет восстанавливать открытый текст, при условии наличия ключа. Наличие режима расшифрования, как ни странно, требуется далеко не всегда. Так, современные режимы использования блочных шифров основаны только на зашифровании.

Если внимательно посмотреть на принципы построения операций AES, то окажется, что большая часть преобразований может быть предвычислена для всевозможных значений отдельных байтов (0-0xFF) и сохранена в таблицах, из которых значения будут извлекаться при работе алгоритма. Это основной программный метод оптимизации AES. Он же помогает составить общее представление о логике построения данного шифра: фактически, AES сводится к извлечению некоторой последовательности элементов матрицы возможных значений и сложении их при помощи XOR (то есть, по модулю 2) с входным блоком данных, при этом сама последовательность определяется используемым ключом, который разворачивается в набор ключей раундов.

Итак, блочный шифр ставит в соответствие блоку байтов открытого текста фиксированной длины и ключу шифрования — блок зашифрованных данных, той же длины. AES является самым часто используемым сейчас в TLS блочным шифром, фактически, это единственный распространённый безопасный вариант. Другие блочные шифры, с которыми можно столкнуться в практике TLS: 3DES (развитие устаревшего и нестойкого шифра DES, стандарта, предшествовавшего AES), Camellia (шифр восточного происхождения, включённый в ряд стандартов), а также ChaCha20.

Шифр ChaCha20

Рассмотренный выше шифр AES является блочным шифром. Ранее в TLS/SSL широко использовался потоковый шифр RC4. Из-за обнаруженных недостатков RC4 сейчас считается недостаточно стойким и не должен использоваться. Другой вариант блочного шифра, получивший широкое распространение, это 3DES — улучшенный шифр, построенный на базе DES. В качестве современной альтернативы AES активно продвигается шифр ChaCha20, разработанный Даниэлем Бернштейном. В частности, соответствующие шифронаборы использует Google в своих браузерах и на своих интернет-сервисах. Кроме того, сейчас ChaCha20 является единственным, кроме AES, вариантом шифра, который доступен в спецификации TLS 1.3.

В основе ChaCha20 (мы рассматриваем шифр в изложении RFC 7539) лежит конструкция, эквивалентная блочному шифру. Строго говоря, шифр называется ChaCha, а ChaCha20 — это версия, использующая 20 раундов. Согласно определению, этот шифр является потоковым, но можно рассматривать ChaCha20 и как блочный шифр с «встроенным» режимом счётчика (это будет очевидно из описания шифра ниже). По сравнению с AES, ChaCha20 оказывается несколько проще по алгоритмической структуре и составу операций. Он алгоритмически ближе к «лёгким» шифрам, предназначенным для микроконтроллеров и других «встроенных» применений (например, Speck), что позволяет получить достаточно быстрые, безопасные и легко портируемые чисто программные реализации на разном аппаратном обеспечении. AES, действительно, отличается тем, что реализация с высокой производительностью на архитектурах, не имеющих достаточного объёма памяти и ряда специальных команд, сталкивается с серьёзными трудностями. Однако основной причиной появления ChaCha20 в стандартах и программном обеспечении TLS является необходимость наличия какой-то сравнимой по качеству альтернативы AES, так как единственность шифра ставит под угрозу безопасность протокола: в случае, если в AES будут обнаружены критические дефекты, быстро перейти окажется не на что.

Операции, составляющие шифр ChaCha20, можно разбить на три части. Первая часть, базовая, это функция ChaCha для «четверть-раунда» (Quarter Round, далее QR). Название обусловлено тем, что в раундах шифра данная функция за один вызов преобразует четыре переменные состояния из шестнадцати (16/4 = 4), а в каждом раунде — данная функция вызывается восемь раз: по четыре раза в каждой из двух конфигураций (см. ниже).

Вторая часть — функция преобразования состояния (базового блока): эта функция (далее — BF, от Block Function) построена на последовательном преобразовании состояния шифра при помощи QR-функции. Начальное состояние формируется на основе ключа, вектора инициализации (уникального значения, nonce) и счётчика, а результатом является блок ключевого потока длинной в 64 байта.

Часть три — это, собственно, функция зашифрования: вызывает функцию шифрования блока (BF) с заданным ключом и nonce, последовательно увеличивая значения счётчика, а вычисляемый таким образом ключевой поток (гамму) суммирует с открытым текстом при помощи XOR. На вход поступают: 256-битный ключ (существуют версии шифра с другой разрядностью ключей, но для TLS рекомендован именно 256-битный); вектор инициализации (96 бит); начальное значение 32-битного счётчика; поток открытого текста. На выходе — шифротекст. Так как шифр представляет собой вариант режима счётчика с гаммированием, расшифрование производится аналогично (вместо открытого текста — шифротекст).

Состояние шифра. Все операции шифра происходят над таблицей, задающей его состояние (это напоминает AES). Таблица состоит из 16 32-битных значений (переменных состояния), которые нумеруются естественным образом — 0..15: Представление в виде таблицы из четырёх строк удобно по той причине, что элементарные преобразования шифра разделены на два типа: диагональные и вертикальные (по столбцу таблицы). Начальное состояние шифра определяется четвёркой констант, заданных в описании шифра (записываются в первую, верхнюю, строку таблицы), значением ключа (две следующих строки: 256/32 = 8), значением счётчика и nonce — последняя строка:

Функция «четверть-раунда» — QR. Функция преобразует четыре входных 32-битных значения (a, b, c, d) при помощи простейших базовых операций: сложение по модулю 2 32 , XOR, циклический битовый сдвиг. Используются следующие преобразования (+ — сложение; ⊕ — XOR; 32 ) с полученным, сумма — выводится как результат функции BF. Наборы (по номерам) переменных состояния шифра, используемые в каждом раунде:

Пример реализации функции BF на псевдокоде:

Таким образом, BF представляет собой блочный шифр, с разрядностью блока 512 бит — соответствует разрядности записи состояния шифра (16 * 32). Реализация, собственно, потокового шифрования ChaCha20 выполняется с применением режима счётчика: последовательно вызывается функция BF, с действующим ключом, действующим значением nonce и значением счётчика, которое для следующего вызова увеличивается (обычно, на единицу). Шифр инициализируется начальным состоянием, и это состояние последовательно изменяется с каждым вызовом BF. Результат работы BF каждый раз выдаёт 64 байта ключевого потока (гаммы), эти байты суммируются функцией зашифрования (XOR) с открытым текстом. Так как длина открытого текста может не быть кратной 64 байтам, для преобразования остатка, аналогично другим реализациям гаммирования в режиме счётчика, используется только часть финального блока ключевого потока ( =0), старшие биты остаются нетронутыми. GHASH основана на умножении значений (битовых блоков) в конечном поле (разрядность которого соответствует разрядности GCM — 128 бит).

Для работы GCM требуется инициализирующий вектор IV, этот вектор представляет собой число, используемое с данным ключом только один раз (то есть, это nonce) — строго говоря, стандарт требует, чтобы вероятность повторного использования на разных входных данных не превышала 2 -32 . Таким образом, на входе — вектор инициализации IV, секретный ключ K, открытый текст PT, подлежащий шифрованию, связанные данные A. На выходе — шифротекст C и код аутентификации AuthTag.

Перед расшифрованием должен быть проверен код аутентификации. Проверка возможна, так как алгоритм вычисления кода использует только открытую часть защищённого сообщения: шифротекст и связанные данные. Для проверки необходимо знать секретный ключ. Если проверка прошла успешно, то расшифрование данных производится аналогично режиму счётчика — генерируется ключевой поток и, при помощи XOR, вычисляется открытый текст. При этом код аутентификации проверяется до попытки расшифрования. Результатом работы функции расшифрования может быть либо открытый текст, либо символ FAIL (⊥), обозначающий невозможность расшифрования.

Режим GCM может быть использован с любым блочным шифром подходящей разрядности блока (128 бит, в действующем стандарте). Однако в современном Интернете этот режим в большинстве случаев встречается вместе с шифром AES, в составе шифронаборов AES_GCM. Необходимо ещё раз отметить, что в AES возможны разные длины ключей (128,192,256 бит), но разрядность блока всё равно остаётся равной 128 битам.

Защищённые записи TLS

Защищённая запись в TLS содержит полезные данные приложения, а также может содержать сообщения Handshake или Alert (в TLS 1.3). От других записей — защищённые отличаются кодом типа: 0x17 (23 в десятичной системе), ApplicationData. Полезные данные внутри записи зашифрованы действующим шифронабором, защищены отдельным кодом аутентификации (MAC) или AEAD-режимом. Часть параметров передаётся в открытом виде: тип записи, версия, длина данных и др. В TLS 1.3 подход к обработке защищённых записей сильно изменился. Так, открытый заголовок зафиксирован в качестве исторического: то есть, любая защищённая запись TLS 1.3 имеет значение поля версии 0x0303, что соответствует TLS 1.2, однако в самом протоколе 1.3 данное поле не используется. В TLS 1.3 все защищённые записи передаются с «историческим» кодом типа 0x17, при этом подлинный тип записи — содержится внутри защищённых данных.

Рассмотрим пример защищённой TLS-записи версии 1.3. Это запись, содержащая HTTP-запрос GET, адресованный хосту facebook.com и запрашивающий индексный документ. В TLS 1.3 структура защищённой записи, если рассматривать её в открытом виде, следующая: к байтам полезных данных приписан байт с кодом типа записи, следом за этим байтом могут идти нулевые байты дополнения. То есть, если после успешного расшифрования защищённых данных, последний байт оказывается нулевым, это означает, что использовано дополнение, и все нулевые байты в конце нужно отбросить. В случае, если дополнения нет — последний байт корректной записи не может быть нулевым, так как он содержит код типа записи.

Длины ключей и сочетание криптосистем

С шифронаборами в TLS связано несколько криптографических примитивов, к которым применимо понятие разрядности. Возьмём в качестве примера шифронабор TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 — здесь есть разрядность ключа RSA (рекомендуемое значение — 2048 бит или более); разрядность симметричного ключа AES (указано 128 бит) и, наименее важная, разрядность хеш-функции (256 бит). Есть ряд рекомендаций по выбору разрядности ключей для криптосистем в TLS. Так, максимальная степень защиты должна применяться к сеансовым данным, потому что ради их защиты TLS и используется. Эти данные защищает симметричный шифр. 256 бит для AES считаются достаточными. Большие длины ключей для добротного симметричного алгоритма не имеют никакого смысла. В качестве симметричного шифра может служить не только AES, но и CAMELLIA, и даже корейский шифр ARIA. Возможно и использование шифров ГОСТ для TLS, однако, к сожалению, с ними есть немалые проблемы в реализации программного обеспечения, кроме того, они не входят в типовой список IANA.

Криптосистемы с открытым ключом служат в TLS для аутентификации. Заметьте, что задача выработки общего секрета — эквивалентна аутентификации узла, с которым устанавливается соединение. Действительно, при использовании слабого ключа аутентификации, атакующая сторона может перехватить сессию, выдав себя за сервер (например). Однако на практике это означает проведение сложной активной атаки, которая представляет собой менее вероятную угрозу, чем простое прослушивание канала, от которого защищает симметричный шифр. Естественно, перехвативший сессию атакующий уже не будет испытывать проблем со взломом симметричного шифра. Тем не менее, защита процедуры аутентификации нередко перемещается на второе по важности место, после защиты потока данных.

Хорошим примером, почему это происходит, является следующее наблюдение (подсказанное Z.T. в комментариях на dxdt.ru): если вы используете нестойкий алгоритм для аутентификации узла, то, в обозримой перспективе, например, через десять лет, этот алгоритм может быть взломан; взломавшая алгоритм сторона получает возможность подделывать сессии, но как атаковать сессию десятилетней давности? Никак. А вот если взломан шифр, защищающий передаваемый трафик, то становится возможным прочитать трафик, записанный десять лет назад. В этом может быть смысл, так как трафик, возможно, содержит до сих пор актуальные сведения.

Весьма полезной практикой является разумное выравнивание стойкости используемых криптосистем. Например, в подавляющем большинстве случаев не имеет смысла использовать RSA-ключ длиной в 4096-бит, если ваш TLS-сервер всё ещё поддерживает SSLv3, а в качестве симметричного шифра применяет DES с 56-битным ключом.

Основные направления атак на TLS

TLS имеет дефекты на уровне протокола, но гораздо больше дефектов обнаруживается в его реализациях. Например, до сих пор можно нередко встретить поддержку заведомо нестойких, устаревших шифронаборов, использующих ключи длиной менее 128 бит. В 2020 году началась активная миграция в сторону стойких сочетаний ключей и шифров в области HTTPS. Но проблема устаревших и слабых криптографических параметров остаётся актуальной для «мобильных приложений» (приложений, предназначенных для смартфонов) и многих видов встроенного программного обеспечения, которое не обновляется. Встречается даже поддержка SSLv2, который давно не является хоть сколь-нибудь защищённым на практике. Использование устаревших протоколов и шифронаборов означает, что атакующий может провести понижение уровня защиты до шифра, который сможет взломать на лету, после чего подделает сообщения Finished, став, тем самым, посредником в сессии. (Посредник в TLS может прослушивать весь трафик.) Однако современные браузеры не позволяют использовать заведомо нестойкие сочетания криптосистем и не поддерживают устаревшие версии SSL/TLS, что сводит поверхность атаки к минимуму. Тем не менее, неверно было бы считать, что проблем здесь нет: существует большое число устаревших клиентских устройств, которые всё ещё поддерживают старые протоколы, по историческим причинам среди них немало важных узлов, это, например, домашние WiFi-роутеры.

Выше уже упоминалась необходимость дополнения данных при использовании блочных шифров, которая приводит к появлению нежелательных криптографических оракулов (такой оракул помогает «угадывать» секретные тексты). Есть целый класс оракулов, которые в англоязычной литературе называются Padding oracle, породивший несколько нашумевших атак. Одно из первых использований оракула, связанного с дополнением данных, относится к 2003 году. Атака, сконструированная Сержем Воденэ (Serge Vaudenay), основывалась на том факте, что реализация протокола SSL возвращала разные сообщения об ошибках в зависимости от того, удалось ли после расшифровки записи обнаружить корректное дополнение, но не совпал код аутентификации (MAC), или корректного дополнения данных обнаружить не удалось. Именно последствия этой атаки были устранены только спустя семь лет в веб-сервере IIS. Не останавливаясь на только что упомянутой атаке, рассмотрим подробнее это важное направление.

Код аутентификации представляет собой некоторое число, записанное в виде последовательности байтов, которые прикрепляются к защищаемым TLS данным. Принимающая сторона вычисляет значение кода аутентификации для принятых данных и сравнивает его с прикреплённым кодом. Если значения совпали, то делается вывод о неизменности данных, если не совпали, то данные должны быть отброшены. Дополнение сообщения (padding) также входит в набор данных, для которого осуществляется вычисление кода аутентификации. В добротной системе — внешняя сторона не должна иметь инструмента, который позволяет различить результаты обработки сообщений, кроме разделения на принятые и отвергнутые. Если же утекает дополнительная информация о внутреннем состоянии реализации криптосистемы, то оказывается возможным создание «оракула», который позволит при помощи простого перебора раскрыть либо какую-то часть защищаемого сообщения, либо восстановить его полностью.

В качестве иллюстрации, рассмотрим гипотетическую схему, которая концептуально схожа с реализациями, послужившими источником уязвимостей TLS/SSL — POODLE, BEAST, SWEET32 и др. Пусть в нашей теоретической криптосистеме блочный шифр работает в режиме CBC и используется следующий алгоритм дополнения до полного блока: в конец блока дописываются байты со значением, равным количеству байтов в дополнении. То есть, если требуется дописать три байта, то все три байта имеют значение 03. Если блок дополняется пятью байтами, то со значением 05, и так далее. Дополнение вносится в открытый текст, перед зашифрованием. На стороне получателя проверяются значения всех байтов дополнения, начиная с самого последнего байта (мы не рассматриваем способ получения принимающей стороной информации о длине дополнения).

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

Здесь C1, . Cn — блоки шифротекста; PTn — блоки открытого текста; IV — инициализирующий вектор; X — операция XOR; K — ключ расшифрования; D — алгоритм расшифрования (шифр). Дополнение содержится в последнем блоке, C3. Схема является обратной к приведённой в разделе «Режимы шифрования». Код аутентификации на схеме не показан — предположим, что код просто дописывается в конец сообщения.

Схема работы криптосистемы. Если сообщение, состоящее из набора блоков , где C3 содержит дополнение, успешно расшифровано, — то есть, после преобразования получено корректное дополнение, — криптосистема переходит к проверке кода аутентификации. Если в процессе расшифрования получено некорректное дополнение, то возвращается сообщение об ошибке расшифрования (присвоим этой ошибке обозначение PAD_ERROR), а код аутентификации не проверяется. (В случае, когда не совпал код аутентификации — возвращается другое сообщение об ошибке, пусть оно называется MAC_ERROR.) В данной схеме байты дополнения расположены в конце последнего блока. Предположим, что число этих байтов известно третьей стороне, которая проводит активную атаку. Пусть теперь дополнение состоит из одного байта, имеющего, соответственно, значение 01. Тогда последний блок открытого текста имеет следующую структуру: [01], где — последовательность байтов открытого текста, а [01] — байт дополнения до полной длины блока.

Заметим, что атакующей стороне известны все блоки шифротекста (они могут быть пассивно перехвачены из канала связи). Мы допускаем активную атаку, поэтому возможна произвольная замена блоков. Заменив блок C2 (см. схему) на произвольный блок V, а блок C3 — на некоторый полный блок шифротекста Cx, и отслеживая сообщения об ошибках, выдаваемые криптосистемой, атакующая сторона может добиться ситуации, когда результат расшифрования блока Cx и последующей операции XOR с блоком V (подменный блок) даст значение 01 в последнем байте. Это значение является результатом операции XOR последнего байта блока V и последнего байта расшифрованного блока Cx. Повторное выполнение XOR с байтом блока V и значением 01, восстанавливает последний байт из расшифрованного Cx. То есть, атакующий узнал значение последнего байта из подставленного в конец цепочки блока Cx, который может являться произвольным блоком с защищёнными данными — это ключевой момент атаки: значение последнего байта последнего блока (дополнение) и так было известно, однако замена блока на другой позволяет навязать криптосистеме задачу расшифрования блока, ни один байт которого не был известен атакующему. Пока значение последнего байта, полученного после расшифрования, не совпадало с ожидаемым значением дополнения — криптосистема выдавала ошибку PAD_ERROR, это позволяло атакующей стороне определить, что байт не угадан; как только значение совпало с 01 — криптосистема выдала ошибку MAC_ERROR, что явилось сигналом об успешном подборе. Такое поведение криптосистемы и является криптографическим оракулом. Так как целостность сообщения проверяется после того, как проведено расшифрование, становится возможной последовательная манипуляция блоками.

В описанной схеме, после того, как стал известен последний байт, можно, урезав фиктивное значение длины открытого текста, перейти к предпоследнему, и так далее: так как известно, какую маску нужно использовать, чтобы каждый следующий байт фиктивного дополнения соответствовал общему числу байтов в этом дополнении. Другими словами: атакующему теперь известно, какое значение имеет последний байт расшифрованного блока Cx, соответственно, он может так подобрать маску в виде подменного блока V, что результат XOR будет равен не 01, а 02, как требуется для дополнения из двух байтов; соответственно, это позволяет перейти к подбору следующего байта (предпоследнего). Манипулируя длиной сообщений и значениями блоков, третья сторона может последовательно раскрыть любое количество байтов секретного текста за обозримое время: так, очевидно, что один байт будет гарантированно раскрыт за 256 попыток (максимально), а хорошая практическая вероятность около 1/2 достигается в 128 попыток.

Схема атаки, для случая с одним байтом дополнения:

Если код аутентификации вообще не используется, то схема атаки не меняется. Однако при совпадении значения дополнения — расшифрованные данные окажутся мусорными, так как атакующая сторона проводит подмену блоков. Соответственно, приложение, использующее эти данные, может работать неверно. Тем не менее, факт отсутствия ошибки расшифрования послужит сигналом об успешном результате обработки очередного блока.

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

Рассмотрим теперь как работает конкретная атака на TLS/SSL, использующая уязвимость POODLE в SSLv3 (а также в некоторых реализациях TLS 1.0). Эта уязвимость построена на описанном только что «оракуле дополнения», однако схема отличается: предполагается, что атакующий может не только переставлять блоки внутри защищённого сообщения, но и изменять часть открытого текста.

Пусть атака проводится на HTTPS-соединение, а атакующий также может отправлять HTTP-запросы из браузера пользователя (например, заманив пользователя на специально подготовленную страницу, что несложно сделать, если уже есть возможность модификации трафика). Целью атакующего является получение содержимого файлов cookie, адресованных защищённому веб-ресурсу. В этом случае, POST-запросу, отправляемому на адрес защищённого HTTPS-ресурса, — работающего по протоколу SSLv3 с шифронабором, использующим режим CBC, — будет соответствовать несколько блоков шифротекста. Cookie-файл передаётся в этой же цепочке блоков, и, согласно протоколу HTTP, следует после адреса документа (path), на который отправляется запрос POST (тут возможны отличия в деталях, но расположение блока, который интересует атакующего, так или иначе известно). Идея состоит в том, чтобы, манипулируя длинной URL в POST-запросе, сдвигать значение Cookie так, чтобы его байты последовательно оказывались на последнем месте в одном из блоков цепочки.

Мастер Йода рекомендует:  Множественные уязвимости в PHP 4.4.0

В SSLv3 фрагмент записи, содержащий код аутентификации сообщения (MAC) предшествует дополнению. А само дополнение может представлять собой один полный блок, при этом последний байт дополнения содержит значение, равное числу байтов дополнения. Шифротексты последовательных сообщений, содержащих генерируемые клиентом HTTP-запросы, будут различаться, как того требует протокол. В рамках атаки, блок, содержащий cookie-файл, переставляется в конец записи, на место блока с дополнением. POODLE использует в качестве оракула только последний байт, то есть — байт, в котором записана длина дополнения. Сервер, при попытке обработать данные, будет возвращать ошибку SSL в случае, если значение последнего байта блока после расшифрования не совпало с корректным (ожидаемым) значением дополнения. Если значения совпали, то сервер корректно обработает HTTP-запрос. Перебор возможен потому, что при каждом следующем запросе, с тем же открытым текстом, блоки шифротекста будут иметь другое значение (это одно из основных свойств TLS, рассмотренное выше). Для проверки следующего байта — атакующий модифицирует открытый текст, — то есть, HTTP-запрос, — таким образом, что значение cookie-файла смещается на один байт вправо (к концу записи), и на границе блока оказывается следующий байт cookie.

Видимое «снаружи» различное поведение программной реализации TLS в зависимости от того, были в TLS-записи обнаружены корректные дополнение и MAC или некорректные, — традиционный фундамент для атак, актуальный до сих пор. Эти атаки привели к тому, что сейчас не рекомендуется поддержка SSLv3 (и, естественно, более ранних версий). Шифры, работающие в режиме GCM — а именно, AES, — не используют уязвимого дополнения блоков, соответственно, ликвидируют основу для возникновения оракулов такого типа (но, конечно, не избавляют от возможных оракулов полностью).

Атака под названием Sweet32 — относится к классу атак, использующих фундаментальные особенности протокола, а не уязвимости конкретных реализаций. Sweet32 также требует работы в режиме CBC, но при этом зависит от шифра — он должен использовать 64-битные блоки (откуда название: 32=64/2). Атака основана на достаточно простом, но поэтому весьма универсальном, свойстве: так как результат работы добротного шифра должен быть вычислительно неотличим от случайного результата, в криптосистеме в какой-то момент обязательно произойдёт коллизия — возникнут два блока с одинаковыми значениями. Из-за парадокса дней рождения, вероятность такой коллизии для шифров с малой разрядностью блока становится достаточно высокой на объёмах данных, которые, по современным меркам Интернета, не являются недостижимыми. Так, для 64-битного блока граница находится около 32 гигабайт. Sweet32 и подобные атаки не требуют наличия каких-то дефектов реализации или возникновения плохо предсказуемых ошибок в криптосистеме. Причина, по которой возможны такие атаки, архитектурная.

Рассмотрим блочный шифр с 64-битным блоком, работающий в режиме CBC, с одним и тем же значением ключа. Коллизия блоков шифротекста означает, что результатом работы шифра оказались два блока с одинаковым значением, присвоим им номера i и k: CTi == CTk. Соответственно, так как ключ не изменялся, а шифр эквивалентен перестановке битов, два блока, поступившие на вход шифра, также равны между собой: INi == INk (обозначим эти блоки как IN, поскольку они, согласно режиму шифрования, не являются открытым текстом в контексте криптосистемы). Шифр работает в режиме CBC, это означает, что на вход шифра (блоки IN) поступали результаты суммирования предыдущего блока шифротекста (CTi-1, CTk-1) c соответствующими блоками открытого текста (PTi, PTk), таким образом: CTi-1⊕PTi == CTk-1⊕PTk, следовательно, по свойствам XOR: PTk⊕PTi == CTk-1⊕CTi-1. Оба блока CTk-1 и CTi-1 — известны, так как они передаются в открытом виде, поэтому прослушивающая канал сторона может вычислить значение XOR от двух блоков открытого текста. Это и составляет утечку. С вероятностью около 1/2 коллизия блоков произойдёт на выборке в 2 n/2 = 2 32 блоков (n — разрядность блока, 64 бита).

Если атакующему известно значение XOR от двух блоков открытого текста (S), а также значение одного из этих блоков, то возможно вычислить второй (PT1⊕S == PT2). В случае с HTTPS некоторые фрагменты открытого текста, действительно, известны заранее, из свойств протокола HTTP и метаданных, например: URL, некоторые файлы Cookie, заголовки запроса, части веб-страницы (её можно получить с сервера) и так далее. Авторы практической атаки Sweet32 использовали для генерации трафика Javascript-код, отправлявший большое число HTTP-запросов с известной частью открытого текста. В качестве транспорта использовалось TLS-соединение с 64-битным 3DES (шифр, основанный на стандарте DES). Целью служили cookie-файлы, дописываемые браузером (это типовой метод демонстрации осуществимости атак на HTTPS). Первая коллизия была зафиксирована при числе переданных блоков 2 31.3 , а полное раскрытие 16-байтного секрета потребовало 705 гигабайт трафика.

Данные объёмы трафика достаточно велики, несмотря на то что являются вполне достижимыми на практике. Кроме того, применительно к TLS, требуется, чтобы весь трафик передавался в рамках одного контекста сессии, так как замена ключей и векторов инициализации приведёт к тому, что атака не сработает из-за отсутствия коллизий. При этом, 705 гигабайт соответствует, приблизительно, 2 36,46 , что превышает порог 2 n/2 == 2 32 блоков, после которого должна была бы последовать замена ключей. Для шифров с большей разрядностью блока, например, AES-128, данная атака оказывается ограничена только тем фактом, что резко возрастает требуемое для достижения практической вероятности возникновения коллизии число блоков, что, естественно, не отменяет необходимости периодической замены ключей.

В описании атак, основанных на подмене блоков и байтов дополнения, отмечено, что сигналом о «правильной» интерпретации байтов дополнения могут служить различные коды ошибок, возвращаемые реализацией TLS, либо сам факт успешной обработки запроса протокола, находящегося уровнем выше TLS (HTTPS в случае с POODLE). Однако атакующий может извлечь полезную информацию и путём анализа времени обработки данных на стороне реализации TLS. На таком побочном канале утечки работает атака Lucky13. Основная идея Lucky13 состоит в отправке на сервер специальным образом подготовленных TLS-записей, содержащих тщательно подобранные дефекты. Обработка этих записей на сервере и, в частности, вычисление кода аутентификации, приводит к тому, что сообщение об ошибке поступает с различной задержкой по времени. То есть, уязвимые реализации используют один универсальный код ошибки (следовательно, не содержат оракулов, подобных описанным выше), но время генерации этого кода коррелирует с данными открытого текста, расположенного внутри TLS-записей. Построив статистику времени обработки запросов, которые были специально подготовлены, можно вычислить открытый текст. То есть, в данном случае, криптографический оракул «отвечает» атакующей стороне посредством изменения времени выполнения тех или иных операций на сервере. Подобные побочные каналы утечки являются одними из самых сложных, как в плане выявления, так и в плане противодействия.

В 2015 году появилась атака Logjam, связанная с использованием устаревших шифронаборов, а именно с протоколом Диффи-Хеллмана в так называемом «экспортном» варианте. «Экспортные» шифры относятся к первому периоду криптовойн, к 90-м годам 20 века, когда был запрещён экспорт стойкой криптографии за пределы США, а вместо стойкой — экспортировались заведомо нестойкие криптосистемы. Logjam не использует оракулов, но позволяет провести понижение уровня секретности, навязав клиенту и серверу нестойкий вариант DH, на группе малой разрядности (512 бит). Это возможно из-за архитектурного недостатка протокола: предложенные клиентом шифронаборы никак не удостоверяются, при этом клиент принимает любые параметры DH, переданные сервером, если только может их обработать. Используя сравнительно небольшие компьютерные мощности, для групп DH малой разрядности (1024 бита и меньше) возможно провести предварительные вычисления арифметической структуры, которые позволят в дальнейшем вычислять дискретный логарифм, фактически, в режиме реального времени. Соответственно, перехватывающий узел может раскрыть сеансовый ключ. (В распространённых браузерах проблема была исправлена летом 2015 года.)

Logjam использует следующую архитектурную особенность TLS: описанный выше процесс установления соединения (Handshake) в TLS версий ниже 1.3 подразумевает, что фактическая аутентификация клиентом серверных параметров криптосистемы (выбранный шифронабор и т.д.) проводится лишь в самом конце. Основой такой аутентификации является сообщение Finished, которое передаётся в защищённом виде и должно подтверждать соответствие выбранных параметров состоянию сервера. При этом дополнительной аутентификации сообщений клиента, на начальном этапе, не предусмотрено. Атакующая сторона может осуществить атаку «Человек посередине» и, например, подменить в самом начале соединения клиентское сообщение ClientHello, содержащее идентификатор выбранного сервером шифронабора.

На первый взгляд, подобные подмены не могут достичь успеха: во-первых, сервер также получает Finished от клиента, а это сообщение содержит значение хеш-функции от всех предыдущих сообщений и удостоверено кодом аутентификации; во-вторых, ответное сообщение ServerKeyExchange содержит подпись сервера, которая может быть проверена клиентом, а перехватывающий узел не сможет поменять сессионные параметры так или иначе. Но оказывается, что как раз здесь и скрывается возможность для атаки. Дело в том, что ServerKeyExchange никак не привязано к выбранному шифронабору, это сообщение содержит лишь параметры; в случае классического протокола Диффи-Хеллмана — это задающий группу модуль и открытый ключ сервера. Ключевой момент Logjam в том, что для клиента все параметры Диффи-Хеллмана в ServerKeyExchange выглядят одинаково. То есть, достаточно, чтобы сервер выбрал шифронабор с DHE (сеансовый вариант Диффи-Хеллмана) и передал любые подходящие для атаки параметры в ServerKeyExchange.

Пусть сервер поддерживает «экспортные» варианты протокола Диффи-Хеллмана: DHE_EXPORT. Предположим, что активно перехватывающий соединение узел подменяет исходное сообщение клиента ClientHello и заменяет список шифронаборов на список, разрешающий только варианты с DHE_EXPORT. В ответ, помимо ServerHello, сервер отправляет ServerKeyExchange, содержащий параметры DHE в «экспортном» варианте, то есть, с модулем разрядностью в 512 бит. Параметры при этом подписаны серверным секретным ключом. Узел, проводящий атаку, заменяет в ServerHello выбранный шифронабор на любой вариант с DHE (уже не с «экспортным»), а на основании открытого ключа в ServerKeyExchange и параметров из ClientHello и ServerHello вычисляет сеансовый ключ. Очевидно, что, используя данный ключ, перехватывающий узел сможет подделать все прочие сообщения (кроме ServerKeyExchange). Клиент, получив в поддельном сообщении ServerHello указание на шифронабор с DHE, принимает параметры из ServerKeyExchange, так как это подлинные параметры, подписанные серверным ключом — единственная их особенность состоит в том, что используется модуль малой разрядности.

Для того, чтобы данная атака сработала, необходима поддержка DHE_EXPORT на сервере и поддержка групп DH малой разрядности клиентом. Ни то, ни другое — не является необходимым для нормальной работы TLS в современных условиях.

Другим примером атаки, использующей устаревшие экспортные ограничения против современных версий TLS, является DROWN, опубликованная в 2015-2020 годах (CVE-2020-0800). DROWN является развитием атаки Блейхенбахера (Daniel Bleichenbacher) и использует соединения по морально устаревшему протоколу SSLv2 для расшифрования сеансовых ключей, которые передаются в сессиях TLS. Для того, чтобы атака стала возможной, необходимо наличие SSLv2-сервера, использующего общий с атакуемым TLS-сервером секретный ключ RSA. Такая ситуация вполне возможна: например, один и тот же TLS-сертификат может быть установлен и на веб-сервере, и на почтовом сервере, а это, в свою очередь, требует использования общего секретного ключа. Со стороны TLS-сервера не требуется наличие каких-то уязвимостей: атака работает против корректной реализации протокола TLS. Единственное существенное ограничение: в рамках атакуемой TLS-сессии клиент и сервер должны использовать для передачи сеансового секрета статический вариант с шифрованием RSA (как описано выше, такой способ не рекомендуется, но, тем не менее, до сих пор достаточно широко используется, в том числе, в банковских системах дистанционного обслуживания, где такой выбор обусловлен желанием инспектировать трафик при помощи относительно простых аппаратно-программных средств и методов).

Часть атаки DROWN в отношении TLS-сервера может быть реализована пассивно: то есть, только с использованием записанного трафика (а именно — TLS Handshake). Однако для завершения атаки потребуется активный доступ к связанному SSLv2-серверу — отправка запросов, имитирующих установление соединения SSLv2.

Атака основана на особенностях установления соединения SSLv2, в варианте, использующем те же самые «экспортные» шифронаборы, которые упоминались выше. Кроме того, ключевую роль играет вариант дополнения блока данных RSA, что совпадает с описанными в начале этого раздела криптографическими оракулами, возникающими при использовании симметричных шифров и дополнения (несмотря на то, что RSA — не является симметричным шифром). Установление соединения в SSLv2 существенно отличается от TLS (как протокол, SSLv2 представляет скорее исторический интерес, поэтому мы не рассматривали его в рамках настоящего описания; кроме того, формально, SSLv2 — проприетарная технология). В SSLv2, клиент в самом начале сеанса отправляет на сервер секрет, зашифрованный с использованием открытого RSA-ключа сервера. Для выполнения экспортных ограничений предусмотрен режим, когда часть сеансового секрета передаётся в открытом виде, и только часть, соответствующая по разрядности требуемому ограничению (40 бит), зашифрована RSA. Современные вычислительные мощности, в случае с анализом «экспортного» SSLv2, позволяют очень быстро перебрать 2 40 вариантов (на практике, для DROWN, пространство перебора с целью расшифрования сессии TLS будет другим, авторы атаки приводят оценку приблизительно в 2 50 операций, что, впрочем, не является препятствием: на специализированном кластере среднего уровня — вычисления заняли менее суток). Кроме того, формат сообщений SSLv2 предписывает при подготовке сообщения к зашифрованию RSA использовать дополнение определённого формата, особенности обработки этого дополнения на серверной стороне позволяют построить криптографический оракул, делающий возможным расшифрование секрета из соответствующего TLS-соединения.

Атака проводится в несколько этапов. На первом этапе атакующий пассивно записывает TLS-трафик: предмет записи — начало TLS-сессий, использующее статический обмен RSA для передачи сеансового секрета. Именно TLS-сообщение, содержащее Premaster Secret, является целью атаки. Раскрыв информацию из данного сообщения, атакующий может вычислить сеансовые ключи и расшифровать весь записанный трафик сессии. На втором этапе — записанные сообщения с Premaster Secret преобразуются к виду, пригодному для отправки в качестве зашифрованного клиентского ключа в рамках SSLv2-сессии. На третьем этапе атакующий проводит попытки установления соединения с SSLv2-сервером, используя ответы сервера (требуется несколько десятков тысяч запросов) для расшифрования одного из подходящих Premaster Secret. Такое расшифрование состоит из набора шагов, в которых атакующий последовательно, на основе ответов сервера, модифицирует сообщение для следующего запроса.

Шифрование RSA — это всего лишь возведение открытого текста в степень со значением шифрующей экспоненты, выполненное по модулю ключа RSA (C = m e mod N — алгоритм описан выше). Дополнение, предписываемое используемым форматом, требует размещения в начале сообщения двух байтов со значениями 00 02. Если результат расшифрования не совпал с данным шаблоном, то сервер может выдать сообщение об ошибке, либо другим способом раскрыть информацию о неудаче. На этом наблюдении и основана исходная атака Блейхенбахера: известное значение двух первых байтов позволяет установить интервал, в котором лежит открытый текст (открытый текст — это число, полученное в результате возведения в степень mod N). Далее, умножая шифротекст на некоторое выбранное значение, воспользовавшись тем, что (C*K e ) = (m*K) e mod N, где m — открытый текст, и отправляя результат для расшифрования на сервер, атакующий может последовательно уменьшать интервал возможных значений шифротекста, с тем, чтобы в итоге получить единственное подходящее значение m. Использование в DROWN SSLv2 и экспортных ограничений, требующих короткого шифротекста (40 бит), позволяет существенно оптимизировать алгоритм Блейхенбахера, сократив число запросов к SSLv2-серверу до практически достижимых значений.

Для большого класса добротных, стойких криптосистем, широко используемых сейчас в TLS на практике, возможно восстановление сеансового ключа из записанного трафика, при условии, что атакующая сторона имеет в своём распоряжении секретный серверный ключ (ключ из пары, открытая часть которой указывается в сертификате сервера). Это означает, что получив секретный ключ сервера (не сеансовый!), кто-то может расшифровать накопленные ранее записи TLS-сеансов между клиентом и сервером. Упомянутый ключ может быть раскрыт разными способами: например, его можно скопировать с сервера, если есть доступ, или он может просто оказаться нестойким (такое случается не так редко, как можно подумать). Сгенерированный по протоколу Диффи-Хеллмана сеансовый ключ также может стать известен злоумышленнику: либо в результате активной атаки на уровне канала (как Logjam), либо в результате получения доступа к серверу, где сеансовый ключ может сохраняться достаточно долго, и не обязательно в защищённом хранилище. Очевидно, что если атакующая сторона получила соответствующий сеансовый ключ, то она может раскрыть TLS-трафик. Секретный серверный ключ или TLS-сертификат для этого не требуются.

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

Однако валидный TLS-сертификат, выпущенный для атакуемого домена, позволяет провести незаметную для пользователя атаку типа «Человек посередине». Для этого требуется, чтобы между атакуемым пользователем и сервером существовал управляемый атакующим узел, активно перехватывающий трафик. Этот узел выдаёт себя пользователю за легитимный сервер, предъявляя тот самый валидный сертификат. Пассивное прослушивание канала не позволяет раскрыть TLS-трафик подобным образом – наличие сертификата или секретных ключей УЦ никак тут не помогает.

Перехват TLS-соединения может быть автоматизирован – существуют специальные узлы-прокси (SSL-прокси), которые выполняют такой перехват на лету, в том числе, генерируя нужные сертификаты. В такой прокси должен быть загружен сертификат и секретный ключ, позволяющие подписывать другие сертификаты (например, годится промежуточный сертификат УЦ, выпущенный для этих целей и соответствующий ему секретный ключ). Такой «человек посередине» не работает при наличии некоторых дополнительных мер: например, установление TLS-соединения требует взаимной аутентификации, и перехватывающему узлу недоступен клиентский секретный ключ (либо ключи УЦ, удостоверяющего клиентский ключ); или – пользовательский браузер ведёт реестр отпечатков открытых ключей сервера, которым он доверяет; или – пользователь применяет дополнительные источники сведений о разрешённых ключах и сертификатах, которые недоступны для подмены на перехватывающем узле (таким источником может служить DNS, либо другая база данных).

На практике, для массовых сервисов, возникают другие технические направления для атак, напрямую не связанные с какими-то особенностями TLS.

Так, массовые онлайн-сервисы используют SSL termination: то есть, пользовательский TLS-трафик в зашифрованном виде доходит только до пограничного прокси, где благополучно транслируется в открытый протокол, обычно это HTTP, сответствующий HTTPS, который дальше ходит по внутренним (в логическом, а не техническом смысле) сетям сервиса в открытом виде. Тотальный HTTPS, с ростом числа клиентов, быстро превращается в неподъёмную, плохо масштабируемую технологию, поэтому SSL termination является весьма распространённым решением. Если система инспекции трафика (DPI) находится внутри сетей сервиса, за таким пограничным SSL-прокси, то никакой TLS ей не помешает. Именно так получают доступ к данным платёжных систем и веб-почты специальные службы, располагающие, на законных основаниях, собственным оборудованием DPI за пограничными прокси.

Сеансовые ключи могут экспортироваться сервером наружу, в другие системы, которые, например, осуществляют балансировку нагрузки или «очистку» трафика. В некоторых случаях вообще используются услуги третьей стороны для организации TLS-соединения. Кроме того, внутренний трафик распределённых сервисов с лёгкостью ходит между узлами и дата-центрами по арендованным у крупных операторов каналам связи в открытом виде, такой трафик может прослушиваться, хотя для пользователя он выглядит как TLS-соединение.

Иными словами: TLS не предоставляет абсолютной защиты, но в подавляющем большинстве сценариев использования Интернета этот протокол делает обмен информацией хорошо защищённым; для повышения скрытности и безопасности, если такое требуется, TLS должен использоваться совместно с другими решениями.

Приложение А. Конечные поля и эллиптические кривые в криптографии

В этом приложении в довольно вольном формате рассмотрены элементарные математические основы, на которых строятся эллиптические криптосистемы, упоминающиеся в основном тексте.

Для начала потребуется базовый инструментарий, прежде всего — конечное множество c дополнительной стрктурой, которая определяется парой операций над элементами множества, обладающих свойствами «обычных» сложения и умножения. Мы собираемся решать в этом множестве некоторые уравнения, поэтому важно, чтобы результат применения операций не выходил за пределы данного множества. Не вдаваясь в алгебраические детали, достаточно вспомнить про деление с остатком (для целых чисел) — оно как раз позволяет построить нужную структуру. Для примера, будем делить на 17: всякое целое число можно отождествить с остатком от его деления на 17. У нас получится множество из семнадцати элементов, соответствующих числам от 0 до 16 (хотя мы взяли систему из наименьших неотрицательных вычетов, примем, что это просто остатки). Можно сказать, что здесь сохранились привычные операции сложения и умножения. Это легко проверяется: 11 + 13 = 7, где 7 — остаток, получившийся при делении 24 на 17; 6*9 = 3, так как 54 = 3*17 + 3. В нашей структуре можно вычитать и делить, то есть, по-научному, она образует поле, однако и вычитание, и деление — несколько отличаются от «обычных»; эти детали мы сейчас не станем рассматривать, но полем всё же получившийся объект называть будем. Точнее — конечным полем, потому что в нём конечное число элементов.

Описанный только что пример вовсе не является каким-то чрезмерным упрощением: конкретные реализации ECDSA именно с такими полями («остатками от деления») и работают, но в качестве основы берётся не 17 или 19, а очень большое простое число (это число, задающее поле, называют модулем; чтобы «по остаткам» получилось именно поле, модуль обязательно должен быть простым числом; в криптографии используются и другие поля, практические воплощения которых строятся «на многочленах», здесь самое заметное отличие будет в количестве элементов; мы, опять же, пропускаем эти детали, иначе можно уйти далеко в сторону).

Для нашей задачи принципиально важен только один момент: можно простым способом, позволяющим проводить эффективные вычисления, построить конечное множество, на котором действуют привычные операции сложения и умножения. Конечность здесь имеет прикладное значение — мы собираемся «считать на компьютере» и нам потребуется эффективный алгоритм, позволяющий за конечное число шагов построить любой элемент нашего множества из других его элементов. Вот теперь можно переходить к кривым.

Рассмотрим формулу 2x + 3 = y. Можно ли найти в нашем множестве остатков от деления на 17, с введённой структурой сложения и умножения, пары элементов (x,y), удовлетворяющие этой формуле? Да, это легко сделать: 1 и 5, 3 и 9. Формулу можно выбрать посложнее. Эллиптической кривой соответствует y 2 = x 3 + ax + b, где a, b — коэффициенты, которые определяют конкретный экземпляр кривой; a и b — элементы выбранного поля, на которые накладываются дополнительные ограничения, которые мы пропустим. В формуле используется возведение в степень. Под этой операцией понимается последовательное умножение элемента на себя, то есть ничего нового здесь не написано, это всё привычные операции, но результат берётся по модулю некоторого числа.

Теперь, взяв подходящую (см. выше: y 2 = x 3 + ax + b) формулу, мы можем выбрать в нашем множестве со структурой пары элементов, соответствующие формуле. Множество таких пар и будет в нашем случае эллиптической кривой, каким бы странным это не казалось. Да, это не совсем кривая в «бытовом» понимании, но это не важно: в контексте рассматриваемой криптосистемы важны именно пары значений, задаваемые уравнением кривой (мы называем его просто формулой). Обычно, таких пар в правильно выбранном поле более чем достаточно. Пары элементов (x,y) называют точками эллиптической кривой. Это просто терминологическое соглашение. Конечно, за соглашением кроется глубоко теоретическая математика, но она, тем не менее, напрямую в прикладной криптографии не используется, в том смысле, что вовсе не обязательно представлять себе эллиптическую кривую над конечным полем как некую «линию» (но можно попробовать и сделать шаг на территорию геометрии над конечными полями; вообще, с точки зрения чистой математики, эллиптическая кривая объект гораздо более общий, чем обозначено в нашем изложении, да и строится он другими способами).

Пусть у нас есть ещё пара формул, которые позволяют по кортежу значений, состоящему из двух пар (x,y) и (u,v), вычислить другую пару (k,l). Важное свойство: новая пара (k,l) тоже удовлетворяет уравнению кривой. То есть, мы берём две точки, вспоминаем, что каждая из них — это пара элементов поля, связанных между собой уравнением кривой, и применяем к этим элементам формулу, которая сопоставляет двум элементам — третий. Обозначим пары элементов буквами �� и ��, (x,y)=��, (u,v)=��. Примем, что упомянутые формулы — это функции F1(��,��) и F2(��,��) от пар элементов нашего множества (поля). Тогда, если у нас на входе две точки (x,y)=�� и (u,v)=��, то, применив функции, мы получаем третью точку (F1(��,��), F2(��,��)), то есть (k,l), где k,l есть значения, элементы поля, вычисляемые по некоторым формулам. Ключевое свойство этих формул в том, что получившаяся пара элементов (k,l) удовлетворяет нашему уравнению кривой.

Только что описанные формулы переводят точки кривой в точки кривой, то есть задают некоторую операцию на множестве этих точек (или, эквивалентно, на _выбранных_ парах элементов нашего поля). Обозначим эту операцию символом «∘». Внутри нашего множества со структурой появилось подмножество пар элементов, соответствующих точкам кривой. Операция ��∘�� = �� задаёт (k,l) — третью пару элементов, или третью точку, соответствующую двум другим. Формулы, преобразующие элементы, должны быть устроены таким образом, чтобы соответствующая им операция обладала определёнными свойствами. Например, она коммутативна и ассоциативна; более того, множество пар с данной операцией образует группу, то есть операция однозначна, существует «нулевая» точка, которая описана ниже, и обратные элементы (если подходить совсем строго, то для получения обратного элемента нужна вторая операция, но она у нас тоже есть). Именно поэтому говорят о группе точек эллиптической кривой. Применение операции к парам элементов, соответствующих точкам кривой, не выводит нас за пределы подмножества пар, которые мы назвали точками. Данную операцию принято называть сложением точек, но это, опять же, всего лишь удобное терминологическое соглашение.

Итак, мы использовали пары элементов поля для построения группы точек эллиптической кривой над конечным полем. То есть, в основе этой группы — два экземпляра поля (потому что у нас пары значений).

Операцию сложения точек можно применять к одной и той же точке. (Строго говоря, сами формулы, задающие сложение, при этом могут быть разными, то есть, различаются формулы для двух различных точек и формулы для сложения одной точки с самой собой, для удвоения точки. Впрочем, можно так подобрать структуры, что формулы окажутся одинаковыми, но это технические детали.) Итак, можно складывать точку саму с собой. Вспомним, что наше исходное множество — конечное. Поэтому множество пар элементов, соответствующих структуре точек эллиптической кривой, тоже конечно. Это означает, что на каком-то шаге последовательное сложение точки с самой собой даст в результате эту же точку (мы как бы вернёмся в начало; можно было бы предположить, что «зацикливание» произойдёт на какой-то другой точке, а не на начальной, но это не так, ввиду свойств операции сложения точек).

Данное наблюдение непосредственно связано с особой «нулевой» точкой ��, главное свойство которой совпадает со свойствами привычного нуля по сложению — сумма любой точки �� с «нулевой» даёт эту же точку ��: ��∘�� = ��∘�� = ��. Возникает вопрос о координатах, то есть, о паре элементов поля, которые соответствуют точке ��. Чтобы не усложнять изложение, примем, что «нулевой» точке соответствует пустая пара элементов нашего множества. Точки, которые в сумме дают точку �� — называют обратными (аналогом этого, например, для целых чисел по сложению, является число A и его «минус», то есть -A, так как A + (-A) = 0). Если говорить о парах элементов, то для взаимно обратных точек, сумма которых даст ��, один элемент будет одинаковым, а два других — обратными. Например: (x, y) и (x, -y). Если последовательно складывать какую-либо точку с собой, то в какой-то момент обязательно получим точку ��.

Только что описанная структура является чисто алгебраическим воплощением метода секущих и касательных, которым обычно геометрически иллюстрируют механизм сложения точек на эллиптической кривой, в её вещественной интерпретации: секущая проходит через две точки, которые суммируются, а касательная — используется при удвоении точки. Очень известная картинка. При этом на иллюстрациях рисуют кривую, обладающую нужной непрерывностью. Уравнения секущих и касательных служат основой для построения формул сложения точек. Элементы, входящие в пары, называют координатами.

Вернёмся к сложению точки с ней самой. ��∘�� можно переписать как 2��, отразив тем самым, что мы сложили две «копии» точки. Тогда 5�� = ��∘��∘��∘��∘��, и так далее. Запись очень похожа на умножение, но это не умножение точек («умножения» для точек у нас вообще нет — мы его не определили), поэтому говорят об умножении точки на скаляр. Скаляром здесь называют целое число, соответствующее количеству «копий» точки. Умножение на скаляр (n��) имеет свои свойства. Например, в записи 5�� можно представить число 5 в виде суммы 3+2, получим (3+2)�� — такая запись соответствует тому, что в «разложение» суммы точек как бы добавили скобки, вот так: (��∘��∘��)∘(��∘��), или 3��∘2�� . Здесь необходимо понимать, что используются два различных «сложения»: сложение в целых числах «+», и сложение точек кривой («∘»). (В алгебре такая структура называется модулем, да, тоже модулем — см. первый абзац, — и встречается сплошь и рядом, в том числе, и под другими названиями.)

По свойствам, умножение на скаляр совпадает с возведением в степень, операции отличаются только способом записи. Именно поэтому в описаниях эллиптических криптосистем фигурируют «логарифмы» — так сложилось исторически. Возможность переписать ��∘��∘��∘�� как 2��∘2��, то есть, как удвоение точки 2�� — даёт необходимый механизм, позволяющий быстрее умножать точки на скаляр, если известно значение скаляра. Только благодаря этому и работают на практике криптосистемы, основанные на дискретном логарифмировании в группе точек эллиптической кривой. Это весьма общее свойство, которое необходимо для построения многих других практически полезных криптосистем. Только что описанное умножение точки на скаляр — прямо используется в протоколе Диффи-Хеллмана на эллиптических кривых (см. основной текст). Стойкость протокола основана на том, что вычислительно сложной является обратная задача: по известным точкам �� = n��, найти n.

Что такое tls-рукопожатие? Как расшифровывается tls?

TLS ставит своей целью создание между двумя узлами сети защищённого от прослушивания и подмены информации канала связи, пригодного для передачи произвольных данных в обоих направлениях, а также проверку того, что обмен данными происходит между именно теми узлами, для которых канал и планировался. Эти задачи называются, соответственно, обеспечением конфиденциальности, целостности и подлинности соединения (аутентификации). Из фундаментальных задач защиты информации, TLS не охватывает только одну: обеспечение доступности информации — и эта задача находится далеко за рамками данного протокола.

TLS Handshake (Handshake— Установление соединения) иногда в современных русскоязычных статьях это называют «рукопожатием», что является прямым, и не очень удачным, переводом английского термина.

Выполнение tsl рукопожатия — что это такое?

Выполнение tsl рукопожатия — что это такое?

Опишите причину своей жалобы

Протокол TSL используется для защищенной передачи данных.

Handshake или TLS-рукопожатие используется при установлении соединения между клиентом и сервером для последующей передачи данных.

В процессе TLS-рукопожатия передаются параметры связи, которые принято называть криптографическим контекстом.

Согласование параметров происходит благодаря обмену handshake-сообщениями. В сообщениях содержится информация о способах аутентификации, согласовании ключей и другие параметры связи. Каждое такое сообщение содержит заголовок, состоящий из 4 байтов. Первый байт несет информацию о типе сообщения, оставшиеся байты определяют длину сообщения.

Изначально протокол TLS (раньше это был SSL) был разработан для защиты транзакций коммерческого характера, которые проводились через сеть Интернет, в частности, для безопасности покупок или для управления счётом в банке.

Сегодня выполнение TSL-рукопожатия — это обеспечение целостности, конфиденциальности и подлинности интернет-соединения (аутентификация), которое необходимо защитить от несанкционированных действий злоумышленников.

Считается, что TLS работает поверх «потокового» соединения TCP, который отвечает за установление соединения, доставку информации и решение других телекоммуникационных задач. Это обычное соединение, не гарантирующее, что информация не будет перехвачена кем-либо в сети, заменена или изменена. Именно от этих угроз: перехвата данных, их подмены или замены защищает TSL-рукопожатие.

Протокол TSL заменил работающий довольно давно протокол SSL, но в некоторых вариантах он обозначается, как SSL/TLS-рукопожатие. Слово рукопожатие подставляют к нему от английского handshake, которым обозначен протокол из-за сходства его с знакомством двух впервые видящих друг друга людей (смотрите ниже как это происходит на простом языке) и после знакомства пожимающих друг другу руки в знак доверия.

Итак вот вся схема работы:


Клиент проникает на сервер, предлагая свой шифр, совместимый с обоюдно установленной версией протокола SSL/TLS.
Сервер проверяет шифр и актуальную версию протокола SSL/TLS, а также передаёт клиенту открытый ключ вместе с файлом сертификата.
Клиент проверяет сертификат, но этого мало и просит также проверить закрытый ключ. При помощи открытого ключа сервера клиент генерирует секретный ключ и отсылает на сервер, прося при помощи закрытого ключа его расшифровать.
Сервер расшифровывает секретный ключ и создаёт секрет, успешно используемый обоюдно при шифровании и расшифровывании информации.
После проверки вся информация шифруется при помощи секрета и расшифровывается при принятии.
Эффект рукопожатия заканчивается процедурой отправки определённый текст для проверки работоспособности.

С этого момента вся информация в общении клиент сервер шифруется.

Вот это и есть TSL рукопожатие

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

Подозрение на блокировку интернет страниц моим провайдером (help)

IPoE в г. Москва (за исключением нескольких районов) — Сеть IPoE и Web-авторизация

Посмотри в настройках роутера WAN . что стоит . если по этой инструкции Asus RT-N12 — то скорее всего это под IPoE (выбираем «Automatic IP» («Автоматический IP») — тогда как выше .

Если в настройках WAN выбрать L2TP . то вместо tp.internet.beeline.ru прописываеш . 85.21.0.243 ВСЁ .
ЕЩЁ . в билайне идёт привязка по МАКу потому МАК на роутере лучше сделать (КЛОНИРОВАТЬ) с твоей сетевой .

Вот сейчас набрал в адресной строке:
www.microsoft.com
Страница бесконечно загружается и внизу появилась такая байда:
выполнение tls-рукопожатия с AZ725125.vo.msecnd.net
Что бы это значило?

Я вот так настраивал роутер

на роутере 192.168.1.1 в настройках в правом верхнем углу ДВА компьютера — зелёненькие . КАК на ВИДЕО .
вместо tp.internet.beeline.ru прописываеш . 85.21.0.243

в командной строке CMD — ping tp.internet.beeline.ru — посмотри адрес своего сервера L2TP .
выполнение tls-рукопожатия с AZ725125.vo.msecnd.net — это твой браузер пытается установить соединение (куки похоже не при-чём) почисть на всякий

Пуск выполнить
cmd /k ipconfig /flushdns
cmd /k ipconfig /renew
перезагрузка

Принцип работы handshake (рукопожатие) SSL/TLS

Принцип работы handshake (рукопожатие) SSL/TLS

Handshake (рукопожатие) SSL/TLS состоит из того, что сервер и клиент идентифицируют друг друга и начинают общение через шифрованный SSL/TLS-туннель (который является безопасным).

Данный процесс и называется handshak-ом или рукопожатием из-за того, что они (сервер и клиент) видятся первый раз. Такой процесс, начинается с идентификации и заканчивается генерированием секретного ключа.

Что такое SSL/TLS-рукопожатие?

SSL handshake – это общение сервера и клиента между собой, где каждый хочет достичь одной и той же цели – безопасно общаться с помощью симметричного шифрования. При таком шифровании у двух сторон один ключ для шифрования и дешифрования сообщений. Такой ключ называется общим секретным – у всех пользователей, которые обмениваются данными, один и тот же ключ.

Принцип работы handshake (рукопожатие) SSL/TLS

Расмотрим диалог сервера и клиента:

Клиент: «Здравствуйте сервер! Я бы хотел установить безопасное соединение между нами. От себя, я отсылаю свои шифры и совместимую SSL/TLS версию».

Сервер: «Здравствуйте, клиент! Я проверил шифр который получил от тебя и SSL/TLS версию, которую ты используешь. Нет повода отсоединятся, так что — продолжаем…. От себя, я хотел бы отправить свой сертификат-файл и публичный ключ. Клиент, проверь их пожалуйста».

Клиент: » Такс, твой сертификат в порядке. Но мне необходимо, чекнуть твой закрытый ключ. Для этого, я сейчас сгенерирую и зашифрую общий секретный ключ с помощью твоего открытого ключа. Выполни расшифровку с помощью своего приватного ключика. Если все пройдет гладко, — ты в свою очередь, создашь главный секрет, который мы в дальнейшем, будем использовать для шифрования и расшифрования информации».

Сервер: «Понял! Все сделано».

С этого момента, когда сервер и клиент доверяют друг другу, то инфу которую они будут передавать между собой, будет зашифрована с помощью главного секрета (После проверок, информация будет зашифрована только через главный секретный ключ).

Клиент: «И так, для тестирования — я отправлю тестовое сообщение, дабы удостоверится, что созданный главный секрет корректно работает. Сервер, ты в свою очередь, когда получишь это тестовое сообщение — отправь мне расшифрованную версию этого сообщения. Если все получится, наши данные — в безопасности».

Сервер: «Да, все прочто отлично. Работает!».

Вот такое вот SSL/TLS-рукопожатие. С этого момента, когда сервер и клиент будут передавать файлы, они будут зашифрованы.

Решение некоторых проблем с handshake (рукопожатием) SSL/TLS

Ошибка «SSL_do_handshake errors с nginx или haproxy»

Если вы загружаете https трафик с haproxy в tcp-режиме, и вы выполняете это с помощью nginx, и вы получаете 502 ошибки, сопровождаемые этими ошибками SSL в журнале ошибок nginx:

То вам нужно отключить опцию proxy_ssl_session_reuse:

По умолчанию nginx пытается повторно использовать сеансы ssl для https upstream; но когда HAProxy циклично обрабатывает tcp-соединения между разными бэкендами, сеанс ssl не будет действителен с одного подключения tcp к другому.

Вот и все, статья «Принцип работы handshake (рукопожатие) SSL/TLS» завершена.

What is: SSL/TLS в деталях

Протоколы криптографии предоставляют возможность установления защищённых соединений между двумя удалёнными хостами.

Два наиболее часто встречающихся набора протоколов — SSL/TLS, основная задача которых заключается в обеспечении конфидициальности передаваемых данных, обеспечении целостности данных (т.е. гарантирование того, что данные не были изменены или подменены во время доставки между узлами), а так же в обеспечении идентификации и аутенфикации ресурсов и хостов с использованием цифровых сертификатов.

Каждый протокол SSL/TLS включает в себя набор внутренних протоколов (subprotocols), которые рассмотрены в разделе Обзор SSL/TLS соединения.

Задачи SSL/TLS соединения:

  • обеспечение приватности с помощью шифрования передаваемых данных
  • аутентификация с помощью сертификатов
  • обеспечение достоверности данных с помощью проверки целостности данных

Ниже будут рассмотрены основные аспекты SSL/TLS. К сожалению, как бы ни хотелось — всего описать не получится, но постарался собрать и хотя бы кратко описать самое важное (плюс ссылки в тексте и в конце поста).

TSL vs SSL: история

Основное отличие между ними — TLS является наследником протокола SSL, и использует более безопасные способы обеспечения безопасности.

  • SSLSecure Socket Layer
  • TLSTransport Layer Security

Краткая история SSL/TLS:

  1. SSL был разработан компанией Netscape, но версия 1.0 не была опубликована и использована из-за проблем безопасности в её реализации
  2. SSL 2.0 была выпущена в феврале 1995, но так же содержала уязвимости, потому:
  3. в 1996 появилась версия SSL 3.0

SSL 2.0 официально признан устаревшей версией в 2011 году (см. RFC 6176 ), а SSL 3.0 — в 2015 ( RFC 7568 ), хотя версия 3.0 была объявлена небезопасной для использования ещё в 2004 году из-за обнаружения уязвимости POODLE .

Из-за проблем с безопасностью, а так же из-за проблем с Netscape, связанных с юридическими вопросами, в 1999 на смену SSL пришёл протокол TLS, основанный на SSL v3.0.

TLS являлся окрытым стандартном (в отличии от SSL, поддерживаемого компанией Netscape) и в результате полностью заменил собой SSL.

  1. TLS 1.0 выпущен в январе 1999, RFC 2246 , и использовался вплоть до 2020 года, когда первый раз был объявлен устаревшим (позже его «устаревание» продлили до 2020 года).
  2. TSL 1.1 выпущен в апреле 2006, RFC 4346 , с 30-го июня 2020 полностью заменит TLS 1.0
  3. TLS 1.2 появился в августе 2008, RFC 5246 , с 30-го июня 2020 полностью заменит TLS 1.0 и будет являться рекомендуемым протоколом для использования
  4. TLS 1.3 ещё находится в состоянии черновика

Аббревиатуры SSL и TLS используются взаимозаменяемы, и под SSL как правило подразумевается TLS, т.к. в большистве случаев (а особенно в 2020) клиенты предлагают (см ClientHello ) использовать версии TLS 1.1 и 1.2.

SSL/TLS: основные понятия

Прежде, чем перейти к соединению и TLS Handshake части — рассмотрим некоторые основные понятия.

SSL certificate

Сертификат открытого ключа (public key certificate, digital certificate или identity certificate, а так же сертификат, сертификат ключа подписи, сертификат ключа проверки электронной подписи) — электронный документ, подтверждающий принадлежность публичного ключа его владельцу.

Сертификат выдаётся и подписывается Certificate Authorities , которые подписывают выданные сертификаты своей цифровой подписью, подтверждая, что владелец сертификата (и публичного ключа, включённого в этот сертификат) был проверен:

TLS сертификат как правило включает в себя поля:

  • Version Number: версия сертификата ( см X.509 )
  • Serial Number: используется для идентификации сертификата его Certificate Authorities
  • Signature Algorithm: алгоритм, использованный для подписи публичного ключа
  • Issuer: кем выдан и подписан сертификат (Certificate Authority)
  • Not Before и Not After: срок действия (валидности) сертификата
  • Subject name: кому принадлежит сертификат
  • Subject Public Key Info
    • Public Key Algorithm: алгоритм, использованный для подписи публичного ключа
    • Subject Public Key: сам публичный ключ владельца сертификата
  • Certificate Signature Algorithm: алгоритм, использованный для подписи сертификата
  • Certificate Signature: цифровая подпись сертификата

Например сертификат для RTFM выглядит так:

Получить только публичный ключ из сертификата можно так:

CipherSuites

Cipher suite — это комбинация криптографических алгоритмов, которые будут использованы для обеспечения безопасности сессии.

Как правило, в неё входят алгоритмы для:

  • алгоритм обмена ключами
  • аутентификации сервера
  • шифрования данных
  • алгоритм контроля целостности (Message Authentication Code, MAC)

Например — для соединения с RTFM клиент (браузер) выбирает набор TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 :

  • TLS: используемый протокол
  • ECDHE: алгоритм обмена ключами сессии ( Elliptic curve Diffie–Hellman ephemeral )
  • RSA: алuоритм аутентификации ( RSA )
  • AES_256_GCM: алгоритм шифрования данных (Advanced Encryption Standard 256 bit Galois/Counter Mode)
  • SHA384: алгоритм Message Authentication Code (MAC) (Secure Hash Algorithm 384 bit)

Message Authentication Code (MAC)

Message Authentication Code, или криптографическая контрольная сумма сообщения — способ аутентификации и проверки целостности сообщения, основанный на цифровой подписи сообщения (или блока данных на Record Layer).

Подпись создаётся с помощью секретного ключа ( client_write_MAC_key и server_write_MAC_key в ChangeCipherSpec и Finish) и самого сообщения.

Hash Based Message Authentication Code (HMAC) — тип MAC, основанный на хешировании ( hash function ).

Пример получения такой контрольной суммы с использованием SHA384:

Симметричное шифрование

Процесс, при котором шифрование и дешифрование выполняется с помощью одного и того же ключа, которым стороны должны обменяться до начала шифрования.

Основной проблем симметричного шифрования как раз явлется сам факт того, что данные должны быть зашифрованы одним и тем же ключём.

Если этот ключ будет перехвачен злоумышленником — он получит возможность расшировать все данные, зашифрованные этим ключём.

Именно поэтому передача такого ключа должна осуществляться по уже зашированному соединению.

Преимущества

  • быстрое, низкое потребление ресурсов системы
  • простые операции
  • безопасно

Недостатки

  • один ключ для шифрования/дешифрования
  • передача ключа должна быть выполнена по уже защищённому соединению
  • нет возможности авторизации пользователей

Ассиметричное шифрование

Asymmetric encryption (также Public Key Cryptography — криптография по открытому ключу) использует пары ключей — публичный и приватный. Эти ключи связаны друг с другом таким образом, что данные, зашифрованные с помощью одного ключа (как правило публичного) могут быть расшифрованы другим (приватным).

Асссиметричное шифрование так же может применяться для авторизации отправителя: если Боб подписывает и шифрует сообщение, используя свой приватный ключ, то любой, у кого есть публичная часть ключа и кто смог расшифровать такое сообщение может быть уверен, что его зашифровал и отправил только Боб (при условии, что Боб не слил свой приватный ключ в Github…).

Преимущества

  • простая передача ключа
  • аутентификация пользователей
  • проверка целостности

Недостатки

  • медлененее, чем симметричное шифрование
  • потребляет больше ресурсов

Теперь можно перейти к рассмотрению непосредственно SSL/TLS соединения.

Обзор SSL/TLS соединения

Любое SSL-соединение использует набор протоколов, описанных в RFC 5246 (тут и ниже рассматривается TLS v 1.2 и этот RFC, как последняя актуальная версия на момент написания этого поста — март 2020).

В RFC 5246 они описаны в обратном порядке, но тут рассмотрим их начиная с Handshake Protocol , т.к. именно в нём описывается процесс установления сессии и создания ключей, которые далее используются в TLS Record Protocol .

Структура получается следующая:

  • The TLS Handshaking Protocols
    • Handshake Protocol
    • Change Cipher Spec Protocol
    • Alert Protocol
  • The TLS Record Protocol
    • Record Layer

Сейчас рассмотрим протоколы кратко, далее рассмотрим общий процесс рукопожатия (раздел SSL Handshake кратко), после чего все его шаги будут описаны детально (раздел SSL Handshake в деталях).

TLS Handshaking Protocols

Описан в разделе 7 RFC.


Включает в себя три протокола, которые используются для согласования узлами параметров безопасности, которые будут использоваться на Record layer (см. ниже). Эти параметры включают в себя аутентификацию узлов, согласование параметров безопасности и для отправки сообщений об ошибках.

Опять-таки — в RFC они описаны в другом порядке, но тут для удобства понимания кратко рассмотрим их в порядке «важности» — Handshake Protocol, Change Cipher Spec Protocol и Alert Protocol.

Выполняется на Presentation Layer модели OSI:

Handshake Protocol

Описан в разделе 7.4 RFC 5246.

Ключевой протокол, описывающий процесс установления сессии и согласования параметров, которые будут использоваться во время сессии. Он включает в себя 9 основных «сообщений рукопожатия» (handshake messages), которые используются для создания сессии — их мы в деталях и рассмотрим далее (Процесс установления SSL сессии – базовый SSL Handshake).

Эти сообщения передаются на TLS Record layer, который передаёт далее, вниз по стеку протоколов OSI.

Change Cipher Spec Protocol

Описан в разделе 7.1 .

Этот протокол используется исключительно для уведомления хостами друг друга об изменении в использовании шифровании, т.е. при переходе в передаче данных в нешифрованном виде к передаче зашифрованных данных.

Состоит из единственного сообщения, которое содержит 1 байт со значением 1, которое отправляется и клиентом и сервером на стадии рукопожатия.

Alert Protocol

Описан в разделе 7.2 .

Этот протокол описывает Alert тип данных, в котором передаются сообщения для управления соединением. Алерты содержат два поля — уровень предупреждения и его описание.

Уровень fatal приводит к немедленному уничтожению соединения. В этому случае другие соединения в этой сессии (см. C: libssh – пример SSH-“клиента”) могут оставаться активными до их завершения, но идентификатор сессии (Session ID, будет рассмотрен ниже) должен быть удалён, предотвращая создание новых соединений в рамках этой сессиии.

The TLS Record Protocol

Описан в разделе 6 .

TLS Record Protocol включает принимает сообщения для передачи от Application Layer модели OSI, разбивает их на блоки, при необходимости выполняет сжатие, добавляет Message authentication code (MAC), выполняет шифрование и передаёт результат вниз по стеку на TCP протокол.

Полученные «снизу» данные (т.е. пришедшие «из интернета») расшифровываются, выполняется проверка их целостности, распаковка, сборка целого сообщения из блоков и выполняется доставка вышележащим клиентам на Application уровне.

TLS Record Protocol выполняется над Transport Layer, который обеспечивает передачу блоков данных между узлами сети, и под Application уровнем, обеспечивая передачу данных приложениям:

Record Layer

На TLS Record Layer выполняется фрагментация ( 6.2.1 ), сжатие и распаковка ( 6.2.2 ) и защита целостности ( 6.2.3 ) передаваемых данных.

Процесс установления SSL сессии — SSL Handshake

Ключевой момент установления защищенного соединения — SSL Handshake, или «рукопожатие», в процессе которого осуществляется согласование используемой версии TLS, верификация узлов (аутентификация сервера и опционально клиента), алгоритмов шифрования, обмен ключами, сертификатами и собственно установдение и начало обмена уже зашифрованными данными.

  • Аутентификация — это проверка соответствия субъекта и того, за кого он пытается себя выдать, с помощью некой уникальной информации — отпечатка пальцев, цифрового сертификата или в простейшем случае — с помощью логина и пароля.
  • Авторизация — это проверка и определение полномочий на выполнение некоторых действий (например, авторизация пользователя в операционной системе) в соответствии с ранее выполненной аутентификацией.

Выше упоминалось про 9 сообщений при выполнении TLS Handshake — они предоставлены на изображении ниже:

SSL Handshake кратко

Прежде, чем углубиться в детали реализации TLS Handshake — рассмотрим процесс кратко.

Процесс рукопожатия можно разбить на три условных фазы — привествие (Hello), обмен сертификатами (Certificate Exchange) и обмен ключами (Key Exchange):

  1. Hello: рукопожатие начинается с того, что клиент, который хочет подключиться к серверу используя TLS, отправляет сообщение ClientHello . В нём содержится вся информация, необходимая для создания (или восстановления) TLS-сессии, например — наборы предпочитаемых методов шифрования (Cipher Suites), версия SSL/TLS и т.д. Сервер в свою очередь отвечает сообщением ServerHello , в котором содержится информация, основанная на запросе клиента, например выбранная сервером версия SSL/TLS, ID создаваемой сессии, выбранный метод шифрования.
  2. Certificate Exchange: после того, как контакт установлен — сервер должен доказать клиенту, что он именно тот, за кого он себя выдаёт — пройти аутентификацию, которая выполняется с помощью предоставления сервером SSL сертификата. В сертификате содержится информация о владельце, домене, на который выдан, публичный ключ, цифровая подпись, дата выдачи срок действия сертификата. Клиент выполняет проверку сертификата — либо он может доверять ему безоговорночно, либо может выполнить проверку через Certificate Authorities (CA), которым клиент доверяет. Сервер так же может запросить сертификат клиента для его аутентификации.
  3. Key Exchange: шифрование передаваемых по защищённому соединению данных выполняется с помощью симметричного шифрования, которое было согласовано во время Hello фазы. Симметричное шифрование использует один ключ для шифрования и дешифрования, в отличии от ассиметричного шифрования, в котором используется пара публичного/приватного ключей. Обеим сторонам — клиенту и серверу, необходимо создать ключ для симметричного шифрования («master key«), а процесс его создания выполняется с помощью ассиметричного шифрования и приватного/публичного ключа сервера плюс рандомные строки, созданные во время Hello фазы.

Далее клиент генерирует pre-master secret key, который будет использоваться для вычисления master key, шифрует его с помощью выбранного в Hello фазе алгоритма используя публичный ключ севера, который передаётся в его сертификате в фазе Certificate Exchange и отправляет его серверу.

Сервер дешифрует pre-master secret key, используя свой приватный ключ и вычисляет master key на своей стороне.

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

SSL Handshake в деталях

Hello, фаза согласования
ClientHello

Клиент отправляет ClientHello сообщение серверу, в котором указываются:

  • client_version : желаемая клиентом версия TLS (последняя из доступных — This SHOULD be the latest (highest valued) version supported by the client)
  • random : структура, содержащая:
    • gmt_unix_time — 4 байта, текущие время и дата в стандартном 32-х битном UNIX формате
    • random_bytes — 28 байт, сгенерированные с помощью генератора случайных чисел ( random number generator , RNG)
  • session_id : ID сессии, если клиент пытается возобновить TLS сессию
  • cipher_suites : поддерживаемые CipherSuites (методы шифрования, см. Appendix A.5 ), с указанием методов, предпочитаемых клиентом.
  • compression_methods : список методов сжатия, поддерживаемых клиентом (см. RFC-3749 — Transport Layer Security Protocol Compression Methods)
  • extensions : (опционально) клиент может запросить расширенную функциональность от сервера, указав её в этом поле (см. Hello Extensions )

Сама структура ClientHello (см. Appendix-A.4.1 ):

ClientHello описывается в разделе 7.4.1.2 .

Пример ClientHello в Wireshark для RTFM:

ServerHello

Сервер отвечает сообщением ServerHello , в котором указываются:

  • server_version : выбранная сервером версия TLS, основываясь на переданном значении client_version из ClientHello
  • random : аналогично random клиента — 4 байта времени и даты на сервере + 28 байта случайного числа. random клиента и random сервера далее будут использованы для генерации ключа шифрования
  • session_id : если поле ClientHello.session_id содержало ID сессии — сервер проверит свой кеш на предмет поиска этого ID. Если ID найден — дальнейшие шаги будут пропущены, и рукопожатие перейдёт сразу к стадии Finished .
  • cipher_suite : метод шифрования, выбранный сервером из списка, предложенного клиентом в его ClientHello.cipher_suite
  • compression_method : метод сжатия, выбранный из ClientHello.compression_methods . Если сессия восстанавливается (в кеше сервера найдён session_id ) — использует метод из старой сессии
  • extensions : список расширений из списка, отправленного клиентом

Описывается в разделе 7.4.1.3 .

ServerHello в Wireshark:

Например, тут видно что в Cipher Suite содержится уже не целый список методов, а только один, выбранный сервером из предложенных клиентом, по которому будет далее и выполняться шифрование.

Certificate Exchange, обмен сертификатами
Certificate

Сервер отправляет сообщение Certificate , в котором в поле certificate_list передаётся список сертификатов (certificate chain), где первым идёт сертификат самого сервера, за ним сертификаты цепочки доверия ( chain of trust ) в порядке очереди. Корневые сертификаты не передаются, т.к. предполагается, что клиент уже ими располагает.

Например — в Linux они располагаются в каталоге /etc/ssl/certs/ :

У браузеров политика валидации сертификатов и поиска корневых сертификатов отличается. Для Chrome/Crhomium — см тут>>> и тут>>> .

Сообщение Certificate описывается в разделе 7.4.2 .

Certificate в результатах Wireshark:

Тут хорошо просматривается цепочка:

    сертификат сервера RTFM: Certificate: ( >Корневой сертификат DST Root CA X3 расположен в системе, в /etc/ssl/certs :

ServerKeyExchange

Cервер отправляет сообщение ServerKeyExchange , опционально, в зависимости от используемого алгоритма шифрования для передачи ключа, если данных в сообщении Certificate недостаточно для создания pre-master secret ключа (т.е. в случае использования DHE_DSS , DHE_RSA , DH_anon , другие алогритмы должны явно указать на необходимость передачи ServerKeyExchange ).

В ServerKeyExchange может передаваться публичный ключ Diffie-Hellman (DF), с помощью которого клиент может завершить обмен pre-master ключём

Публичный ключ DF в сообщении ServerKeyExchange в результатах Wireshark:

ServerHelloDone

Сервер отправляет сообщение ServerHelloDone , которое указывает на то, что сервер закончил передачу своего ServerHello и ждёт ответа клиента.
После получения ServerHelloDone клиент выполняет проверку цифровой подписи сертификата сервера ( Digital signatures in SSL and TLS ), проверяет цепочку сертификатов ( How certificate chains work ), дату выдачи и срок действия сертификата, и статус сертификата — не был ли он отозван Central Authority, который выдал этот сертификат ( Working with revoked certificates ).

ServerHelloDone в Wireshark:

ClientKeyExchange

Клиент отправляет сообщение ClientKeyExchange , в котором вырабатывается pre-master secret key.

В случае использования RSA — pre-master ключ отправляется серверу зашифрованным с помощью публичного ключа сервера. В случае использования алгоритма Diffie-Hellman — передаются DF параметры со стороны клиента, позволяющие согласовать pre-master ключ.

В случае использования EDF (ephemeral Diffie-Hellman) — клиент передаёт публичный ключ. В случае использования DF (static Diffie-Hellman) — поле ClientDiffieHellmanPublic передаётся пустым.

Описывается в разделе 7.4.7 .

Wireshark и публичный ключ клиента для DF:

На этом фаза Key Exchange завершена, и начинается процесс «активации» защищённого соединения.

ChangeCipherSpec и Finish

Обе стороны — и клиент, и сервер, вычисляют общий master key длиной 48 байт, используя строки из ClientRandom и ServerRandom + pre_master_secret , используя Pseudorandom Function (PRF):

Далее этот master_key используется для генерации набора ключей (см. 6.3. Key Calculation ):

  • client_write_MAC_key – аутентификация и проверка целосности данных клиентом
  • server_write_MAC_key – аутентификация и проверка целосности данных сервером
  • client_write_key – шифрование сообщения клиентом, используя симметричный ключ
  • server_write_key – шифрование сообщения сервером, используя симметричный ключ
  • client_write_IV – Initialization Vector используемый некоторыми AEAD алгоритмами
  • server_write_IV –Initialization Vector используемый некоторыми AEAD алгоритмами

После генерации ключей обеими сторонами — они готовы к началу передачи зашифрованных данных, используя эти ключи ( client_write_key для клиента и server_write_key для сервера).

Клиент отправляет серверу сообщение ChangeCipherSpec , указывая серверу на то, что все данные, начиная с этого сообщения, будут зашифрованы.

После отправки ChangeCipherSpec — клиент отправляет сообщение Finished , в которой в поле finished_label содержится строка «client finished», которую сервер должен расшифровать и проверить целостность самого сообщения.

После успешной проверки Finished сообщения от клиента — сервер отправляет своё сообщение ChangeCipherSpec , а затем своё сообщение Finished , в котором в поле finished_label содержится строка «server finished», которую клиент должен расшифровать и проверить целостность самого сообщения.

В результатах Wireshark — ChangeCipherSpec и зашифрованная строка:

С этого момента все остальные данные (Application data) передаются в зашифрованном виде.

Протокол SSL/TLS

Протокол Рукопожатия

Протокол Рукопожатия состоит из трех подпротоколов, использование которых позволяет участникам согласовать криптографические алгоритмы, аутентифицировать друг друга, и сообщить друг другу о возникновении тех или иных ошибок.

В результате выполнения протокола Рукопожатия будут созданы следующие элементы сессии:

Таблица 11.1.

Идентификатор сессии Произвольная последовательность байтов, выбираемая сервером для идентификации активного или возобновляемого состояния сессии.
Сертификат участника Х.509 v3 сертификат участника. Этот элемент может быть нулевым.
Метод сжатия Алгоритм, используемый для сжатия данных перед шифрованием.
Набор алгоритмов Алгоритм симметричного шифрования данных (например, NULL, DES, AES и т.д.), МАС-алгоритм (такой как MD5 или SHA-1) и параметры этих алгоритмов.
Мастер-секрет 48-байтный секрет, разделяемый клиентом и сервером.
Возобновляемо Флаг, определяющий, может ли данная сессия использоваться для создания нового ТСР-соединения.

Протокол изменения шифрования

Протокол состоит из единственного сообщения, которое зашифровано и сжато, как определено в текущем состоянии соединения.

Сообщение об изменении шифрования посылается как клиентом, так и сервером для уведомления противоположной стороны о том, что следующие записи будут защищены алгоритмами и ключами, о которых стороны только что договорились. При получении данного сообщения протокол Записи копирует ожидаемое состояние чтения в текущее состояние чтения. Сразу после посылки данного сообщения отправитель копирует ожидаемое состояние записи в текущее состояние записи. Сообщение об изменении шифрования посылается при Рукопожатии после того, как параметры безопасности согласованы, но перед тем как посылается заключительное верифицирующее сообщение.

Alert-протокол

Одним из протоколов, выполняющихся выше протокола Записи, является протокол Аlert. Содержимым протокола является либо фатальное, либо предупреждающее сообщение. Фатальное сообщение должно приводить к немедленному разрыву данного ТСР-соединения. В этом случае другие соединения, соответствующие данной сессии, могут быть продолжены, но идентификатор сессии должен быть помечен как недействительный для предотвращения использования данной сессии для установления новых соединений. Подобно другим сообщениям, сообщения Alert зашифрованы и сжаты, как определено в текущем состоянии соединения.

Протокол Рукопожатия

Криптографические параметры сессии создаются протоколом Рукопожатия, который выполняется выше протокола Записи. Когда клиент и сервер начинают взаимодействовать, они согласовывают версию протокола, выбирают криптографические алгоритмы, могут аутентифицировать друг друга, используя технологию с открытым ключом. Для создания разделяемого секрета также используется технология с открытым ключом.

Протокол Рукопожатия состоит из следующих шагов:

  1. Обмен сообщениями Hello для согласования алгоритмов, обмена случайными значениями и проверки возобновляемости сессии.
  2. Обмен необходимыми криптографическими параметрами, которые позволяют клиенту и серверу согласовать премастер-секрет.
  3. Обмен сертификатами и криптографической информацией, которая позволяет клиенту и серверу аутентифицировать друг друга.
  4. Предоставление параметров безопасности на уровень Записи.
  5. Возможность клиенту и серверу проверить, что они вычислили одни и те же параметры безопасности и что Рукопожатие произошло без вмешательства злоумышленника.

Протокол разработан для минимизации риска атак «встреча посередине», но защита от атак, при которых злоумышленник может блокировать доступ к порту, не предусмотрена.

Клиент посылает сообщение ClientHello , на которое сервер должен ответить сообщением ServerHello или фатальной ошибкой и разрывом соединения. ClientHello и ServerHello используются для определения максимального уровня безопасности между клиентом и сервером. Client Hello и Server Hello устанавливают следующие атрибуты: Protocol Version, Session ID, Cipher Suite и Compression Method . Дополнительно создаются и передаются два случайных значения: ClientHello.random и ServerHello.random .

Аутентификация и обмен общим секретом осуществляются в четырех сообщениях: сертификат сервера, обмен ключа сервера, сертификат клиента и обмен ключа клиента. Общий секрет должен быть достаточно большим; текущие методы распределения ключа обмениваются секретами, длина которых находится в диапазоне от 48 до 126 байт.

После сообщений Hello сервер посылает сертификат, с помощью которого клиент выполняет аутентификацию сервера. Дополнительно может быть послано сообщение обмена ключа сервера, если сервер не имеет сертификата или его сертификат может использоваться только для проверки подписи. Если сервер аутентифицирован, он может запросить сертификат клиента, если того требует установленная политика безопасности на стороне сервера. После этого сервер посылает сообщение Server Hello Done , указывающее на то, что фаза Hello -сообщений рукопожатия завершена. Затем сервер ждет ответа клиента. Если сервер послал сообщение запроса сертификата, клиент должен послать сообщение Certificate . После этого посылается сообщение обмена ключа клиента. Содержимое этого сообщения зависит от выбранного алгоритма выработки общего секрета. Если клиент посылал свой сертификат, то он посылает сообщение, содержащее цифровую подпись для проверки всех сообщений Рукопожатия.

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

Когда клиент и сервер решают возобновить предыдущую сессию или дублировать существующую (вместо того чтобы вести новые переговоры о параметрах безопасности), выполняется так называемое сокращенное рукопожатие:

  • Клиент посылает Client Hello , используя Session ID возобновляемой сессии.
  • Сервер ищет соответствующий идентификатор сессии в своем кэше сессий. Если идентификатор существуует, и сессия помечена как возобновляемая, сервер устанавливает соединение с параметрами указанной сессии, после чего посылает Server Hello с этим значением Session ID . Если соответствующий Session ID не найден, сервер создает новый ID сессии, и клиент и сервер выполняют полное рукопожатие.
  • После этого и клиент, и сервер должны послать сообщения об изменении состояния, затем сразу послать завершающие сообщения.
  • И клиент, и сервер начинают обмен данными прикладного уровня.

Поток сообщений при сокращенном Рукопожатии

Следует заметить, что, так как Session ID передается без шифрования и обеспечения целостности, он не содержит конфиденциальную информацию. Содержимое всего Рукопожатия, включая Session ID , защищено Finished -сообщениями, которыми участники обмениваются в конце рукопожатия.

Список Cipher Suite , передаваемый от клиента серверу в сообщении Client Hello , содержит перечень криптографических алгоритмов, поддерживаемых клиентом, упорядоченный по предпочтениям клиента. Сервер выбирает по одному алгоритму из каждой категории, который он поддерживает. Если такого алгоритма не существует, сервер возвращает фатальный Alert и закрывает соединение.

После посылки сообщения Client Hello клиент ждет сообщения Server Hello . Любое другое сообщение, возвращаемое сервером, за исключением Hello Request , трактуется как фатальная ошибка.

Сервер посылает Server Hello в ответ на сообщение Client Hello , для того чтобы выбрать конкретный набор алгоритмов. Если для какого-то типа алгоритмов клиент и сервер не имеют одинакового алгоритма, ТСР-соединение будет сброшено.

Сообщение Certificate (сервера)

Сервер должен посылать сертификат, если метод обмена ключей не является анонимным. Данное сообщение всегда следует сразу за сообщением Server Hello .

Тип сертификата должен соответствовать выбранному алгоритму обмена ключа. Обычно это сертификат X.509v3. Он должен содержать ключ, который соответствует методу обмена ключа.

Сообщение сервера обмена ключа посылается сервером только тогда, когда сообщение Server Certificate (если оно послано) не содержит достаточно данных для того, чтобы клиент мог осуществить обмен премастер-секретом.

Данное сообщение передает криптографическую информацию, которая позволяет клиенту передавать премастер-секрет: премастер-секрет шифруется либо открытым ключом RSA, либо открытым ключом Диффи-Хеллмана.

Сообщение Certificate Request

Неанонимный сервер может дополнительно запросить сертификат клиента, если это требуется политикой безопасности сервера.

Сообщение Server Hello Done

Сообщение Server Hello Done посылается сервером как признак окончания фазы Server Hello .

Сообщение Certificate (клиента)

Это первое сообщение, которое клиент посылает после получения сообщения Server Hello Done . Оно посылается только в том случае, если сервер запросил аутентификацию клиента.

Сообщение Client Key Exchange

Данное сообщение посылается клиентом всегда. Оно следует сразу за сообщением Client Certificate , если оно посылалось. В противном случае это первое сообщение, посланное клиентом после получения сообщения Server Hello Done .

После получения данного сообщения сервер может вычислить премастер-секрет, который передается либо с помощью RSA шифрования, либо вычисляется по алгоритму Диффи-Хеллмана. В любом случае каждая сторона вычисляет один и тот же премастер-секрет.

Проверка целостности с помощью сертификата клиента

Данное сообщение используется для выполнения проверки целостности переданных и полученных сообщений Рукопожатия и аутентификации клиента. Оно посылается только в том случае, если алгоритм открытого ключа, для которого создан сертификат клиента, имеет возможность подписывания. Это означает, что исключением являются сертификаты, созданные для открытого ключа алгоритма Диффи-Хеллмана.

Сообщение Finished всегда посылается непосредственно после сообщения Сhange Сipher Spec для проверки успешного выполнения обмена ключа и процессов аутентификации. Сообщение Change Cipher Spec должно быть получено после остальных сообщений Рукопожатия и перед Finished -сообщением.

Finished -сообщение является первым сообщением, защищенным с помощью только что обговоренных алгоритмов и ключей. Получатели Finished -сообщения должны убедиться, что его содержимое корректно. После того как одна сторона послала свое Finished -сообщение, получила и проверила Finished -сообщение другой стороны, она может начинать посылать и получать прикладные данные по этому соединению.

Вычисление мастер-секрета

Независимо от методов обмена ключа используется следующий алгоритм для преобразования премастер-секрета в мастер-секрет. Премастер-секрет должен быть удален после того, как вычислен мастер-секрет.

Длина мастер-секрета всегда равна 48 байтам. Длина премастер-секрета изменяется в зависимости от метода обмена ключа.

Добавить комментарий