Мне не нравились существующие менеджеры паролей: неудобно синхронизировать базу паролей между различными устройствами и операционными системами, к тому же, зачастую программы-менеджеры откровенно плохо защищены. Однажды я читал статьи по криптографии, и мне пришла в голову мысль: а почему бы не сделать менеджер паролей, который вместо хранения паролей будет вычислять их?
Первый вариант реализации этой идеи, приходящий на ум — криптографические хеш-функции. На первый взгляд, всё круто: выбираем стойкую функцию (скажем, SHA-3 в 224-битной версии), подаём ей на вход мастер-пароль qwerty и тип аккаунта vk, на выходе мгновенно получаем 56 символов из набора 0123456789abcdef. Я сходу нашёл два подобных проекта: взломанный и потенциально взламываемый. В таком подходе есть большая проблема: криптографические хеш-функции проектируются в том числе с целью быть максимально быстрыми и нетребовательными к ресурсам, и поэтому можно устроить словарный или полный перебор мастер-пароля по перехваченному паролю для одного сайта на CPU (относительно медленно), GPU, FPGA (куда быстрее), ASIC (очень быстро). Для проведения таких атак на популярные алгоритмы хеширования без использования подсаливания можно использовать также радужные таблицы, сильно ускоряющие процесс взлома на CPU.
К счастью, есть другой вариант реализации — функции получения ключей. В двух словах, они выполняют хеширование, но относительно медленно (скажем, одну секунду на обычном процессоре) и с относительно большим потреблением ресурсов (скажем, 16 мегабайт оперативной памяти), чтобы максимально затруднить атаки полным и словарным перебором. Среди знакомых мне современных функций PBKDF2, bcrypt и scrypt лучше всего выглядела scrypt: созданная с учётом опыта первых двух, успешно противостоящая вычислениям на графических процессорах и микросхемах (как FPGA, так и ASIC) и рассчитанная на гибкость при настройке под любые задачи. Я подумывал над реализацией этого проекта, но почему-то задвинул его в долгий ящик. И очень напрасно.
Криптограф Надим Кобеисси сделал как раз такой менеджер паролей npwd на JavaScript (работает как десктопное приложение через Node.JS). Я установил утилиту на компьютер под Linux и под Windows, а также на ноутбук под Linux, начал боевое использование, и мне очень понравилось. Вводишь единственный мастер-пароль и тип аккаунта (например, «twitter») в приложение, и через пару секунд в твоём буфере обмена уже лежит вычисленный сложный пароль конкретно для этого аккаунта, причём взломать твой мастер-пароль (читай: все твои пароли) по паролю для одного аккаунта будет очень, очень сложно.
Но была и проблема. Версия под Windows действительно выдавала пароль через пару секунд, а вот под Linux (в том числе на том же самом компьютере!) для вычислений требовалось уже секунд 15, что напрягало. Сначала я просто уменьшил одну константу, сделав мастер-пароль менее защищённым, но потом я подумал — а почему бы не переписать приложение на C, ведь наверняка будет работать гораздо быстрее! Особенно меня подзадоривала мысль, что у меня давно был замысел этого проекта, но я стормозил, и кто-то реализовал его до меня.
Через несколько дней неспешной работы я сделал свой менеджер паролей cpwd, полностью совместимый с оригиналом. Это было весело! После небольшой оптимизации мне удалось достичь желанной высокой скорости работы. Портировать cpwd под Windows я не пробовал, но это должно быть несложно. На GitHub-странице проекта я собрал коллекцию ссылок на подобные проекты в академическом мире и за его пределами – оказалось, что идея вообще-то весьма стара.
Конечно, это не серебряная пуля, но it works for me. В процессе использования я наткнулся на проблему: некоторые сайты имеют интересные требования к паролям типа «не более 20 символов», «обязательно встречается большая буква, маленькая буква, цифра и спецсимвол», в результате сгенерированный npwd/cpwd пароль иногда требует доработки руками перед вводом. К счастью, таких сайтов немного.
Оригинал опубликован в моём блоге 7.08.15. Прошло 5 лет, а я до сих пор пользуюсь этой утилиткой.
lrrr11
хотел написать про Argon2, но
понятно, его тогда просто не было)