Нужно ли хранить исходный пароль в базе
Что проверяют
Это вопрос-фильтр: ответ должен прозвучать сразу и без оговорок. Дальше смотрят, отличаете ли вы хеширование от шифрования, знаете ли, почему обычный хеш тут не годится, и пользуетесь ли готовыми механизмами вместо самописных.
Как отвечать
Исходный пароль не хранится ни открытым текстом, ни в обратимо зашифрованном виде. Хранится результат специальной медленной хеш-функции с солью:
- Argon2id как основной выбор сегодня, bcrypt и scrypt как проверенные временем варианты, PBKDF2 там, где нужен сертифицированный алгоритм;
- соль уникальна для каждого пользователя и берётся из криптографического источника случайности; bcrypt и Argon2 кладут её прямо в строку хеша, отдельная колонка не нужна;
- параметры стоимости подбираются так, чтобы одна проверка занимала заметное время, и пересматриваются по мере роста железа.
В Spring Security всё это закрывает PasswordEncoder:
PasswordEncoder enc = PasswordEncoderFactories.createDelegatingPasswordEncoder();
String stored = enc.encode(raw);
boolean ok = enc.matches(raw, stored);DelegatingPasswordEncoder пишет в хеш префикс алгоритма, поэтому перейти на новый можно постепенно, перехешируя пароль при очередном успешном входе.
Где спотыкаются
Называют SHA-256 с солью и считают вопрос закрытым. Быстрая функция и задумана быстрой: перебор на видеокарте идёт миллиардами вариантов в секунду, а соль спасает от готовых радужных таблиц, но не от перебора пароля конкретного пользователя.
Предлагают шифровать, чтобы уметь показать пароль владельцу. Обратимость означает, что ключ лежит рядом, а сама задача надумана: пользователю нужен не старый пароль, а сброс по одноразовой ссылке с коротким сроком жизни.
Забывают про всё вокруг хранения: пароль, попавший в лог или в текст исключения, отсутствие ограничения на число попыток, разные ответы на «нет такого пользователя» и «неверный пароль», по которым чужие логины перебираются за вечер.