3DES in Java – Java中的3DES

最后修改: 2021年 6月 28日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

3DES or Triple Data Encryption Algorithm is a symmetric-key block cipher that applies the DES cipher algorithm three times to each data block.

3DES或Triple Data Encryption Algorithm是一种对称密钥的区块密码,它将DES密码算法应用于每个数据块三次。

In this tutorial, we’ll learn how to create 3DES keys and use them for encrypting and decrypting Strings and files in Java.

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

2. Generating Secret Key

2.生成秘钥

Generating a 3DES secret key requires a couple of steps. First, we’ll need to generate a secret key that will be used for the encryption-decryption process. In our case, we’ll use a 24-byte key constructed from random numbers and letters:

生成一个3DES秘钥需要几个步骤。首先,我们需要生成一个秘密密钥,用于加密-解密过程。在我们的例子中,我们将使用一个由随机数字和字母组成的24字节的密钥。

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

Note that a secret key shouldn’t be shared publicly.

请注意,秘密密钥不应公开分享

Now, we’ll wrap our key in the SecretKeySpec combining it with a chosen algorithm:

现在,我们将用SecretKeySpec包裹我们的密钥,并将其与选定的算法相结合。

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

In our case, we’re using TripleDES, which is one of the Java Security Standard Algorithms.

在我们的案例中,我们使用TripleDES,它是Java安全标准算法之一。

Another item we should generate in advance is the Initialization Vector for our key. We’ll use an 8-byte array of random numbers and letters:

另一个我们应该提前生成的项目是我们的密钥的初始化矢量。我们将使用一个8字节的随机数字和字母数组。

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

And then, we’ll wrap it in the IvParameterSpec class:

然后,我们将把它包装在IvParameterSpec类中。

IvParameterSpec ivSpec = new IvParameterSpec(iv);

3. Encrypting Strings

3.加密字符串s

We’re now ready to encrypt simple String values. Let’s first define a String that we’ll work with:

我们现在准备对简单的String值进行加密。让我们首先定义一个String,我们将用它来工作。

String secretMessage = "Baeldung secret message";

Next, we’ll need a Cipher object initialized with the encryption mode, secret key, and the initialization vector that we generated previously:

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

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

Note that we’re using the TripleDES algorithm with a CBC and a PKCS#5 padding scheme.

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

With the Cipher, we can run the doFinal method to encrypt our message. Note that it only works with a byte array, so we need to transform our String first:

使用Cipher,我们可以运行doFinal方法来加密我们的信息。注意,它只适用于字节数组,所以我们需要先转换我们的字符串

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

Now, our message is successfully encrypted. If we’d like to store it in a database or send it via a REST API, it would be more convenient to encode it with the Base64 alphabet:

现在,我们的信息已经成功加密了。如果我们想把它存储在数据库中或通过REST API发送它,用Base64字母编码会更方便。

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

Base64 encoding makes the message more readable and easier to work with.

Base64编码使信息更可读,更容易操作。

4. Decrypting Strings

4.解密字符串

Now, let’s see how we can reverse the encryption process and decrypt the message to its original form. For this, we’ll need a new Cipher instance, but this time, we’ll initialize it in decryption mode:

现在,让我们来看看如何逆转加密过程,将信息解密为原始形式。为此,我们需要一个新的Cipher实例,但这一次,我们将以解密模式初始化它

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

Next, we’ll run the doFinal method:

接下来,我们将运行doFinal方法。

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

Now, we’ll decode the result to a String variable:

现在,我们将把结果解码为一个String变量。

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

Finally, we can verify the results to make sure the decryption process performed correctly by comparing it to the initial value:

最后,我们可以通过与初始值的比较来验证结果,以确保解密过程正确执行。

Assertions.assertEquals(secretMessage, decryptedMessage);

5. Working with Files

5.与文件打交道

We can encrypt whole files as well. As an example, let’s create a temp file with some text content:

我们也可以对整个文件进行加密。作为一个例子,让我们创建一个带有一些文本内容的临时文件。

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

Next, let’s transform its content into a single byte array:

接下来,让我们把它的内容转化为一个单字节数组。

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

Now, we can use the encryption cipher the same way we did with a String:

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

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

Finally, let’s overwrite the file content with new, encrypted data:

最后,让我们用新的、加密的数据覆盖文件内容。

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

The decryption process looks very similar. The only difference is a cipher initialized in decryption mode:

解密过程看起来非常相似。唯一的区别是在解密模式下初始化了一个密码。

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

Once again, let’s overwrite the file content – this time, with the decrypted data:

再一次,让我们覆盖文件内容–这一次,用解密后的数据。

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

As the last step, we can verify if the file content matches the original value:

作为最后一步,我们可以验证文件内容是否与原始值相符。

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

6. Summary

6.总结

In this article, we’ve learned how to create a 3DES key in Java and how to use it to encrypt and decrypt Strings and files.

在这篇文章中,我们已经学会了如何在Java中创建一个3DES密钥,以及如何使用它来加密和解密Strings和文件。

As always, all source code is available over on GitHub.

一如既往,所有的源代码都可以在GitHub上找到