Хеширование паролей с солью в Java: безопасное хранение
Быстрый ответ
Если вам необходимо надёжно хешировать пароль в Java, вы можете использовать класс MessageDigest
с алгоритмом SHA-256
. Очень важно не забывать использовать уникальную "соль" для повышения безопасности вашего приложения против радужных таблиц. Вот пример реализации:
import java.security.MessageDigest;
import java.util.Base64;
String hashWithSalt(byte[] salt, String password) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(salt);
byte[] hashedPassword = md.digest(password.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(hashedPassword);
}
При каждой генерации хэша создайте новую "соль" для каждого пользователя. Если вы это сделаете, не забудьте хранить и "соль", и хэш пароля в надёжном хранилище.
Остановимся на SHA-256
Несмотря на простоту применения SHA-256, его слишком высокая скорость создаёт уязвимости перед брутфорс-атаками. Вместо него стоит рассмотреть более надёжные альтернативы: PBKDF2, BCrypt или Argon2.
Лучшие методы: PBKDF2, BCrypt и Argon2
PBKDF2: Криптография на стероидах
Если важна высокая степень безопасности, выбирайте Password-Based Key Derivation Function 2 (PBKDF2). Этот метод сложнее, но представляет из себя достойное решение.
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import java.util.Base64;
String generateStrongPasswordHash(String password) throws Exception {
int iterations = 10000;
char[] chars = password.toCharArray();
byte[] salt = getSalt();
PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, 64 * 8);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
byte[] hash = skf.generateSecret(spec).getEncoded();
return Base64.getEncoder().encodeToString(hash);
}
private static byte[] getSalt() throws Exception {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[16];
sr.nextBytes(salt);
return salt;
}
Не забывайте хранить количество итераций, "соль" и хэш в вашей базе данных. Чем больше количество итераций, с которым работает алгоритм, тем более трудозатратным становится его взлом.
BCrypt: Баланс надёжности и простоты
BCrypt имеет в своей основе модифицированный алгоритм Blowfish и автоматически генерирует "соль".
import org.mindrot.jbcrypt.BCrypt;
String hashPassword(String plainPassword){
return BCrypt.hashpw(plainPassword, BCrypt.gensalt(12));
}
boolean verifyPassword(String plainPassword, String hashedPassword) {
return BCrypt.checkpw(plainPassword, hashedPassword);
}
Argon2: Авангард технологии хеширования
Argon2 был признан лучшим методом хеширования паролей и сегодня он считается современным стандартом в области безопасности.
Визуализация
Перевод пароля в хешированный вид можно сравнить с присвоением ему уникального отпечатка, который крайне сложно подделать.
До хеширования: "OpenSesame"
После хеширования: сложный и уникальный хэш
Каждый ввод непременно даёт уникальный хешированный вывод, подобно уникальности снежинок.
Шторм из "солей" и хешей
Соли: секретный ингредиент безопасности
Сгенерируйте "соль" при помощи SecureRandom
:
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
Валидация паролей
Для проверки введённого пароля при авторизации извлеките сохранённый хэш и "соль", а затем сравните их с данными, полученными от пользователя:
boolean passwordMatch(String enteredPassword, String savedHash, byte[] salt) throws Exception {
String hashedEnteredPassword = hashWithSalt(salt, enteredPassword);
return hashedEnteredPassword.equals(savedHash);
}
Полезные материалы
- Java Cryptography Architecture (JCA) Reference Guide — официальное руководство Oracle.
- OWASP Password Storage Cheat Sheet — рекомендации по хранению паролей от экспертов OWASP.
- jBCrypt — руководство по прочному хешированию паролей с использованием jBCrypt.
- Best way to store password in database – Stack Overflow — обсуждение на форуме Stack Overflow о безопасном хранении паролей.
- Password Encoding in Spring Security — примеры использования кодирования паролей в Java-веб-приложениях от профессионалов.