java - 在 JAVA 上使用 RSA 加密和解密的问题
问题描述
所以我正在尝试加密在用户键入内容时创建的文件,并且在加密之后我想解密文件。用户创建的文件和加密文件的创建没有问题,但是当我打开加密文件时,我认为它的空白是错误的,因为它上面应该写有一些乱码。
package br.com.rsa;
import java.security.*;
import java.io.*;
import java.util.*;
import javax.crypto.*;
public class Geracao {
public static void main(String[] args) throws IOException {
//Gerando um arquivo que será encriptado e descriptografado.
Scanner entrada1 = new Scanner(System.in);
System.out.println("Digite qualquer coisa: ");
String entrada = entrada1.nextLine();
System.out.println("Arquivo criado.");
FileOutputStream saida = new FileOutputStream("arquivo.txt");
PrintStream imprimir = new PrintStream(saida);
System.setOut(imprimir);
System.out.println(entrada);
saida.close();
//Gerando as chaves publica e privada.
try {
KeyPairGenerator chave = KeyPairGenerator.getInstance("RSA");
chave.initialize(1024);
KeyPair chaves = chave.generateKeyPair();
PrivateKey privada = chaves.getPrivate();
PublicKey publica = chaves.getPublic();
Base64.Encoder cripto = Base64.getEncoder();
System.out.println("Chave privada: " + cripto.encodeToString(privada.getEncoded()));
System.out.println("");
System.out.println("Chave publica: " + cripto.encodeToString(publica.getEncoded()));
System.out.println("");
//Salvando as chaves publica e privada.
try (FileOutputStream s_prv = new FileOutputStream("privada" + ".key")){
s_prv.write(chaves.getPrivate().getEncoded());
}
try (FileOutputStream s_pub = new FileOutputStream("publica" + ".key")){
s_pub.write(chaves.getPublic().getEncoded());
}
Criptografar(chaves, null);
//Descriptografar(chaves, null);
}
//Qualquer erro dentro da geração das chaves
catch (Exception e){
System.out.println(e);
}
}
//TODO - Comentario
static private void processFile(Cipher cifra, InputStream entrada_arq_c, OutputStream saida_arq_c){
try {
byte[] ibuf = new byte[1024];
int len;
while ((len = entrada_arq_c.read(ibuf)) != -1) {
byte[] obuf = cifra.update(ibuf, 0, len);
if ( obuf != null ) saida_arq_c.write(obuf);
}
byte[] obuf = cifra.doFinal();
if ( obuf != null ) saida_arq_c.write(obuf);
}
catch(Exception e) {
System.out.println("Problema no manuseio do arquivo.");
}
}
//Metodo para criptografar.
static private void Criptografar(KeyPair chaves, Cipher ci){
try {
PublicKey publica = chaves.getPublic();
Cipher cifra = Cipher.getInstance("RSA");
cifra.init(Cipher.ENCRYPT_MODE, publica);
FileInputStream entrada_arq_c = new FileInputStream("arquivo.txt");
FileOutputStream saida_arq_c = new FileOutputStream("criptografado.txt");
processFile(ci, entrada_arq_c, saida_arq_c);
}
catch(Exception e){
System.out.println("Erro ao criptografar.");
}
}
//Metodo para descriptografar.
static private void Descriptografar(KeyPair chaves, Cipher ci){
try {
PrivateKey privada = chaves.getPrivate();
Cipher cifra = Cipher.getInstance("RSA");
cifra.init(Cipher.DECRYPT_MODE, privada);
FileInputStream entrada_arq_c = new FileInputStream("criptografado.txt");
FileOutputStream saida_arq_c = new FileOutputStream("descriptografado.txt");
processFile(ci, entrada_arq_c, saida_arq_c);
}
catch(Exception e){
System.out.println("Erro ao descriptografar.");
}
}
}
解决方案
更新:
RSA 并不意味着加密大量数据。在这种情况下,使用 1024 位 RSA 密钥和默认为 PKCS#1 v1.5 的填充,他不能加密超过 117 字节的数据。——詹姆斯·K·波尔克
这里有很多问题。
首先,您设置System.out
新流并关闭它。因此,您看不到来自您的应用程序的任何响应。
解决方案1:保留默认输出流并将其重新设置
PrintStream defaultOutStream = System.out;
PrintStream imprimir = new PrintStream(saida);
System.setOut(imprimir);
System.out.println(entrada);
saida.close();
System.setOut(defaultOutStream);
解决方案2:以不同的方式写入文件,例如
try (FileOutputStream saida = new FileOutputStream("arquivo.txt");){
saida.write(entrada.getBytes(Charset.forName("UTF-8")));
} catch (Exception e){
e.printStackTrace();
}
其次,你有一个例外。您将看到“Problema no manuseio do arquivo”。在解决第一个问题后在您的控制台中。但是没有堆栈跟踪就没有帮助。您需要更新 catch 块以打印异常的原因。例如:
catch(Exception e) {
e.printStackTrace();
System.out.println("Problema no manuseio do arquivo.");
}
在它之后,您将在控制台中找到异常的名称和它发生的行号。这是输出文件为空的根本原因。
在进一步阅读之前,请尝试了解如何修复 nullpointer 以及导致它的原因。练习调试!在导致空指针的行上放置断点。
首先,您使用Cipher
as调用构造函数null
:
Criptografar(chaves, null);
接下来,您正在创建正确的密码,但使用旧密码调用进程函数,其值仍然为空:
static private void Criptografar(KeyPair chaves, Cipher ci){
try {
PublicKey publica = chaves.getPublic();
Cipher cifra = Cipher.getInstance("RSA");
cifra.init(Cipher.ENCRYPT_MODE, publica);
FileInputStream entrada_arq_c = new FileInputStream("arquivo.txt");
FileOutputStream saida_arq_c = new FileOutputStream("criptografado.txt");
processFile(ci, entrada_arq_c, saida_arq_c);
}
catch(Exception e){
System.out.println("Erro ao criptografar.");
}
}
解决方案之一是使用正确的参数调用函数:processFile(cifra, entrada_arq_c, saida_arq_c);
几点建议:
- 您没有
Cipher
在构造函数中使用参数Criptografar
,请将其删除 - 在所有 catch 块中打印堆栈跟踪
推荐阅读
- swift - 如何在 Swift 中创建一个返回可解码类型的函数?
- c# - BulkWrite 操作可以用于多个集合吗?
- python - 如果 where 条件为空,Postgres 检索所有行
- android - Android popBackStack 显示片段未添加到后台堆栈
- javascript - 从 yr.no 获取 XML 天气数据
- c++ - 如何重新定义c++指针函数?
- c# - 从 makecert.exe 升级到 CertEnroll - 证书信任问题
- python - Pyomo:从 json 存档错误加载三维集数据:无法使用索引集索引组件
- database - Neo4J:如何从 cypher-shell 重新启动数据库?
- .net - httpclient 取消令牌只能工作 21 秒或更短