Алиса и Боб: примеры практической криптографии

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

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

УСТОЯВШИЕСЯ ИМЕНА В КРИПТОГРАФИИ:

Алиса и Боб (Alice and Bob) – Наиболее часто Алиса хочет послать сообщение Бобу. Эти имена были использованы Роном Ривестом (Ron Rivest) в 1978 году в журнале «Communications of the ACM» в статье «A Method for Obtaining Digital Signatures and Public-Key Cryptosystems».
Ева (Eve) – пассивный злоумышленник, от англ. eavesdropper (подслушивающий). Она может прослушивать сообщения между Алисой и Бобом, но она не может влиять на них.
Мэллори (Mallory, от malicious) – активный злоумышленник; в отличие от Евы, Мэллори может изменять сообщения, воспроизводить старые сообщения, подменять сообщения и так далее.
Трент (Trent) – доверенный арбитр, своего рода нейтральная третья сторона, чья точная роль изменяется в зависимости от стадии обсуждения протокола.

ШИФРОВАНИЕ

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

ОБМЕН КЛЮЧАМИ

Чтобы Алисе и Бобу получить общий секрет им следует о нем договориться. Так как они не могут использовать для этого небезопасный канал, который прослушивает Ева, им придется воспользоваться другим вариантом. Вариант который здесь будет рассмотрен называется криптография с открытым ключом. Для того чтобы Алисе и Бобу безопасно обменяться ключами, Бобу нужно сгенерировать два ключа, приватный и публичный. Далее Боб отсылает публичный ключ Алисе, не опасаясь того, что Ева его тоже может получить, иначе почему бы ему называться публичным. После того, как Алиса получила публичный ключ Боба, она может зашифровать им свой секрет и отправить Бобу. Сообщение зашифрованное публичным ключом можно расшифровать только зная парный секретный ключ. Когда Боб получит зашифрованное сообщение он может воспользоваться своим секретным ключом для его расшифровки, после этого Алиса и Боб будут иметь общий секрет. Так, например, работает самый популярный алгоритм с открытым ключом – RSA. Но этот метод с 2015 года считается историческим по ряду причин. Например, если секретный ключ RSA когда-нибудь будет скомпрометирован, все предыдущие сообщения, которые получала Ева, можно будет расшифровать. Рекомендуемый метод генерации общего сеансового секрета – это протокол Диффи-Хеллмана(DH). Его использование, прежде всего, позволяет добиться так называемой прогрессивной секретности (Perfect Forward Secrecy), когда раскрытие серверного ключа асимметричной криптосистемы (RSA или ECDSA) не приводит автоматически к раскрытию ранее записанных сообщений, так как установленный общий секрет никогда не покидает Алису или Боба и, соответственно, не может быть перехвачен Евой, даже если та знает закрытый ключ сервера. Основная идея протокола DH может быть сформулирована достаточно просто. Алиса и Боб, желающие получить общий секрет, очевидно, могут сгенерировать собственные, локальные секреты. Предположим, что у них есть некоторая однонаправленная функция – то есть, можно легко вычислить значение функции для заданного аргумента, но обратить вычисления и узнать аргумент по значению – сложно. Тогда можно было бы устроить алгоритм таким образом, чтобы договаривающиеся об общем секрете стороны передавали по открытому каналу друг другу значения функции от секретных аргументов, проводили над этими значениями и аргументами собственные вычисления и, в результате применения некоторых преобразований, могли бы каждая прийти к одному и тому же значению. Просматривающая коммуникации третья сторона же видела бы только значения однонаправленной функции, без возможности обратить её и узнать секрет.

ЦИФРОВАЯ ПОДПИСЬ

Классический DH не защищен от атак модификации передаваемых параметров математической системы. Чтобы их защитить используются цифровые подписи. Основная задача цифровых подписей – это аутентификация, проверка целостности и предотвращение отрицания авторства (non-repudiation). Также они являются ответом на вопрос про приказ. В качестве криптосистемы подписи может использоваться либо RSA (устаревший вариант), либо ECDSA (современный вариант).
Общая схема генерации подписанного сообщения выглядит так:

Общая схема генерации подписанного сообщения.

На этот раз Боб применяет специальный алгоритм для генерации пары ключей (<секретный ключ>, <публичный ключ>). Если Боб хочет отослать Алисе подписанное сообщение m, он генерирует цифровую подпись <цифровая подпись> = <функция хеширования>(<секретный ключ>, <сообщение>).
Затем сообщение и подпись отсылаются Алисе. Алиса применяет принадлежащий Бобу публичный ключ и алгоритм верификации <алгоритм верификации>(<публичный ключ>, <сообщение>, <цифровая подпись>)
для проверки цифровой подписи. Успешная верификация гарантирует, что данные не изменялись и отправлены тем, у кого есть закрытый ключ, парный имеющемуся открытому. Процесс обмена ключами, в зависимости от выбранных криптографических примитивов, выглядит так:

