简体   繁体   English

在JAVA上使用RSA进行加密和解密的问题

[英]Problem with encrypting and decrypting using RSA on JAVA

so I'm trying to encrypt a file thats created when the user types something and right after the encryption I want to decrypt the file. 因此,我正在尝试对用户键入内容时创建的文件进行加密,并且在加密之后我想解密该文件。 The file that the user created and the encryption file are created without an issue, but when I open the encrypted file its blank which I think is wrong since it should have some gibberish written on it. 用户创建的文件和加密文件的创建没有问题,但是当我打开加密文件时,我认为它的空白是错误的,因为它上面应该写有一些乱码。

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.");
    }
  }
}

Update: 更新:

RSA is not meant to encrypt large amounts of data. RSA并非旨在加密大量数据。 In this case, with a 1024 bit RSA key and padding that defaults to PKCS#1 v1.5, he cannot encrypt more than 117 bytes of data. 在这种情况下,使用1024位RSA密钥和默认为PKCS#1 v1.5的填充,他不能加密超过117个字节的数据。 James K Polk James K Polk


There are a lot of issues here. 这里有很多问题。
First, you set System.out to new stream and close it. 首先,将System.out设置为新流并关闭它。 As a result you cannot see any response from your application. 结果,您看不到应用程序的任何响应。

Solution 1: keep default output stream and set it back 解决方案1:保留默认输出流并将其重新设置

PrintStream defaultOutStream = System.out;
PrintStream imprimir = new PrintStream(saida);
System.setOut(imprimir);
System.out.println(entrada);
saida.close();
System.setOut(defaultOutStream);

Solution 2: write to file in different way, for example 解决方案2:例如以不同方式写入文件

try (FileOutputStream saida = new FileOutputStream("arquivo.txt");){
    saida.write(entrada.getBytes(Charset.forName("UTF-8")));
} catch (Exception e){
    e.printStackTrace();
}

Second, you have an exception. 其次,您有一个例外。 You will see "Problema no manuseio do arquivo." 您将看到“没有任何问题的arquivo”。 in you console after fixing first issue. 修复第一个问题后在控制台中进行操作。 But it is not helpful without stack trace. 但是,如果没有堆栈跟踪,它就没有帮助。 You need to update your catch block to print the cause of the exception. 您需要更新catch块以打印异常原因。 For example: 例如:

catch(Exception e) {
    e.printStackTrace();
    System.out.println("Problema no manuseio do arquivo.");
}

After it you will find in console the name of the exception and the the number of the line where it occurs. 之后,您将在控制台中找到异常的名称和发生异常的行号。 This is a root cause of why your output file is empty. 这是为什么您的输出文件为空的根本原因


Before reading further, try to find how to fix nullpointer and what causes it. 在进一步阅读之前,请尝试查找如何修复nullpointer及其原因。 Practice debugging! 练习调试! put break point on the line which causing nullpointer. 将断点放在导致空指针的行上。

First, you are calling constructor with Cipher as null : 首先,您要使用Cipher调用null构造函数:

Criptografar(chaves, null);

Next, you are creating correct cipher, but calling process function with old one which value is still null: 接下来,您将创建正确的密码,但是使用旧值仍为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.");
    }
}

One of the solution is to just call function with correct arguments: processFile(cifra, entrada_arq_c, saida_arq_c); 解决方案之一是仅使用正确的参数调用函数: processFile(cifra, entrada_arq_c, saida_arq_c);

Few suggestions: 几点建议:

  • you are not using Cipher parameter in Criptografar constructor, remove it 您没有在Criptografar构造函数中使用Cipher参数,请将其删除
  • print stack traces in all catch blocks 在所有捕获块中打印堆栈跟踪

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM