Криптография в Java: шифрование и хеширование – практическое руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Криптография в Java: шифрование и хеширование – полное руководство

Криптография — фундаментальная основа безопасности современных приложений. В Java встроена мощная и гибкая инфраструктура для работы с шифрованием и хешированием — Java Cryptography Architecture (JCA) и Java Cryptography Extension (JCE). Эти библиотеки позволяют реализовать как симметричное (AES), так и асимметричное (RSA) шифрование, а также криптографическое хеширование (SHA-256). В этой статье мы разберем ключевые концепции и напишем рабочие примеры на чистом Java (без сторонних зависимостей).

Основные понятия и архитектура JCA/JCE

JCA предоставляет каркас для работы с криптографическими операциями. Ключевая идея — провайдеры (providers), которые реализуют конкретные алгоритмы. По умолчанию JDK включает провайдер SUN (для хешей) и SunJCE (для шифрования). Основные классы находятся в пакете javax.crypto и java.security.

  • Cipher — основной класс для шифрования и дешифрования.
  • KeyGenerator — генерация симметричных ключей.
  • KeyPairGenerator — генерация пар ключей для асимметричного шифрования.
  • MessageDigest — вычисление хеш-сумм.
  • SecretKeySpec — представление симметричного ключа из массива байт.

Симметричное шифрование: AES

AES (Advanced Encryption Standard) — самый популярный симметричный алгоритм. Использует один и тот же ключ для шифрования и дешифрования. Рекомендуемый режим — GCM (аутентифицированное шифрование) или CBC с PKCS5Padding. Ниже пример шифрования строки с использованием AES-256/GCM.

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AESGCMExample {
    private static final int AES_KEY_SIZE = 256;
    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 128;

    public static SecretKey generateKey() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(AES_KEY_SIZE, SecureRandom.getInstanceStrong());
        return keyGen.generateKey();
    }

    public static String encrypt(String plaintext, SecretKey key) throws Exception {
        byte[] iv = new byte[GCM_IV_LENGTH];
        SecureRandom.getInstanceStrong().nextBytes(iv);
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);
        byte[] cipherText = cipher.doFinal(plaintext.getBytes());
        byte[] encrypted = new byte[iv.length + cipherText.length];
        System.arraycopy(iv, 0, encrypted, 0, iv.length);
        System.arraycopy(cipherText, 0, encrypted, iv.length, cipherText.length);
        return Base64.getEncoder().encodeToString(encrypted);
    }

    public static String decrypt(String encryptedData, SecretKey key) throws Exception {
        byte[] decoded = Base64.getDecoder().decode(encryptedData);
        byte[] iv = new byte[GCM_IV_LENGTH];
        System.arraycopy(decoded, 0, iv, 0, iv.length);
        byte[] cipherText = new byte[decoded.length - iv.length];
        System.arraycopy(decoded, iv.length, cipherText, 0, cipherText.length);
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        return new String(cipher.doFinal(cipherText));
    }

    public static void main(String[] args) throws Exception {
        SecretKey key = generateKey();
        String original = "Привет, мир!";
        String encrypted = encrypt(original, key);
        String decrypted = decrypt(encrypted, key);
        System.out.println("Оригинал: " + original);
        System.out.println("Зашифровано: " + encrypted);
        System.out.println("Расшифровано: " + decrypted);
    }
}

В примере мы генерируем 256-битный ключ, добавляем случайный IV (вектор инициализации) и используем режим GCM, который обеспечивает проверку целостности. Результат кодируется в Base64 для удобства передачи.

Асимметричное шифрование: RSA

RSA использует пару ключей: открытый (public) для шифрования и закрытый (private) для дешифрования. Обычно RSA применяют для шифрования небольших данных (например, ключей сессии). Размер ключа — 2048 или

Рекомендаций