Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过运行时进程在Java中调用GnuPG来加密和解密文件-解密总是挂起_Java_Encryption_Runtime.exec_Gnupg - Fatal编程技术网

通过运行时进程在Java中调用GnuPG来加密和解密文件-解密总是挂起

通过运行时进程在Java中调用GnuPG来加密和解密文件-解密总是挂起,java,encryption,runtime.exec,gnupg,Java,Encryption,Runtime.exec,Gnupg,注意:由于我无法找到有效的解决方案,所以稍后再讨论这个问题。手动排空输入流而不是使用BufferedReaders似乎没有帮助,因为inputStream.read()方法会永久性地阻塞程序。我将gpg调用放在一个批处理文件中,并从Java调用批处理文件以获得相同的结果。一旦使用decrypt选项调用gpg,输入流似乎变得不可访问,从而阻塞了整个程序。当我有更多的时间专注于这项任务时,我必须回到这一点。同时,我必须通过其他方式(可能是BouncyCastle)使解密工作 最后一个可能尝试的选项是

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

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

我感谢在这个问题上提供的帮助


我已经研究这个问题好几天了,没有任何进展,所以我想我应该向这里的执行官寻求帮助

我正在创建一个简单的程序,它将通过Java运行时进程调用GnuPG。它需要能够加密和解密文件。加密有效,但我在解密文件时遇到了一些问题。每当我尝试解密一个文件时,进程都会挂起。
exitValue()
总是抛出它的非法ThreadStateException,程序就会像在等待一样快速运行。这些方法的代码附在下面。该程序的最终目标是解密文件,并用Java解析其内容

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

第三种选择是BouncyCastle,但我在让它识别我的私钥(这可能是一篇单独的文章)时遇到了问题

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

以下是gpgEncrypt、gpgDecrypt和getStreamText方法。我发布了这两种方法,因为encrypt可以工作,我看不到encrypt和decrypt方法之间执行和处理过程的方式有任何明显的区别。getStreamText只读取流的内容并返回字符串

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


公共布尔gpgEncrypt(字符串文件、字符串收件人、字符串输出文件){ 布尔成功=真; StringBuilder gpgCommand=新的StringBuilder(“gpg--recipient\”); gpgCommand.append(recipient.append(“\”--output\”).append(outputFile.append(“\”--yes--encrypt\”); gpgCommand.append(文件).append(“\”); System.out.println(“加密命令:“+gpgCommand”); 试一试{ Process gpgProcess=Runtime.getRuntime().exec(gpgCommand.toString()); BufferedReader gpgOutput=新的BufferedReader(新的InputStreamReader(gpgProcess.getInputStream()); BufferedWriter gpgInput=new BufferedWriter(new OutputStreamWriter(gpgpgprocess.getOutputStream()); BufferedReader gpgErrorOutput=新的BufferedReader(新的InputStreamReader(gpgpprocess.getErrorStream()); 布尔值=真; 执行时{ 试一试{ int-exitValue=gpgProcess.exitValue(); if(gpgerrororOutput.ready()){ 字符串错误=getStreamText(gpgErrorOutput); 系统错误打印项次(错误); 成功=错误; 打破 }else if(gpgOutput.ready()){ System.out.println(getStreamText(gpgOutput)); } 执行=假; }捕获(例外e){ //进程尚未准备好退出。请暂停,然后重试。 试一试{ 睡眠(100); }捕捉(中断异常e1){ System.err.println(“此线程有:+e1.getMessage()); } } } }捕获(IOE异常){ System.err.println(“通过运行时运行GPG时出错:+e.getMessage()); 成功=错误; } 回归成功; } 公共字符串gpgDecrypt(字符串文件、字符串密码文件){ 字符串结果=null; StringBuilder命令=新建StringBuilder(“gpg—密码短语fd 0—解密\”);
command.append(file.append(“\”0您是否尝试从命令行而不是Java代码运行该命令?
当GnuPG等待控制台输出时,“仅供您观看”选项可能会出现问题。

这可能是问题所在,也可能不是问题所在(在解密函数中)

您正在包装
getInputStream
的结果两次。显然
gpgErrorOutput
应该包装错误流,而不是输入流

int exitValue = gpgProcess.exitValue();

//它给出了进程未退出异常

当我用下面的命令替换解密命令时,它对我有效

gpg --output decrypted_file --batch --passphrase "passphrase goes here" --decrypt encrypted_file

我忘了在Java中是如何处理的,有100种方法。但我一直使用decrypt命令本身,它非常有用,尽管您不需要所有这些引号,如果您希望解密一个大文件,它是这样的:

gpg --passphrase-fd 0 --output yourfile.txt --decrypt /encryptedfile.txt.gpg/ 0</passwrdfile.txt
gpg——密码短语fd0——输出您的
gpg --output decrypted_file --batch --passphrase "passphrase goes here" --decrypt encrypted_file
gpg --passphrase-fd 0 --output yourfile.txt --decrypt /encryptedfile.txt.gpg/ 0</passwrdfile.txt
String line = null;
while ( (line = gpgOutput.readLine()) != null ) {
     System.out.println(line);
}
public static 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;
}

// gpg --pinentry-mode=loopback --passphrase "siv_test" -d -o
// "sample_enc_data_op.txt" "sample_enc_data_input.gpg"

public static String gpgDecrypt(String file, String passphrase,
        String outputfile) {
    String result = null;
    StringBuilder command = new StringBuilder(
            "gpg --pinentry-mode=loopback --passphrase \"");
    command.append(passphrase).append("\" -d -o \"").append(outputfile)

    .append("\" --yes \"").append(file)

    .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);
                }
                String line = null;
                while ((line = gpgOutput.readLine()) != null) {
                    System.out.println(line);
                }
                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 static 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();
}