本文介绍了通过运行时进程在Java中调用GnuPG来加密和解密文件 - 解密始终挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:稍后再回来,因为我找不到一个可行的解决方案。手动排放输入流而不是使用BufferedReaders,似乎没有帮助,因为inputStream.read()方法会永久阻止该程序。我将gpg调用放在一个批处理文件中,并从Java中调用批处理文件,只得到相同的结果。一旦使用decrypt选项调用gpg,输入流似乎变得无法访问,阻塞整个程序。当我有更多的时间专注于这个任务时,我必须回到这个。同时,我必须通过一些其他方式(可能是BouncyCastle)解密工作。



最后一个可能尝试的选项是调用cmd.exe,并通过该进程生成的输入流写命令...



感谢在这个问题上的帮助。






我一直在处理这个问题几天,没有取得任何进展,所以我以为我会在这里提供一些帮助。 / p>

我正在创建一个简单的程序,将通过Java运行时进程调用GnuPG。它需要能够加密和解密文件。加密工作,但我解密文件有一些问题。每当我尝试解密一个文件时,进程将挂起。 exitValue()总是抛出它的IllegalThreadStateException,程序如同仍在等待一样。这些方法的代码如下。程序的最终目标是解密文件,并在Java中解析它的内容。



我尝试了三种方法来获取gpgDecrypt方法。第一种方法是删除passphrase-fd选项,并通过catch块中的gpgOutput流将密码写入gpg,假设它通过命令行提示输入密码。这没有工作,所以我将密码短语放在一个文件中,并添加了-passphrase-fd选项。在这种情况下,程序无限重复。如果我通过gpgOutput流写任何东西,程序将完成。打印的退出值将为2,结果变量将为空。



第三个选项是BouncyCastle,但是我遇到问题我的私钥(这可能是一个单独的帖子)。



我用于加密和解密的密钥是由GnuPG生成的4096位RSA密钥。在使用密码和密码文件的两种情况下,我尝试通过>将输出管道传输到一个文件。 myFile.txt ,但似乎没有任何区别。



这是gpgEncrypt,gpgDecrypt和getStreamText方法。自从加密工作以来,我发布了两个,我看不到在执行和处理加密和解密方法之间的过程中有任何明显的区别。 getStreamText只读取流的内容并返回一个字符串。



编辑:快速笔记,Windows环境。如果我复制decrypt命令输出,它通过控制台正常工作。所以我知道命令是有效的。






  public boolean gpgEncrypt(String file, String recipient,String outputFile){
boolean success = true;
StringBuilder gpgCommand = new StringBuilder(gpg --recipient \);
gpgCommand.append(recipient).append(\--output \)。append(outputFile ).append(\--yes --encrypt \);
gpgCommand.append(file).append(\);

System.out.println(ENCRYPT COMMAND:+ gpgCommand);
尝试{
进程gpgProcess = Runtime.getRuntime()。exec(gpgCommand.toString());

BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream()));
BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));

boolean execution = true;

while(execution){
try {
int exitValue = gpgProcess.exitValue();

if(gpgErrorOutput.ready()){
String error = getStreamText(gpgErrorOutput);
System.err.println(error);
success = false;
break;
} else if(gpgOutput.ready()){
System.out.println(getStreamText(gpgOutput));
}

execution = false;
} catch(Exception e){
//进程尚未准备好退出。休息一下,再试一次。
try {
Thread.sleep(100);
} catch(InterruptedException e1){
System.err.println(This thread has insomnia:+ e1.getMessage());
}
}
}
} catch(IOException e){
System.err.println(通过运行时运行GPG时出错:+ e.getMessage() );
success = false;
}

返回成功;
}

public String gpgDecrypt(String file,String passphraseFile){
String result = null;
StringBuilder command = new StringBuilder(gpg --passphrase-fd 0 --decrypt \);
command.append(file).append(\0< \ ).append(passphraseFile).append( \);
System.out.println(DECRYPT COMMAND:+ command.toString());
try {

进程gpgProcess = Runtime.getRuntime()。exec(command.toString());

BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));
BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream()));

boolean execution = true;

while(execution){
try {
if(gpgErrorOutput.ready()){
result = getStreamText(gpgErrorOutput);
System.err.println(result);
break;
} else if(gpgOutput.ready()){
result = getStreamText(gpgOutput);
}

int exitValue = gpgProcess.exitValue();
System.out.println(EXIT:+ exitValue);

execution = false;
} catch(IllegalThreadStateException e){
System.out.println(尚未准备好。流状态:+ gpgOutput.ready()+,错误:+ gpgErrorOutput.ready());

try {
Thread.sleep(100);
} catch(InterruptedException e1){
System.err.println(This thread has insomnia:+ e1.getMessage());
}
}
}
} catch(IOException e){
System.err.println(无法通过命令行执行GPG解密命令+ e .getMessage());
}

返回结果;
}

private String getStreamText(BufferedReader reader)throws IOException {
StringBuilder result = new StringBuilder();
try {
while(reader.ready()){
result.append(reader.readLine());
if(reader.ready()){
result.append(\\\
);
}
}
} catch(IOException ioe){
System.err.println(读取流时出错:+ ioe.getMessage());
throw ioe;
}
return result.toString();
}


解决方案

我忘了你如何处理在Java中有100种方法。但是我被解密命令本身困扰,这是非常有帮助的,虽然你不需要所有这些引号,如果你想解密一个大文件,它就像这样:

  gpg --passphrase-fd 0  - 输出yourfile.txt --decrypt /encryptedfile.txt.gpg/ 0< /passwrdfile.txt 


