一、简介

3DES(三重数据加密算法)是一种对称密钥分组密码,它对每个数据块应用三次 DES 密码算法。

在本教程中,我们将学习如何 创建 3DES 密钥并使用它们在 Java 中加密和解密 String 和文件

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 = "Baeldung secret message";

接下来, 我们需要一个用加密模式、密钥和我们之前生成的初始化向量初始化的 Cipher 对象

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

请注意,我们使用的是带有CBCPKCS#5 填充方案的 TripleDES 算法。

使用 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 Baeldung message";
Path tempFile = Files.createTempFile("temp", "txt");
writeString(tempFile, originalContent);

接下来,让我们将其内容转换为单个字节数组:

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

现在,我们可以像使用 String 一样使用加密密码:

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);

六、总结

在本文中,我们学习了如何在 Java 中创建 3DES 密钥以及如何使用它来加密和解密 String 和文件。

与往常一样,所有源代码都可以在 GitHub 上获取。