
Короткое напоминание
Месяц назад я тут рассказывал, как сделал свой сервис для обмена чувствительной и приватной информацией Copy Sync - устроенный так, чтобы мой сервер физически не мог прочитать ваши пароли и ссылки. Текст шифруется прямо на вашем устройстве, на сервер уезжает уже зашифрованная каша, ключа от неё у меня нет.
Многие тогда справедливо спросили в комментах: "а ключи-то от шифрования откуда устройства берут?" Вопрос в точку. И в той статье я сам честно написал, что тут осталась слабое место. Вот её и чиню.
В чём была дыра
Объясню простым языком:
Чтобы зашифровать сообщение для вашего второго устройства, первому нужен "публичный ключ" второго, что-то вроде открытого почтового ящика, куда можно бросить письмо, но достать его может только владелец. Вопрос: откуда первое устройство этот ящик берёт? Спрашивает у сервера. У моего сервера.
И вот тут собака зарыта. А что если сервер (или тот, кто его взломал) вместо настоящего ящика вашего устройства подсунет свой? Тогда:
ваше первое устройство шифрует письмо в подставной ящик;
сервер его спокойно открывает, читает, потом перепаковывает в настоящий ящик и отправляет дальше;
второе устройство получает письмо как ни в чём не бывало.
Оба ваших устройства довольны, а посередине кто-то всё прочитал. Это называется "человек посередине" (man-in-the-middle). И самое обидное шифрование тут ни при чём, оно идеальное. Просто зашифровали не туда. А "не туда" подсунул именно тот, кому мы вроде как не должны были доверять, мой сервер.
Неприятно, что мой же сервис, про который я писал "нечем вас прочитать", в этом сценарии всё-таки мог. Так не пойдёт.
Как защититься
Способ старый и проверенный, такой же используют в Signal и WhatsApp, когда показывают "код безопасности". Идея простая:
У каждого ящика-ключа есть короткий отпечаток - набор букв и цифр, который из этого ключа однозначно вычисляется. Как отпечаток пальца: у разных ключей он разный, у одного и того же - всегда одинаковый.
Вы открываете Copy Sync на двух своих устройствах и сравниваете отпечатки глазами. Совпали - значит, между устройствами реально один и тот же ключ, никто посередине не встрял. А если сервер подсунул свой ключ - отпечаток сразу разойдётся, и вы это увидите. Подделать его нельзя: отпечаток намертво привязан к ключу.
Пять секунд работы - и MITM из "незаметно читает всё" превращается в "попадётся на первой же сверке".
А теперь - самое главное, ради чего и пишу
Когда вы сверили отпечатки и нажали "Сверено", эту галочку надо где-то запомнить. И вот тут у меня был соблазн сделать "как удобно": сохранить её на сервере, чтобы синхронизировалась между устройствами.
Я этого не сделал. Сознательно.
Смотрите. Мы защищаемся от кого? От сервера. А теперь представьте, что я бы доверил тому же серверу хранить отметку "этому ключу можно верить". Взломщик просто поставил бы галочку "проверено" своему поддельному ключу и вся защита превратилась бы в спектакль. Нельзя ставить сторожить дверь того, от кого ты эту дверь запираешь.
Поэтому галочка "сверено" живёт только в вашем браузере и на сервер не уходит вообще никогда. У этого есть приятный побочный эффект: галочка привязана к самому ключу. Если сервер завтра попробует подменить ключ, отметка "проверено" слетит сама собой, и устройство снова покажет "не сверено". Вы заметите, что что-то поменялось. Подмена ключа автоматически сбрасывает доверие - это не баг, это и есть защита.
Цена честная: сверять придётся на каждом устройстве отдельно. Но это в сто раз лучше, чем доверять "проверку" тому, кого проверяешь.
Бонусом - подключение второго устройства по QR
Заодно сделал удобную мелочь. Раньше, чтобы добавить второе устройство, надо было вводить пароль. Теперь на первом устройстве показывается QR-код, вы сканируете его вторым и всё, вы в системе. Без пароля.
И тут важная деталь в том же духе: по QR передаётся только разовый "пропуск" (живёт 5 минут, срабатывает один раз). Ключи шифрования по нему не передаются - второе устройство создаёт свои собственные, прямо у себя, и они его никогда не покидают. Так что даже перехваченный QR не даст доступа к вашим данным.
Честно о том, чего ещё нет
Как и в прошлый раз - про минусы сам, без прикрас:
Сверка ручная. Она работает, только если вы реально сравнили отпечатки. Не сравнили - защита не сработает. Я не заставляю это делать насильно, но честно: это инструмент, а не автоматический щит.
Сервис пока не предупреждает сам, если ключ вдруг сменился - он лишь снимает галочку "проверено". Автоматическое уведомление "эй, ключ поменялся!" следующая задача.
Это по-прежнему пет-проект одного человека. Веб-версия работает, расширение и мобильные приложения - в планах. Код по-прежнему весь открыт - можете сами проверить, а не верить на слово.
Посмотреть
Сайт: copysync.ru (заведите два устройства, подключите второе по QR и сверьте отпечатки — увидите всё своими глазами)
-
Исходники: gitlab.com/razgiva/copy-sync
Буду рад вопросам и критике - особенно от тех, кто шарит в безопасности. Нашли, как обойти сверку, - для меня это ценнее лайка.
А вопрос к вам такой: вы вообще когда-нибудь сверяли "код безопасности" в Signal или WhatsApp? Или это та штука, которую все видели, но никто ни разу не нажимал?