1. Overview
1.概述
Originally designed as an alternative to the DES encryption algorithm, the Blowfish encryption algorithm is one of the most popular encryption algorithms available today. Blowfish is a symmetric-key block cipher designed by Bruce Schneier in 1993. This algorithm has a block size of 64 bits and a key length of 446 bits, which is better than the DES and 3DES algorithms.
DES加密算法最初是作为Blowfish加密算法的替代品而设计的,它是当今最流行的加密算法之一。Blowfish是一种对称密钥块密码,由Bruce Schneier于1993年设计。该算法的块大小为64位,密钥长度为446位,优于DES和3DES算法。
In this tutorial, we’ll learn how to implement encryption and decryption using Blowfish ciphers with the Java Cryptography Architecture (JCA) available in JDK.
在本教程中,我们将学习如何使用 JDK 中的 Java Cryptography Architecture (JCA) 使用 Blowfish 密码实现加密和解密。
2. Generating Secret Key
2.生成密钥
Since Blowfish is a symmetric-key block cipher, it uses the same key for both encryption and decryption. Accordingly, we’ll create a secret key to encrypt texts in the next steps. This secret key should be preserved securely and shouldn’t be shared in public. Let’s define the secret key:
由于 Blowfish 是一种对称密钥块密码,它在加密和解密时使用相同的密钥。因此,我们将在接下来的步骤中创建一个用于加密文本的秘钥。此密匙应安全保存,不应公开共享。让我们定义秘钥:
// Generate a secret key
String secretKey = "MyKey123";
byte[] keyData = secretKey.getBytes();
// Build the SecretKeySpec using Blowfish algorithm
SecretKeySpec secretKeySpec = new SecretKeySpec(keyData, "Blowfish");
Next, we can proceed to build the cipher with encryption mode:
接下来, 我们可以继续使用加密模式创建密码: <br
// Build the cipher using Blowfish algorithm
Cipher cipher = Cipher.getInstance("Blowfish");
Then, we’ll initialize the cipher with encryption mode (Cipher.ENCRYPT_MODE) and use our secret key:
然后,我们将使用加密模式(Cipher.ENCRYPT_MODE)初始化密码,并使用我们的秘钥:
// Initialize cipher in encryption mode with secret key
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
3. Encrypting Strings
3.加密 字符串</em
Let’s see how to use the instantiated Blowfish cipher with the secret key to encrypt Strings:
让我们看看如何使用实例化的 Blowfish 密码和秘钥对 Strings 进行加密:</em
// the text to encrypt
String secretMessage = "Secret message to encrypt";
// encrypt message
byte[] encryptedBytes = cipher.doFinal(secretMessage.getBytes(StandardCharsets.UTF_8));
As we can see, the cipher gives us an encrypted message in the form of a byte array. However, if we’d like to store it in a database or send the encrypted message via REST API, it would be more suitable and safer to encode it with the Base64 alphabet:
我们可以看到,密码以字节数组的形式为我们提供了加密信息。但是,如果我们想将其存储到数据库中,或通过 REST API 发送加密信息,使用 Base64 字母编码会更合适、更安全:
// encode with Base64 encoder
String encryptedtext = Base64.getEncoder().encodeToString(encryptedBytes);
Now, we get the final encrypted text, which is readable and easy to handle.
现在,我们得到了最终的加密文本,它可读且易于处理。
4. Decrypting Strings
4.解密 字符串</em
Decrypting Strings with the Blowfish encryption algorithm is equally simple. Let’s see it in action.
使用 Blowfish 加密算法解密字符串也同样简单。让我们看看它的实际操作。
First, we need to initialize the cipher with decryption mode (Cipher.DECRYPT_MODE) along with the SecretKeySpec:
首先,我们需要使用解密模式(Cipher.DECRYPT_MODE)和SecretKeySpec对密码进行初始化:
// Create the Blowfish Cipher
Cipher cipher = Cipher.getInstance("Blowfish");
// Initialize with decrypt mode & SecretKeySpec
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
Next, we can use this cipher to decrypt the message:
接下来,我们就可以用这个密码来解密信息了:
// decode using Base64 and decrypt the message
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedtext));
// convert the decrypted bytes to String
String decryptedString = new String(decrypted, StandardCharsets.UTF_8);
Finally, we can verify the results to ensure the decryption process performs correctly by comparing it to the original value:
最后,我们可以通过将结果与原始值进行比较来验证结果,以确保解密过程的正确执行:
Assertions.assertEquals(secretMessage, decrypedText);
In addition, we can notice that we use StandardCharsets.UTF_8 charset during both encryption and decryption. This way, we can be sure that encryption or decryption always replaces the input text containing malformed and unmappable char sequences with the replacement byte array of UTF-8 charset.
此外,我们可以注意到,在加密和解密过程中,我们都使用了 StandardCharsets.UTF_8 字符集。这样,我们就可以确保在加密或解密时,总是用 UTF-8 字符集的替换字节数组替换包含畸形和不可应用字符序列的输入文本。
5. Working With Files
5.使用文件
Sometimes, we may need to encrypt or decrypt the whole file instead of individual Strings. The Blowfish encryption algorithm allows to encrypt and decrypt the whole files. Let’s see an example to create a temp file with some sample content:
有时,我们可能需要加密或解密整个文件,而不是单个字符串。Blowfish加密算法允许对整个文件进行加密和解密。下面我们来看一个例子,创建一个包含一些示例内容的临时文件:
String originalContent = "some secret text file";
Path tempFile = Files.createTempFile("temp", "txt");
writeFile(tempFile, originalContent);
Next, we need to transform the content into a byte array:
接下来,我们需要将内容转换为字节数组:
byte[] fileBytes = Files.readAllBytes(tempFile);
Now, we can proceed with the encryption of the whole file using encryption cipher:
现在,我们可以使用加密密码对整个文件进行加密:
Cipher encryptCipher = Cipher.getInstance("Blowfish");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes);
Finally, we can overwrite the encrypted content in the temp file:
最后,我们可以覆盖临时文件中的加密内容:
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(encryptedFileBytes);
}
Decrypting the whole file is a similar process. The only difference is to change the cipher mode to do decryption:
解密整个文件的过程类似。唯一的区别是更改密码模式来进行解密:
encryptedFileBytes = Files.readAllBytes(tempFile);
Cipher decryptCipher = Cipher.getInstance("Blowfish");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes);
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(decryptedFileBytes);
}
Finally, we can verify whether the file content matches the original value:
最后,我们可以验证文件内容是否与原始值一致:
String fileContent = readFile(tempFile);
Assertions.assertEquals(originalContent, fileContent);
6. Weakness and Successors
6.弱点和继承者
Blowfish was one of the first secure encryption algorithms not subject to patents and freely available for public use. Although the Blowfish algorithm performs better than DES and 3DES algorithms in terms of encryption speed, it has some limitations due to its inherent design.
Blowfish 是首批不受专利限制的安全加密算法之一,可免费供公众使用。虽然 Blowfish 算法在加密速度方面优于 DES 和 3DES 算法,但由于其固有的设计,它也有一些局限性。
The Blowfish algorithm uses a 64-bit block size as opposed to AES’s 128-bit block size. Hence, this makes it vulnerable to birthday attacks, specifically in the HTTPS context. Attackers have already demonstrated that they can leverage the 64-bit block size ciphers to perform plaintext recovery (by decrypting ciphertext). Moreover, because of its small block size open-source projects such as GnuPG recommend that the Blowfish algorithm won’t be used to encrypt files larger than 4 GB.
Blowfish 算法使用 64 位块大小,而 AES 算法使用 128 位块大小。因此,它很容易受到生日攻击,特别是在 HTTPS 环境中。攻击者已经证明,他们可以利用 64 位块大小的密码进行明文恢复(通过解密密文)。此外,由于块大小较小,GnuPG 等开源项目建议不要将 Blowfish 算法用于加密 大于 4 GB 的文件。
Changing new secret keys slows down the process. For instance, each new key needs pre-processing and takes about 4 KB of text, which is slower when compared to other block ciphers.
更改新密匙会减慢处理速度。例如,每个新密钥都需要预处理,需要大约 4 KB 的文本,与其他块密码相比速度较慢。
Bruce Schneier has recommended migrating to his Blowfish successor, the Twofish encryption algorithm, which has a block size of 128 bits. It also has a free license and is available for public use.
Bruce Schneier 建议迁移到他的 Blowfish 后继算法,即 Twofish加密算法,该算法的块大小为 128 位。 该算法还拥有免费许可证,可供公众使用。
In 2005, Blowfish II was released, which was developed by people other than Bruce Schneier. Blowfish II has the same design but has twice as many S tables and uses 64-bit integers instead of 32-bit integers. Also, it works on 128-bit blocks like the AES algorithm.
2005 年,布鲁斯-施耐尔以外的人开发的 Blowfish II 发布。Blowfish II 采用了相同的设计,但 S 表的数量增加了一倍,并使用 64 位整数而不是 32 位整数。此外,它还能像 AES 算法一样在 128 位块上运行。
Advanced Encryption Standard (AES) is a popular and widely used symmetric-key encryption algorithm. AES supports varying key lengths such as 128, 192, and 256 bits to encrypt and decrypt data. However, its block size is fixed at 128 bits.
高级加密标准(AES)是一种流行且广泛使用的对称密钥加密算法。AES 支持 128、192 和 256 位等不同密钥长度来加密和解密数据。不过,其块大小固定为 128 位。
7. Conclusion
7.结论
In this article, we learned about the generation of secret keys and how to encrypt and decrypt Strings using the Blowfish encryption algorithm. Also, we saw encrypting and decrypting files are equally simple. Finally, we also discussed the weaknesses and various successors of Blowfish.
在本文中,我们了解了密钥的生成以及如何使用 Blowfish 加密算法加密和解密 Strings 。此外,我们还看到加密和解密文件同样简单。最后,我们还讨论了 Blowfish 的弱点和各种后继算法。
As always, the full source code of the article is available over on GitHub.
一如既往,本文的完整源代码可在 GitHub 上查阅。