Как правильно хэшировать пароли в Java?

«Как правильно хэшировать пароли в Java?» — вопрос из категории Безопасность, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для безопасного хэширования паролей в Java следует использовать специализированные алгоритмы, устойчивые к перебору. Простые хэш-функции (MD5, SHA-256) без соли небезопасны для паролей.

Рекомендуемые подходы:

  1. Использовать библиотеки, реализующие адаптивные хэш-функции:

    • BCrypt, SCrypt, Argon2 – автоматически добавляют соль и имеют настраиваемую вычислительную сложность.
    • PBKDF2 – стандартный, но менее устойчивый к GPU-атакам, чем BCrypt.
  2. Пример с 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);
  3. Пример с 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).
  • Никогда не храните пароли в открытом виде или с обратимым шифрованием.