拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Java中的RSA加密

Java中的RSA加密

白鹭 - 2021-11-24 552 0 0

1.简介

RSA,或者换句话说, Rivest–Shamir–Adleman是一种非对称密码算法。它具有两个密钥,与诸如DES或AES之类的对称算法不同。我们可以与任何人共享的公共密钥用于加密数据。还有一个我们只为自己保留的私有数据,用于解密数据

在本教程中,我们将学习如何在Java中生成,存储和使用RSA密钥。

2.生成RSA密钥对

在开始实际的加密之前,我们需要生成我们的RSA密钥对。 java.security包中KeyPairGenerator轻松地做到这一点:

KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");

 generator.initialize(2048);

 KeyPair pair = generator.generateKeyPair();

生成的密钥的大小为2048位。

接下来,我们可以提取私钥和公钥:

PrivateKey privateKey = pair.getPrivate();

 PublicKey publicKey = pair.getPublic();

我们将使用公共密钥对数据进行加密,并使用私有密钥对数据进行解密。

3.在文件中存储密钥

将密钥对存储在内存中并非总是一个好的选择。通常,按键会长时间保持不变。在这种情况下,将它们存储在文件中更为方便。

要将密钥保存在文件中,我们可以使用getEncoded方法,该方法以其主要编码格式返回密钥内容:

try (FileOutputStream fos = new FileOutputStream("public.key")) {

 fos.write(publicKey.getEncoded());

 }

要从文件中读取密钥,我们首先需要将内容加载为字节数组:

File publicKeyFile = new File("public.key");

 byte[] publicKeyBytes = Files.readAllBytes(publicKeyFile.toPath());

然后使用KeyFactory重新创建实际实例:

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

 EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);

 keyFactory.generatePublic(publicKeySpec);

密钥字节内容需要用EncodedKeySpec类包装。在这里,我们使用X509EncodedKeySpec,它表示用于保存文件的Key::getEncoded方法的默认算法。

在此示例中,我们保存并仅读取公共密钥文件。可以使用相同的步骤来处理私钥。

请记住,使用私钥将文件保持尽可能安全,并限制访问。未经授权的访问可能会带来安全问题。

4.使用字符串

现在,让我们看一下如何加密和解密简单字符串。首先,我们需要一些数据才能使用:

String secretMessage = "Baeldung secret message";

其次,我们需要Cipher对象,以使用之前生成的公钥进行加密:

Cipher encryptCipher = Cipher.getInstance("RSA");

 encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

准备好之后,我们可以调用doFinal方法来加密消息。请注意,它仅接受字节数组参数,因此我们需要在转换字符串之前:

byte[] secretMessageBytes = secretMessage.getBytes(StandardCharsets.UTF_8);)

 byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);

现在,我们的消息已成功编码。如果我们要将其存储在数据库中或通过REST API发送,则使用Base64 Alphabet对其进行编码会更方便:

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

这样,该消息将更具可读性并且更易于使用。

现在,让我们看看如何将消息解密为原始形式。为此,我们需要另一个Cipher实例。这次,我们将使用解密模式和私钥对其进行初始化:

Cipher decryptCipher = Cipher.getInstance("RSA");

 decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);

doFinal方法像以前一样调用密码:

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

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

最后,让我们验证加密解密过程是否正确进行:

assertEquals(secretMessage, decryptedMessage);

5.处理文件

也可以加密整个文件。例如,让我们创建一个包含一些文本内容的临时文件:

Path tempFile = Files.createTempFile("temp", "txt");

 Files.writeString(tempFile, "some secret message");

在开始加密之前,我们需要将其内容转换为字节数组:

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

现在,我们可以使用加密密码:

Cipher encryptCipher = Cipher.getInstance("RSA");

 encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

 byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes);

最后,我们可以用新的加密内容覆盖它:

try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {

 stream.write(encryptedFileBytes);

 }

解密过程看起来非常相似。唯一的区别是在解密模式下使用私钥初始化的密码:

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

 Cipher decryptCipher = Cipher.getInstance("RSA");

 decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);

 byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes);

 try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {

 stream.write(decryptedFileBytes);

 }

作为最后一步,我们可以验证文件内容是否与原始值匹配:

String fileContent = Files.readString(tempFile);

 Assertions.assertEquals("some secret message", fileContent);

6.总结

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

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *