Comments 44
Без описания PBKDF2, bcrypt (хотя упоминание есть), scrypt, Argon2 пост выглядит неполным
Ему неизвестна глобальная соль, поэтому ее придется брутить.
Но ещё есть вариант, когда конфиг с солью тоже сливается через какую-нибудь RCE-уязвимость (или даже тупо по недосмотру с неправильно настроенными правами на файл, пару раз и на такое натыкался)
Не сказано про методики на уровне архитектуры — создание небольших микросервисов с задачами "регистрация/логин/удаление", аудит которых прост и дёшев, а выкачивание базы хешей соответственно требует взлома микросервиса, доступного извне, и постоянных запросов к этому микросервису авторизации (привет сетевым экранам и эвристическому анализу трафика между микросервисами). Плюс — hash blinding каким нибудь hmac перед внесением в базу с хранением ключа от блиндинга в HSM.
meh.
Когда встал вопрос хранения паролей, конечно, первой идеей было просто записывать их в открытом виде в соответствующей табличке в базе данных.
Очень плохо, что в 2018 году это все еще первая идея.
В мире .net есть такая штука как Identity. Там сразу и хранение и изменение и бан. Рекомендую обратить внимание, если гвоздями не прибиты к php.
В то же время есть усовершенствованный вариант хэширования хэша: hash(перец+hash(pass+соль)). Где соль уникальна для каждого пользователя, а перец — для каждой попытки авторизации, и выдается сервером.
Одним из требований к хэш-функциям же является быстрота выполнения.
Нет такого требования. Различие в том, что шифрование обратимо и будет иметь переменную длину в зависимости от исходных данных, хэш же необратим и в результате вычисления будет фиксированного размера блок.
Если уж говорить про php — то из-за безалаберного отношения к паролям в ядро давно уже включили обёртку password_hash. И использовать надо именно это.
Несколько дополнений.
Про соль не сказано, почему же она мешает построить радужные таблицы. Тут все очень просто, соль — это удлинитель пароля. Чем длиннее пароль, тем больше ресурсов требует построение таблиц… вплоть до полной невозможности их построить на существующем железе. То, что эта "часть пароля" открыта — ничего не меняет, ибо она случайна, а значит радужные таблицы нужно строить для всех вариантов.
- Как уже сказали, пропущен важный момент, почему bcrypt и argon2, а не, например, sha256 с кучей итераций. Как было упомянуто, что есть подбор на GPU и подобном. Вот эти алгоритмы и пытаются "ставить палки в колеса" таким подборам за счет повышения затрат на оперативную память (например, у многоядерных GPU память каждого ядра очень мала, а если каждое ядро начнет обращаться к общей памяти, то скорость подбора стает тех же порядков, что и у CPU).
Ну и 3. По поводу придумывания своих алгоритмов, хешей от хешей и т.п. Не делайте так. В криптографии много нюансов, о которых вы не знаете. Например, Timing attack. Используйте проверенные инструменты, предназначенные именно для хеширования и проверки паролей.
Тут все очень просто, соль — это удлинитель пароля.Красивый бред, Вы сами до этого дошли или кто-то подсказал? Не говорите так больше при людях… Учитывая фиксированную длину выходной последовательности и возможность коллизии с прообразом произвольной длины (не обязательно тоже большой) этот удлинитель можно было бы засунуть очень далеко и глубоко. Соль изначально предназначалась для защиты от простого поиска повторений прообразов (слили базу, узнали/угадали/перебрали 1 простой пароль, а потом выборкой или визуальным осмотром нашли кучу коллег по несчастью для первого бедолаги) с чем она успешно справляется по сей день.
Видимо вы слишком молоды, что бы знать о радужных таблицах.
Говорить о криптографии с человеком, говорящим о подборе пароля через коллизии? Смешно.
В криптографии много нюансов, о которых вы не знаете.
Ну вы же сами сказали, что длинная соль плохо, ибо "возможность коллизии". Но, видимо, вы совсем не это имели ввиду, а что имели, то не в виду ;) Видимо вас волнует вероятность коллизии… или нет? Уж объяснитесь.
Советую убрать свой апломб, включить голову и рассказать, как соль увеличивает вероятность коллизии (подсказка — соль известна, соль должна находиться в найденной коллизии именно там, куда ее поставил алгоритм хеширования).
Ну вы же сами сказали, что длинная соль плохо, ибо «возможность коллизии».Интересный плод Вашего воображения. Такого в мою голову даже придти не могло… Я говорил, что ОЦЕНКА соли, как удлинителя — мимо темы. И я ни как не оценивал плоха длинная соль или хороша.
Конкретно имелось ввиду, что добавление соли несёт не тупо «удлинительный» характер, а увеличивает энтропию. И поэтому говорить «с солью длиннее! А значит лучше» — бред, учитывая, что хеш-функция в итоге свернёт, что 5, что 25 символов — ей без разницы. И не гарантируется, что именно вот к этим 25 нет коллизии, скажем, с прообразом гораздо меньшей длины. И поэтому оценка длины прообраза (с солью или без) практически ни какого смысла не имеет (ну за исключением защиты от тупого перебора (полного или по словарю).
Конечно длина увеличится — это факт. Но это не ставилось целью в идеи подсаливания хешей. Повторяю — в первую очередь это защита от простого поиска повторений прообразов. Всё остальное — следствия.
hmac384 или sha384(пароль+глобальное чтонить). Про потери перфоманса… только на тестах в вакууме.
Разве многократное хеширование не увеличивает вероятность коллизий?
Об этом можно прочитать здесь: habr.com/post/100301
Это действительно помогает?
Я для своего сервиса сделал просто хэш(индивидуальная_соль+хэш(хэш(имя_пользователя)+хэш(пароль_пользователя)))
Неужели этого недостаточно?
Смотря какой хэш. Но, подозреваю, такой, что будет перебираться на хорошем GPU очень быстро.
Для сравнения: в Django по умолчанию используется PBKDF2, в котором SHA256-хэш хэширует 150000 (прописью: сто пятьдесят тысяч) раз подряд
Чтобы на GPU не перебрали, очевидно же :)
Я тут по случайному совпадению запустил перебор одного md5-хэша за пару дней до этого поста — на дохлом ноутбучном GPU. 8 и 9 символов уже перебраны, 10 символов переберутся через полтора месяца. Если обзавестись хотя бы двумя хорошими нвидиями, можно будет и 10 символов за пару дней перебрать) И это если не вспоминать пришедшие из мира криптовалют ASIC и FPGA, которые заточены именно для такого перебора (только в контексте всяких там блокчейнов, но по сути то же самое).
А соль и имя пользователя никак не затруднят перебор — они же заранее известны, и злоумышленник исследователь просто сразу их подставит в алгоритме, перебирая только собственно пароль
А соль и имя пользователя никак не затруднят перебор — они же заранее известны, и злоумышленник исследователь просто сразу их подставит в алгоритме, перебирая только собственно пароль
Только если знает алгоритм конкатенации промежуточных строк, да?
Безопасность через неясность это плохо, стоит автоматически предполагать, что вместе с базой слит и код сайта, в котором есть этот алгоритм (к тому же мне самому доводилось сливать код сайтов пару раз, хех)
Извиняюсь, я просто в теме профан, но в качестве хобби пилю клиент-серверную игру, и вот как раз недавно делал систему авторизации)
А в чём принципиальная разница-то? С точки зрения сливов сервер игры тоже не обязательно безопасен и теоретически может обеспечить слив через какую-нибудь дырку. Разница разве что в нагрузке алгоритма на сервер, но у PBKDF2 даже с 150000 итераций нагрузка всё равно небольшая — это не какой-нибудь Argon2, который придуман специально чтобы выжирать и проц, и оперативку)) (а придуман он тоже именно для того, чтобы затруднить перебор на GPU)
Ну или можно включить режим неуловимого Джо и заявить что-то вроде «да кому нахрен нужен этот мой сервер игры, никто ничего подбирать не будет». Именно по этому принципу на двух моих старых сайтах до сих пор используются несолёные md5 и sha1 :D
Хотя с другой стороны vladbarcelo в комментах выше предлагает вынести аутентификацию в микросервис, и это в принципе может немного защитить как базу, так и алгоритм. Но зачем, когда можно просто взять хороший алгоритм, который достаточно надёжен, даже если он всем известен? Тот же PBKDF2 хотя бы
никак не затруднят перебор
Разница очевидна если конечная цель подобрать пароли пользователей. Сравните:
ХЕШ("12345") ->
нашли 29 пользователей с таким паролем.ХЕШ("12345" + ИНДИВ.СОЛЬ) ->
нашли 1 пользователя с таким паролем. Но ещё нужно обнаружить 28 пользователей с таким же паролем, но другим итоговым хешем.Чтобы вычислительную сложность повысить.
Интересно, если хранить в БД не соленые многораундные хэши, а зашифрованную пару соль+хэш пароля. Можно также делать многораундное шифрование. Можно даже шифровать ассиметрично и хранить приватный ключ рядом с БД.
Плюсы: 1) асиметричный шифр более ресурсоемкий, чем любой хэш, и плохо брутится. 2) По определению нет радужных таблиц. 3) Даже, если сольют базу и приватный ключ, в лучшем случае получат хэш пароля и соль
По-моему намного проще будет просто вынести всю аутентификацию в микросервис без всяких шифрований, как vladbarcelo предлагал. А уж микросервис может располагаться хоть на условном «токене», хоть вообще в другой стране — фиг сольёшь, даже если основной сайт сольют целиком
Про хранение паролей в БД