Как безопасно авторизироваться в веб-сервисе через скомпрометированное устройство?
Поискав в интернете, побеседовав с ИИ, можно выделить bullet-proof технологию многофакторной авторизации. «Добавь TOTP и спи спокойно», говорят они. Но что, если у вас только одно устройство, и оно скомпрометировано? Например, вы едете в путешествие и берёте с собой только телефон. Можете ли вы доверять вашему телефону? Можете ли вы с него ввести пароль и с него же сгенерировать TOTP?
Мне показалось, что собственному телефону я верить не могу (особенно после того, как удалив приложение одной нехорошей соцсети, через пару недель я обнаружил, что приложение снова установлено). Я задался вопросом безопасной авторизации на скомпрометированном устройстве.
В голову сразу пришла идея шифрования в уме: авторизатор выдаёт вам контрольное слово, вы в уме его шифруете алгоритмом, который знаете только вы и авторизатор, и в качестве пароля вписываете результат шифрования (или хэширования). Но можно ли шифровать в уме?
Простые алгоритмы шифрования
Шифр Цезаря. Ключ — это число. Суть — сдвиг каждой буквы слова на число из ключа по алфавиту. Шифровать в уме — вполне реально, надо только помнить алфавит. Но надёжности здесь практически нет. Любой аналитик раскусит алгоритм моментально. (подробнее тут)
Шифр Виженера. Это прокачанный Цезарь, в котором вместо ключа из 1 числа используется ключ из последовательности чисел. Например, первую букву сдвигаем на 2 символа, вторую на 8, третью на 1, и дальше по кругу. Если у Цезаря, подставляя одни и те же буквы, будем получать одни и те же буквы шифра (например, любая буква «А» в любом месте всегда будет буквой «Г»), то в случае Виженера шифр становится не таким очевидным. (подробнее тут)
Шифр Плейфера. Не хочу углубляться в суть этого метода, просто скажу, что для его использования необходимо запомнить максимально длинную ключевую фразу из неповторяющихся букв и запомнить оставшиеся в алфавите буквы. Причём запомнить это в виде матрицы 5 на 5. Фишка этого метода в том, что шифруются не буквы за буквой, а пары букв. В итоге, частотному анализу придётся собирать данные не для 25 букв, а для 25×25=625 пар букв. Но… шифровать в уме по такому алгоритму будет крайне некомфортно. (подробнее тут)
Остальные рассматриваемые мной алгоритмы становились только сложнее, от чего я решил бросить это дело и подумать над изобретением собственного велосипеда.
Собственный алгоритм
За основу я решил взять Виженера
Вместо алфавита я решил взять случайную последовательность букв (вместо «АБВГ», «ВАГБ»)
Чтобы проще было запомнить эту последовательность букв, я решил взять обычный текст и в нём использовать первое упоминание нужной буквы. (такая схема не позволит нормально дешифровать текст, но оно нам и не надо. Другими словами, с этого этапа мы не шифруем, а хэшируем)
Чтобы защититься от тупых частотных анализаторов, ключом будет являться самая новая статья на Habr
Чтобы окончательно поломать любую адекватную аналитику, добавляем зависимость со второй по свежести статьёй.
Пример
Итак, нам надо зашифровать слово «pass», которое выдал нам сервер.
Ключ Виженера — пин-код от текущей банковской карты — 6113.
Текст первой статьи:
Привет! За клавиатурой Влад Калашников, Senior Product Designer в стартапе Re: Luna, до этого работал в МТС и Pinkman. 6 лет занимаюсь дизайном и 4 года продуктовом. Недавно в своем телеграм-канале писал о том, как я сделал портфолио во Framer. Решил написать чуть более расширенную мини-статью на эту тему с картинками.
Текст второй статьи:
Привет, Хабр! Меня зовут Дарья Фролова. Я редактор в МТС Диджитал, а еще — родитель, который старается подбрасывать детям полезный контент получается не всегда.
Ищем в статье первое упоминание каждой буквы, в первой статье, сдвигаем всё на числа из пин-кода, полученную букву ищем во второй статье и сдвигаем ещё раз.
Итак:
Pass
П со сдвигом в 6 в первой статье превращается в З.
З со сдвигом в 6 во второй статье превращается в А.
pAss
А со сдвигом в 1 в первой статье превращается в К.
К со сдвигом в 1 во второй статье превращается в Т.
paSs
С со сдвигом в 1 в первой статье превращается в Т.
Т со сдвигом в 1 во второй статье превращается в Х.
pasS
С со сдвигом в 3 в первой статье превращается в Р.
Р со сдвигом в 3 во второй статье превращается в Е.
Так проделываем с каждой буквой и получаем: ATHE (латиницей).
То же самое проделывает и наш сервер авторизации, и если шифровка совпадает, впускает нас.
Чтобы наш пароль не ввели сразу через секунду после нас, превращаем его в OTP и вычёркиваем из списка. Чтобы войти повторно, берём самую актуальную статью из тех, которые ещё не использовали. Думаю, в рамках частоты обновления статей, у нас в памяти будут оставаться статьи, которые мы уже использовали.
И после всего этого ещё остаётся огромный потенциал для творчества по улучшению алгоритма, например:
время публикации статьи в перемешку с пин-кодом в качестве ключа
ротация разных новостных порталовучитывание знаков препинания
персонифицированное преобразование кириллицы в латиницу (например, буква «Ю» может быть превращена в «yu», может в «u», а может в »1–0», как придумаете)
использовать TOTP с длинным временным интервалом вместо пина
Заключение
Думаю, подобная штука может помочь для авторизации на скомпрометированном девайсе, но также предполагаю, что использование такой штуки примерно настолько же неадекватно, как ношение шапки из фольги. Тем не менее, размышления над подобным алгоритмом мне показались забавными и достойными публикации.