Процесс обмена ключами, в зависимости от выбранных криптографических примитивов.

PUBLIC-KEY INFRASTRUCTURE

Публичный ключ Боба, используемый для цифровой подписи параметров, может быть подменён Мэллори на свой, имитирующий легитимный ключ Боба. Для того, чтобы можно было обнаружить подобную подмену, служит инфраструктура открытого ключа(Public-Key Infrastructure — PKI), которая даёт Алисе механизм проверки принадлежности ключа. То есть, Алиса соглашается верить некоторой третьей стороне (не Мэллори, а Тренту), что эта третья сторона проверила соответствие ключа и имени (в вебе это обычно домен). Это работает примерно так: Боб передает открытый ключ Тренту со следующим пояснением: «Привет, я Боб, и у меня есть открытый ключ PK». Трент проверяет, действительно ли Боб является тем, за кого себя выдает, а затем подписывает цифровое утверждение примерно следующего содержания: «Ключ PK принадлежит Бобу». Это подписанное утверждение называется сертификатом(certificate, X.509).

Сертификат этого блога
Он удостоверяет, что данный публичный ключ принадлежит Бобу. Предполагается, что у Алисы есть сертификат(в котором присутствует так же публичный ключ) Трента, с помощью которого она может проверить цифровую подпись последнего. Так как Алиса безоговорочно верит Тренту, то с помощью открытого ключа Трента она может проверить цифровую подпись на сертификате Боба и тем самым удостовериться, что PK действительно принадлежит Бобу. Алисе не нужно иметь публичные ключи всех Трентов, а только одного самого главного. Тогда Бобу нужно прислать помимо своего сертификата, все промежуточные. В этом случае Алисе необходимо построить цепочку доверия(chain of trust) от сертификата Боба, до сертификата главного Трента. В современном web роль Трента играет центр сертификации(Certificate Authority — CA).
Еще один вариант решить проблему обмена секретами воплощенная в протоколе kerberos и называется key distribution center(KDC). Если Алиса хочет обратиться к Бобу — она посылает сообщение Тренту(KDC). Трент направляет каждому участнику сеанса копии сеансового секрета, действующие в течение небольшого промежутка времени. Копия сеансового секрета, пересылаемая Бобу, шифруется с помощью публичного ключа Боба, а направляемая Алисе – публичного ключа Алисы. Предполагается, что Трент хранит публичные ключи всех абонентов у себя в базе. Это теоретический вариант, отображающий суть схемы, который на практике реализовать очень сложно в таком виде.

CERTIFICATE PINNING

Chain of trust решает проблему распределения ключей в стерильной среде. Однако это требует доверие третьей стороне, что на практике оказывается совсем не очень хорошо. Представьте себе ситуацию, вы в кафе подключаетесь к открытому WI-FI, вам показывается окно с предупреждением вида – «для использования бесплатного интернета вам необходимо установить сертификат», неподкованный пользователь может это сделать. Это приведет к тому, что Алиса будет безоговорочно доверять левому сертификату. Это плохо, потому что позволит Мэллори провести атаку человек посередине(man-in-the-middle).
Как это работает:

  1. Алиса посылает Бобу запрос на соединение.
  2. Его перехватывает Мэллори и отправляет свой запрос на соединение Бобу.
  3. Боб отсылает свой сертификат Мэллори.
  4. Мэллори отсылает свой сертификат Алисе.
  5. Алиса успешно проводит проверку сертификата Мэллори и устанавливает с ней соединение.
  6. Мэллори без особых проблем тоже проверяет сертификат Боба и устанавливает с ним соединение.

Certificate pinning – это способ предотвращения успешной проверки сертификата Мэллори. Способ можно описать так – Алиса и Боб встречаются в кафе, для того, чтобы Боб лично отдал Алисе свой публичный ключ. Этот лайфхак используется, в основном, мобильными приложениями и заключается в сохранении публичного ключа в коде клиента. Это позволяет не зависеть от третьей стороны, такой как CA, при принятии решений касающихся безопасности. Проверка проходит по следующему алгоритму:

  1. Алиса получает чей-то сертификат.
  2. Сверяет с сертификатом Боба(который получила при личной встрече в кафе).
  3. Если проверка проходит успешно Алиса устанавливает соединение с Бобом.
  4. Если проверка заканчивается неудачей, разрывает соединение.

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

