Перейти к основному содержимому

3DES в Java

· 4 мин. чтения

1. Введение

3DES или алгоритм тройного шифрования данных — это блочный шифр с симметричным ключом, который трижды применяет алгоритм шифрования DES к каждому блоку данных.

В этом руководстве мы узнаем, как создавать ключи 3DES и использовать их для шифрования и дешифрования строк и файлов в Java.

2. Генерация секретного ключа

Генерация секретного ключа 3DES требует нескольких шагов. Во-первых, нам нужно сгенерировать секретный ключ, который будет использоваться для процесса шифрования-дешифрования. В нашем случае мы будем использовать 24-байтовый ключ, составленный из случайных чисел и букв:

byte[] secretKey = "9mng65v8jf4lxn93nabf981m".getBytes();

Обратите внимание, что секретный ключ не должен быть общедоступным .

Теперь мы завернем наш ключ в SecretKeySpec , объединив его с выбранным алгоритмом:

SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "TripleDES");

В нашем случае мы используем TripleDES , который является одним из стандартных алгоритмов безопасности Java .

Еще один элемент, который мы должны сгенерировать заранее, — это вектор инициализации для нашего ключа . Мы будем использовать 8-байтовый массив случайных чисел и букв:

byte[] iv = "a76nb5h9".getBytes();

А затем мы обернем его в класс IvParameterSpec :

IvParameterSpec ivSpec = new IvParameterSpec(iv);

3. Шифрование строк

Теперь мы готовы зашифровать простые значения String . Давайте сначала определим строку , с которой мы будем работать:

String secretMessage = "ForEach secret message";

Далее нам понадобится объект Cipher , инициализированный режимом шифрования, секретным ключом и вектором инициализации , который мы сгенерировали ранее:

Cipher encryptCipher = Cipher.getInstance("TripleDES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);

Обратите внимание, что мы используем алгоритм TripleDES с CBC и схемой заполнения PKCS#5 .

С помощью Cipher мы можем запустить метод doFinal для шифрования нашего сообщения . Обратите внимание, что он работает только с массивом байтов , поэтому нам нужно сначала преобразовать нашу строку :

byte[] secretMessagesBytes = secretMessage.getBytes(StandardCharsets.UTF_8);
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessagesBytes);

Теперь наше сообщение успешно зашифровано. Если мы хотим сохранить его в базе данных или отправить через REST API , было бы удобнее закодировать его с помощью алфавита Base64 :

String encodedMessage = Base64.getEncoder().encodeToString(encryptedMessageBytes);

Кодировка Base64 делает сообщение более читабельным и удобным для работы.

4. Расшифровка строк

Теперь давайте посмотрим, как мы можем обратить процесс шифрования и расшифровать сообщение в его исходную форму. Для этого нам понадобится новый экземпляр Cipher , но на этот раз мы инициализируем его в режиме расшифровки :

Cipher decryptCipher = Cipher.getInstance("TripleDES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);

Далее мы запустим метод doFinal :

byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);

Теперь мы декодируем результат в строковую переменную:

String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);

Наконец, мы можем проверить результаты, чтобы убедиться, что процесс дешифрования выполняется правильно, сравнив его с начальным значением:

Assertions.assertEquals(secretMessage, decryptedMessage);

5. Работа с файлами

Мы также можем зашифровать целые файлы. В качестве примера создадим временный файл с текстовым содержимым:

String originalContent = "Secret ForEach message";
Path tempFile = Files.createTempFile("temp", "txt");
writeString(tempFile, originalContent);

Далее преобразуем его содержимое в однобайтовый массив:

byte[] fileBytes = Files.readAllBytes(tempFile);

Теперь мы можем использовать шифровальный шифр так же, как мы это делали со строкой :

Cipher encryptCipher = Cipher.getInstance("TripleDES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes);

Наконец, давайте перезапишем содержимое файла новыми зашифрованными данными:

try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(encryptedFileBytes);
}

Процесс расшифровки очень похож. Единственное отличие состоит в том, что шифр инициализируется в режиме расшифровки:

encryptedFileBytes = Files.readAllBytes(tempFile);
Cipher decryptCipher = Cipher.getInstance("TripleDES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes);

Еще раз перезапишем содержимое файла — на этот раз расшифрованными данными:

try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(decryptedFileBytes);
}

В качестве последнего шага мы можем проверить, соответствует ли содержимое файла исходному значению:

String fileContent = readString(tempFile);
Assertions.assertEquals(originalContent, fileContent);

6. Резюме

В этой статье мы узнали, как создать ключ 3DES в Java и как использовать его для шифрования и дешифрования строк и файлов.

Как всегда, весь исходный код доступен на GitHub .