Что такое сквозное шифрование?

Практически все серверы в федеративной сети используют шифрование на транспортном уровне для доставки ваших сообщений. Это означает, что когда вы пишете статус вроде «#cofe» и нажимаете кнопку «отправить», ваш браузер отправляет зашифрованный запрос для доставки написанного сообщения на сервер. Затем ваш сервер расшифровывает полученный запрос с сообщением и так же, с использованием шифрования для запросов на транспортном уровне, отправляет его дальше, другим серверам в сети. Поэтому никто не может прочитать содержимое вашего запроса, пока он передаётся между вами и сервером, вашим сервером и остальной федеративной сетью.

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

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

Но как ваши устройства обменялись информацией об этом закрытом ключе? Есть две популярные практики.

Шифрование с открытым ключом

PGP (Pretty Good Privacy) и схожие средства шифрования называются асимметричными, потому что они используют два ключа вместо одного. Один — закрытый, который вы, исходя из названия, обязаны никому не сообщать, а другой — наоборот, открытый, доступный всем, от кого вы хотите получать зашифрованные данные. В такой системе шифрование сообщений может производиться с помощью открытого ключа, но расшифровка возможна только с помощью закрытого ключа устройства адресуемой стороны.

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

Шифрование с двойным храповиком1

мини|Храповик позволяет оси вращаться в одном направлении и не позволяет вращаться в другом. Эта практика используется в популярных мессенджерах, вроде Signal, WhatsApp, Matrix и многих других. Шифрование с двойным храповиком делает кражу ключей меньшей проблемой. В то же время оно более сложное, чем простое асимметричное шифрование.

«Храповик» — это функция, которая генерирует значения из других значений, но с помощью неё нельзя узнать результат предыдущего вычисления значения. Она используется для генерирования ключей.

f(x) = x * 2

Это функция, которая не является храповиком.

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

f(x) = md5(x)

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

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

Использование храповика

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

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

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

Использование двойного храповика

Но что если злоумышленник украдёт сам храповик? Он не сможет расшифровать предыдущие сообщения, но получит доступ ко всем будущим отправленным сообщениям. Для устранения этого недостатка введён механизм двойного храповика.

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

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

Сквозное шифрование в действии

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

Подытоживая преимущества шифрования с двойным храповиком:

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

Обычный день с шифрованием

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

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

Звучит и выглядит не так удобно, как хотелось бы. Ещё хуже, если в диалоге участвуете не только вы и ваш собеседник, а, например, ещё 200 человек. Если у вас появилось новое устройство, вам придётся верифицировать его не 2 раза (для себя и собеседника), а 202 раза. Аналогично и для каждого участвующего в этом диалоге. Конечно же, это преувеличение, которое нужно для наглядной демонстрации проблематики сквозного шифрования, делающей его неудобным и невозможным для использования в некоторых ситуациях.

Как с этим борются популярные мессенджеры? Программы вроде WhatsApp и Line делают всё по-простому, позволяя вам иметь только одно устройство. Если вы захотите перейти на другое устройство, предыдущее будет отключено без возможности переноса сообщений. Подлинность личности гарантируется с помощью номера мобильного телефона в качестве идентификатора, что делает ненужным процесс верификации. Такая система не только не подвержена проблемам, описанным ранее, но и проще для понимания пользователям.

В то же время пользователи сети Matrix могут одновременно иметь несколько устройств, историю сообщений между ними, и им не нужно подтверждать каждое новое добавленное устройство, при этом имея красивую иконку статуса, сообщающую о том, что всё является зашифрованным. Но это удобство достигается в ущерб безопасности. По документации основным протоколом шифрования в Matrix является Olm, работающий практически так же, как мы ранее описывали шифрование с двойным храповиком, как в Signal и WhatsApp. Но в действительности пользовательские сообщения зашифровываются с помощью другого протокола — Megolm, используя шифрование с одним храповиком. Этот механизм не устраняет храповик после процесса взаимного обмена сообщениями. Храповик сохраняется на устройстве в таком состоянии, чтобы с помощью него можно было расшифровать наиболее раннюю историю сообщений.

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

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

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

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

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

Но это не говорит о том, что Matrix является более худшим вариантом для использования, чем WhatsApp. Мы должны учитывать все преимущества и недостатки каждого подхода. К сожалению, такие тонкости нельзя просто объяснить конечному пользователю. Ещё более печальным фактом является то, что сквозное шифрование стало не чем-то важным, а «ещё одной» возможностью «для галочки» среди бесчисленных второстепенных задач в процессе продвижения очередного средства коммуникации. Потенциально полезные подробности о работе шифрования спрятаны от глаз пользователя, вместо которых он видит зелёный символ «всё защищено».

Федеративные сети в большинстве своём предполагают работу со множеством клиентских устройств, поэтому применить простой подход WhatsApp с единственным устройством мы не можем. Также мы не хотим бомбардировать пользователя сообщениями о верификации сотен устройств. В то же время подход Matrix потенциально является угрозой для безопасности. Что же делать?

Радикальное упрощение концепции

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

Поэтому работу шифрования в федеративных сетях можно свести к следующему виду:

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

Этот подход похож на то, что используется в WhatsApp и Line. Он простой и понятный для пользователей, потому что вместо объяснения принципа работы и всевозможных недостатков синхронизации зашифрованных сообщений между несколькими устройствами, у нас в контексте только по одному устройству каждого собеседника. Это также облегчает понимание технической причины отсутствия синхронизированной истории шифрования — потому что она хранится только на устройствах, где происходил диалог.

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

Взгляд в будущее

Без сомнений, федеративные сети, вроде ActivityPub, со временем придут к одному из предложенных вариантов шифрования.

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


  1. Русскоязычный вариант термина «double ratchet».↩︎