Локальный мастер-пароль с помощью ресурсоемкой хеш-функции — безопасно ли?
Прошу прокомментировать подход к созданию локального мастер-пароля.
Контекст решаемый задачи: защита обычного локального менеджера паролей. В данном случае рассматриваем вопрос исключительно надежности пароля в случае физического доступа злоумышленника к размониторованному (зашифрованному) хранилищу.
Не являясь экспертом в ИТ-безопасности и криптографии, потратив день на более глубокое изучение вопроса понял что не существует единого общепризнанного надежного метода. Например, классические советы ограничиваются "придумыванием" последовательности необычных слов и в дополнение применить некий алгоритмы замены или перестановки части символов.
Выглядеть в итоге такой пароль может и эффектно, создается ощущение надежности. Но по факту сколько есть общеупотребительных слов? 5000, 10000? А сколько существует вариантов перестановок первой буквы, добавления подчеркивания, смены раскладки (неприменимо для тач-устройств)? Ну, берем группу из 10 человек и выделяем час времени, сомневаюсь что на выходе получится более 1000 вариаций которые удастся надежно запомнить. Перемножаем эти цифры друг на друга и на длину фразы, в итоге получается не лучше чем случайный набор из 10 символов. Т.е. метод не подходит, если я ничего не упустил в логической цепочке.
В итоге для себя сформулировал два правила мастер-пароля:
1. Неподдающийся брутфорсу.
2. Достаточно запоминаемый чтобы никуда не записывать.
Дилемма в том, что пункты противоречат друг другу. В первом пароль должен быть действительно громоздким и длинным, от 20 символов. Но тогда его крайне сложно запомнить. А может ли быть пароль одновременно и длинным, и коротким? :)
Кажется, может. Берем за предположение что злоумышленнику известен хэш и алгоритмы оригинального пароля, соль отсутствует. На практике это будет не так, но даже имея софт с открытым исходным кодом (Veracrypt, например), я не имею возможность в этом убедиться. Плюс данный софт периодически обновляется, вполне могут быть ошибки и бэкдоры. Но ядро в любом случае одно - хэшированный пароль.
Математически доказано что хэши невозможно преобразовать обратно в пароль. Выглядит как достаточно надежное утверждение.
Соответственно, единственный вариант подобрать пароль - брутфорс. Естественно с применением словарей: тех самых наборов слов, фраз, стишков, вариантов перестановок и всего-всего что может придумать "средний человек". Плюс радужные таблицы. Сколько современные вычислительные устройства могут генерировать паролей в секунду, уже миллиарды? Ок. пускай будет триллион, с заделом на будущее :)
Исходя из этого появилась такая идея: брутфорс это метод грубой силы, его эффективность зависит исключительно от вычислительных возможностей (если пароль действительно случайный). А что если создавать пароль с помощью очень ресурсоемкой хеш-функции, но при этим сам "ключ" останется коротким?
Например, берем алгоритмы PBKDF2, Scrypt, Argon2 (первое что нагуглилось). Пускай будут все 3 для большей надежности. Вводим ключ "123", длину 50 символов и настройки таким образом, чтобы генерация хеша по каждому алгоритму занимала 1 секунду на среднем ПК. В идеале если ещё и оперативку будет жрать минимум 1GB (не разобрался пока возможно ли это). В итоге чтобы превратить 123 в хэш первым алгоритмом - уходит 1 сек, потом полученный 50-символьный пароль подаем как ключ и генерируем с него хэш вторым алгоритмом, потом аналогично третьим.
На выходе потрачено 3 секунды вычислительной мощи и из элементарного пароля получен 50-символьный случайный (шестнадцатеричный по факту, но его длина компенсирует этот недостаток). Который подобрать брутфорсом уже физически невозможно.
Ок, допустим злоумышленник знает что я использовал вот эти 3 алгоритма с такими-то настройками. А в криптографии принято считать что он-таки знает. Пускай у него мощностей в 1000 раз больше, в итоге методом перебора за 3 секунды злоумышленник получит 300 вариаций. Изначальный ключ 123, конечно, подобрать несложно, но что если здесь будет случайный набор из 7 символов? Пускай 1 символ это 72 вариаций, 72 в седьмой степени это 10030613004288 вариаций. При 300 вариантах за секунду нужно 1060 лет чтобы со 100% вероятностью получить этот пароль. С 1% вероятностью нужно 10 лет. Пожалуй меня устроит, учитывая что внутри нет ни миллиона биткоинов, ни кодов запуска ракет :)
В итоге на практике остается запомнить 7-значную ключевую фразу, а выбранные алгоритмы и настройки можно и записать рядом в открытом виде чтобы не усложнять себе жизнь. А также подобрать необходимый софт который в пару кликов позволит сгенерировать необходимый хеш, чтобы по затратам времени это действие не занимало больше чем ручной ввод даже 20-символьного пароля.
Бонусом получаем интересный эффект: у первоначального пароля достаточно изменить один символ (например, дописать в конце "2", "3" и т.д.) чтобы получить совершенно новый хэш. И его уже применять как конечный пароль где-то в другом месте.
Вопрос: где ошибка, почему это не будет работать?
Мне бы очень хотелось найти для себя такой алгоритм, опирающийся исключительно на математически проверенные утверждения, а не надежность какого-либо софта. Для этой цели специально взял 3 хеш-алгоритма подряд, чтобы компрометация одного не ставила под угрозу первоначальную ключевую фразу.
Ошибка №1 - "Сколько современные вычислительные устройства могут генерировать паролей в секунду, уже миллиарды?"
Можно сделать так, чтобы пароль проверялся хоть 10 минут, хоть 1 секунду (на своём ПК)
Допустим, ты сделаешь проверку в 20 секунд (для секурности), представим, что топовый суперкомпьютер может вычислить его в 100000 раз быстрее. (т.е. ~0.2 мс на пароль). Что около 5000 вариантов паролей в секунду, но не какие миллиарды уж точно)
И чтобы кто-то тратил такие огромные ресурсы на перебор пароля, он должен этого стоить (а скорее всего это не так, а значит атака в лучшем случае будет на ПК в 100-500 раз быстрее ~5-25 вариантов в секунду)
Ещё явно косяк в расчёте сложности парольных фраз, но мне пока лень считать :)
Это будет работать. Более того, примерно так и работают и VeraCrypt, и KeePass, и даже Rar. Чтобы из пароля получить ключ, которым уже зашифрованы данные, используют какую-либо KDF (key derivation function). Эта функция односторонняя, ресурсоёмкая и медленная. Она состоит из множества раундов хеширования или блочного шифрования (где результат одной итерации служит ключом для следующей, отсюда необратимость). А между итерациями туда ещё подмешивается уникальная соль, чтобы предвычисления никак не помогали ускорить процесс.
Нагугленные вами PBKDF2, Scrypt и Argon2 как раз являются такими KDF, и служат ровно для той цели, что вы озвучили: превращать относительно простой пароль в криптостойкий ключ, с защитой от брутфорса.
Да, если задрать сложность, можно получить в целом приемлемую стойкость даже с коротким паролем. Только он должен быть истинно случайным, иначе число вариантов с 72^7 сократится до гораздо более скромных величин.
Спасибо за комментарий, обнадеживающе.
Попытался сгенерировать хеш хотя бы одним из упомянутых алгоритмов и тут всплыл неприятный момент: оказывается для Windows нет подобного софта. Максимум что находится это какая-то библиотека под C++, а просто готового софта с интерфейсом не существует. Онлайн-сервисы есть, но по понятным причинам это не вариант.
В итоге в теории вроде и всё хорошо, но на практике нет инструментария для реализации :(
Здесь бы фразу посложнее с конкретными слабыми местами :)
Выглядит это всё изобретательством велосипедов и подобные решения должны делать на уровне софта, например менеджерами паролей. И они там есть. Проблема в том что настройки хеширования неподконтрольны простому юзеру и наверняка софт не рассчитан на короткие пароли в угоду производительности.
Satorisat, Вы понимаете значение слова "хеширование"?
Если - да, приведите не название, а алгоритм самой простой функции хеширования.
(которую сможете сами сделать сходу... криптостойкость - сейчас не важна и не обсуждаем её даже)