NOTE: Coming back to this later as I've been unable to find a working solution. Draining the input streams manually instead of using BufferedReaders doesn't seem to help as the inputStream.read() method permanently blocks the program. I placed the gpg call in a batch file, and called the batch file from Java to only get the same result. Once gpg is called with the decrypt option, the input stream seems to become inaccessible, blocking the entire program. I'll have to come back to this when I have more time to focus on the task. In the mean time, I'll have to get decryption working by some other means (probably BouncyCastle).

The last option to probably try is to call cmd.exe, and write the command through the input stream generated by that process...

I appreciate the assistance on this issue.


I've been working on this problem for a couple days and haven't made any progress, so I thought I'd turn to the exeprtise here for some help.

I am creating a simple program that will call GnuPG via a Java runtime process. It needs to be able to encrypt and decrypt files. Encryption works, but I'm having some problems decrypting files. Whenever I try to decrypt a file, the process hangs.exitValue() always throws it's IllegalThreadStateException and the program chugs along as if it's still waiting. The code for these methods is attached below. The ultimate goal of the program is to decrypt the file, and parse it's contents in Java.

I've tried three approaches to getting the gpgDecrypt method to work. The first approach involved removing the passphrase-fd option and writing the passphrase to gpg via the gpgOutput stream in the catch block, assuming it was prompting for the passphrase like it would via the command line. This didn't work, so I put the passphrase in a file and added the -passphrase-fd option. In this case, the program repeats infinitely. If I write anything via the gpgOutput stream the program will complete. The Exit value printed will have a value of 2, and the result variable will be blank.

The third option is BouncyCastle, but I'm having problems getting it to recognize my private key (which is probably a separate post all together).

The keys I'm using to encrypt and decrypt are 4096-bit RSA keys, generated by GnuPG. In both cases using the passphrase and the passphrase file, I've tried piping the output to a file via > myFile.txt, but it doesn't seem to make any difference.

Here are the gpgEncrypt, gpgDecrypt and getStreamText methods. I posted both since the encrypt works, and I can't see any glaring differences between how I'm executing and handling the process between the encrypt and decrypt methods. getStreamText just reads the contents of the streams and returns a string.

EDIT: Quick note, Windows environment. If I copy the decrypt command output, it works via the console just fine. So I know the command is valid.


public boolean gpgEncrypt(String file, String recipient, String outputFile){
    boolean success = true;
    StringBuilder gpgCommand = new StringBuilder("gpg --recipient \"");
    gpgCommand.append(recipient).append("\" --output \"").append(outputFile).append("\" --yes --encrypt \"");
    gpgCommand.append(file).append("\"");

    System.out.println("ENCRYPT COMMAND: " + gpgCommand);
    try {
        Process gpgProcess = Runtime.getRuntime().exec(gpgCommand.toString());

        BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
        BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream()));
        BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));

        boolean executing = true;

        while(executing){
            try{
                int exitValue = gpgProcess.exitValue();

                if(gpgErrorOutput.ready()){
                    String error = getStreamText(gpgErrorOutput);
                    System.err.println(error);
                    success = false;
                    break;
                }else if(gpgOutput.ready()){
                    System.out.println(getStreamText(gpgOutput));
                }

                executing = false;
            }catch(Exception e){
                //The process is not yet ready to exit.  Take a break and try again.
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e1) {
                    System.err.println("This thread has insomnia: " + e1.getMessage());
                }
            }
        }
    } catch (IOException e) {
        System.err.println("Error running GPG via runtime: " + e.getMessage());
        success = false;
    }

    return success;
}

public String gpgDecrypt(String file, String passphraseFile){
    String result = null;
    StringBuilder command = new StringBuilder("gpg --passphrase-fd 0 --decrypt \"");
    command.append(file).append("\" 0<\"").append(passphraseFile).append("\"");
    System.out.println("DECRYPT COMMAND: " + command.toString());
    try {

        Process gpgProcess = Runtime.getRuntime().exec(command.toString());

        BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
        BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));
        BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream()));

        boolean executing = true;

        while(executing){
            try{
                if(gpgErrorOutput.ready()){
                    result = getStreamText(gpgErrorOutput);
                    System.err.println(result);
                    break;
                }else if(gpgOutput.ready()){
                    result = getStreamText(gpgOutput);
                }

                int exitValue = gpgProcess.exitValue();
                System.out.println("EXIT: " + exitValue);

                executing = false;
            }catch(IllegalThreadStateException e){
                System.out.println("Not yet ready.  Stream status: " + gpgOutput.ready() + ", error: " + gpgErrorOutput.ready());

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e1) {
                    System.err.println("This thread has insomnia: " + e1.getMessage());
                }
            }
        }
    } catch (IOException e) {
        System.err.println("Unable to execute GPG decrypt command via command line: " + e.getMessage());
    }

    return result;
}

private String getStreamText(BufferedReader reader) throws IOException{
    StringBuilder result = new StringBuilder();
    try{
        while(reader.ready()){
            result.append(reader.readLine());
            if(reader.ready()){
                result.append("\n");
            }
        }
    }catch(IOException ioe){
        System.err.println("Error while reading the stream: " + ioe.getMessage());
        throw ioe;
    }
    return result.toString();
}
解决方案

I forget how you handle it in Java, there are 100 methods for that. But I was stuck with decrypt command itself, it was very helpful, though you didn't need all those quotes and if you wish to decrypt a large file, it goes like this:

gpg --passphrase-fd 0 --output yourfile.txt --decrypt /encryptedfile.txt.gpg/ 0</passwrdfile.txt

这篇关于通过运行时进程在Java中调用GnuPG来加密和解密文件 - 解密始终挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 17:18