ПРИХОДИТЕ УЧИТЬСЯ НОВОЙ ПРОФЕССИИ ЛЕТОМ СО СКИДКОЙ ДО 70%Забронировать скидку

Хеширование паролей с солью в Java: безопасное хранение

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если вам необходимо надёжно хешировать пароль в Java, вы можете использовать класс MessageDigest с алгоритмом SHA-256. Очень важно не забывать использовать уникальную "соль" для повышения безопасности вашего приложения против радужных таблиц. Вот пример реализации:

Java
Скопировать код
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);
}

При каждой генерации хэша создайте новую "соль" для каждого пользователя. Если вы это сделаете, не забудьте хранить и "соль", и хэш пароля в надёжном хранилище.

Пройдите тест и узнайте подходит ли вам сфера IT
Пройти тест

Остановимся на SHA-256

Несмотря на простоту применения SHA-256, его слишком высокая скорость создаёт уязвимости перед брутфорс-атаками. Вместо него стоит рассмотреть более надёжные альтернативы: PBKDF2, BCrypt или Argon2.

Лучшие методы: PBKDF2, BCrypt и Argon2

PBKDF2: Криптография на стероидах

Если важна высокая степень безопасности, выбирайте Password-Based Key Derivation Function 2 (PBKDF2). Этот метод сложнее, но представляет из себя достойное решение.

Java
Скопировать код
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 и автоматически генерирует "соль".

Java
Скопировать код
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:

Java
Скопировать код
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);

Валидация паролей

Для проверки введённого пароля при авторизации извлеките сохранённый хэш и "соль", а затем сравните их с данными, полученными от пользователя:

Java
Скопировать код
boolean passwordMatch(String enteredPassword, String savedHash, byte[] salt) throws Exception {
    String hashedEnteredPassword = hashWithSalt(salt, enteredPassword);
    return hashedEnteredPassword.equals(savedHash);
}

Полезные материалы

  1. Java Cryptography Architecture (JCA) Reference Guide — официальное руководство Oracle.
  2. OWASP Password Storage Cheat Sheet — рекомендации по хранению паролей от экспертов OWASP.
  3. jBCrypt — руководство по прочному хешированию паролей с использованием jBCrypt.
  4. Best way to store password in database – Stack Overflow — обсуждение на форуме Stack Overflow о безопасном хранении паролей.
  5. Password Encoding in Spring Security — примеры использования кодирования паролей в Java-веб-приложениях от профессионалов.