Какой у вас практический опыт применения криптографии в Java-приложениях?

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

Ответ

Опыт включает реализацию базовых криптографических операций с использованием JCA (Java Cryptography Architecture) и JCE (Java Cryptography Extension).

Основные сценарии и алгоритмы:

  1. Симметричное шифрование (AES) для защиты конфиденциальных данных (например, токенов в БД).
  2. Хеширование (SHA-256, SHA-512) с солью (salt) для безопасного хранения паролей.
  3. Асимметричное шифрование и цифровые подписи (RSA) для верификации данных или обмена ключами.

Пример: Шифрование строки с использованием AES:

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.util.Base64;

public class AesEncryptor {
    public static String encrypt(String plainText, SecretKey key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); // Используем режим GCM для аутентификации
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] iv = cipher.getIV(); // Вектор инициализации (IV) для GCM
        byte[] cipherText = cipher.doFinal(plainText.getBytes());
        // Объединяем IV и зашифрованный текст для хранения/передачи
        return Base64.getEncoder().encodeToString(iv) + ":" + 
               Base64.getEncoder().encodeToString(cipherText);
    }
}

Пример: Хеширование пароля с солью:

import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;

public class PasswordHasher {
    public static String hashPassword(String password, byte[] salt) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(salt);
        byte[] hashedPassword = md.digest(password.getBytes());
        return Base64.getEncoder().encodeToString(hashedPassword);
    }
    // Соль должна генерироваться случайно для каждого пароля
    public static byte[] generateSalt() {
        byte[] salt = new byte[16];
        new SecureRandom().nextBytes(salt);
        return salt;
    }
}

Важные принципы безопасности:

  • Никогда не храните ключи и соли в коде. Используйте специализированные хранилища (AWS KMS, HashiCorp Vault) или защищённые файлы (Java KeyStore).
  • Используйте криптографически стойкие алгоритмы и режимы. Избегайте устаревших (DES, MD5, ECB mode).
  • Генерируйте случайные значения (IV, соль) с помощью SecureRandom.