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 .