Ответ
Для безопасного хэширования паролей в Java следует использовать специализированные алгоритмы, устойчивые к перебору. Простые хэш-функции (MD5, SHA-256) без соли небезопасны для паролей.
Рекомендуемые подходы:
-
Использовать библиотеки, реализующие адаптивные хэш-функции:
- BCrypt, SCrypt, Argon2 – автоматически добавляют соль и имеют настраиваемую вычислительную сложность.
- PBKDF2 – стандартный, но менее устойчивый к GPU-атакам, чем BCrypt.
-
Пример с Spring Security BCrypt (наиболее распространён):
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12); // strength factor String rawPassword = "userPassword123"; String hashedPassword = encoder.encode(rawPassword); // Автоматически генерирует соль // Проверка пароля boolean matches = encoder.matches(rawPassword, hashedPassword); -
Пример с Java's
MessageDigest(НЕ рекомендуется для паролей, только для демонстрации):import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Base64; public static String hashWithSalt(String password) throws Exception { SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.nextBytes(salt); MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(salt); byte[] hashedBytes = md.digest(password.getBytes()); // Сохраняем соль вместе с хэшем (например, salt:hash) return Base64.getEncoder().encodeToString(salt) + ":" + Base64.getEncoder().encodeToString(hashedBytes); }
Ключевые принципы:
- Всегда используйте криптографически стойкую случайную соль.
- Выбирайте алгоритм с настраиваемой стоимостью (work factor).
- Никогда не храните пароли в открытом виде или с обратимым шифрованием.