MAC-коды

Наконец Алиса и Боб имеют общий секрет. На этом этапе они могут безопасно(нет) обмениваться сообщениями. На самом деле мы защитились только от Евы(пассивный злоумышленник), но у нас еще есть Мэллори(активный злоумышленник), которая может изменять наши зашифрованные сообщения! Частой ошибкой на вопрос – «как обнаружить преднамеренную модификацию данных», есть ответ – «вычислить хэш от сообщения и отправить вместе с ним». Это заблуждение, так как злоумышленник может изменить сообщение и перевычислить хэш. На помощь в этом случае приходит MAC(message authentication code), который предназначен для обеспечения целостности сообщения и аутентификации источника данных. Это некоторое значение, вычисляемое для заданного сообщения и секретного ключа. Значение различается для разных сообщений. Чтобы вычислить корректное значение MAC требуется знать секретный симметричный ключ. Таким образом, если сообщение было изменено третьей стороной, то проверка MAC позволит это выявить. Кроме того, корректное значение MAC позволяет утверждать, что данное сообщение было сгенерировано стороной, которой известен соответствующий ключ. MAC отличается от цифровой подписи тем, что использует общий сеансовый секрет, вместо закрытого ключа из пары. Также MAC намного быстрее вычисляется чем цифровая подпись. В остальном они идентичны. Большая ошибка вычислять MAC на основе открытого текста, добавлять его в конец и после этого шифровать все сообщение(архитектурная ошибка протокола SSL/TLS). Проблема в том, что MAC можно проверить только после расшифровки сообщения и, если значение оказалось некорректным, отбросить его. Из-за этого активный атакующий, манипулируя шифрованным текстом, может использовать расшифровывающий узел в качестве криптографического оракула, который постепенно раскроет весь секретный текст. Примерами алгоритмов вычисления MAC-кодов могут быть HMAC-SHA-256, основанный на хэш-функции и CBC-MAC, основная идея которого заключается в том, чтобы зашифровать сообщение с помощью блочного шифра, используя режим CBC (каждый блок зависит от предыдущего), и затем откинуть все блоки шифрованного текста кроме последнего. В этом варианте стоит опасаться использования шифрования в режиме CBC и аутентификацию CBC-MAC с одним и тем же ключом. В этом случае значение MAC будет просто равно последнему блоку шифрованного текста.

Схема генерации аутентифицированного сообщения.

TCP REPLAY

Казалось бы теперь уж точно ничто не помешает Алисе и Бобу безопасно обмениваться сообщениями. Как бы не так. Представьте себе ситуацию, когда Боб получает значение MAC(K, m), он знает, что кто-то, кому известен ключ K, подтвердил правильность сообщения m. Между тем это не обеспечивает действительной корректности сообщения. Злоумышленница Мэллори могла записать сообщение, отправленное Алисой Бобу, и затем послать копию этого сообщения Бобу когда-нибудь потом. Если система последнего не имеет специальной защиты от такого типа атак, Боб примет эту копию как корректное сообщение от Алисы. Аналогичные проблемы возникают, если Алиса и Боб применяют один и тот же ключ K для аутентификации сообщений в обоих направлениях. Мэллори может послать записанное им сообщение обратно Алисе, и та поверит, что сообщение было отправлено Бобом. Например, если перехватить зашифрованное сообщение отправленное Алисой с логином и паролем и отправить его, то можно получить несанкционированный доступ к Данным Алисы. Проблема кроется в том, что мы вычисляем MAC только на основе текста сообщения(не считая общий секрет), а нужно вычислять на основе сообщения и контекста. Для предотвращения данной атаки контекстом могут служить:

  • Идентификатор сессии (session token).
  • Метка времени (timestamp).
  • Nonce вставка.

Теперь общение между Алисой и Бобом будет выглядеть так(трафик зашифрован):

  1. Алиса посылает Бобу запрос на соединение.
  2. Боб отправляет Алисе случайное число.
  3. Алиса отвечает ее аутентификационными данными и этим же случайным числом.
  4. Боб проверяет, то же ли это число, что он отправил Алисе и делает решение на основе аутентификационных данных Алисы.

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

РЕЗЮМЕ

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

полезные ссылки:

Practical Cryptography: Niels Ferguson, Bruce Schneier – лучшая книга по криптографии, которую я читал. Рассказывает не только про математическую основу, но так же где это применить. Полезно для понимания того, на чем основана современная криптография, для чего она применима и как ей пользоваться.

Если вам нравятся мои статьи, можете следить за обновлениями с помощью E-Mail, Twitter, Facebook, а также канала в Telegram.

Share on VKTweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInEmail this to someone