Вызов GnuPG в Java через процесс выполнения для шифрования и дешифрования файлов - Decrypt всегда зависает

ПРИМЕЧАНИЕ: Вернемся к этому позже, так как я не смог найти рабочего решения. Осушение входных потоков вручную вместо использования BufferedReaders, похоже, не помогает, поскольку метод inputStream.read () постоянно блокирует программу. Я поместил вызов gpg в пакетный файл и вызвал пакетный файл из Java, чтобы получить только тот же результат. После вызова gpg с опцией дешифрования входной поток становится недоступным, блокируя всю программу. Мне придется вернуться к этому, когда у меня будет больше времени, чтобы сосредоточиться на задаче. А пока мне придется заставить дешифрование работать каким-то другим способом (возможно, BouncyCastle).

Последний вариант, который, вероятно, стоит попробовать, - это вызвать cmd.exe и записать команду через входной поток, сгенерированный этим процессом. ...

Я ценю помощь в этом вопросе.


Я ' Я работал над этой проблемой в течение пары дней и не добился никакого прогресса, поэтому я подумал, что обращусь к руководителю за помощью.

Я создаю простую программу, которая будет вызывать GnuPG через среду выполнения Java процесс. Он должен иметь возможность шифровать и расшифровывать файлы. Шифрование работает, но у меня возникают проблемы с расшифровкой файлов. Всякий раз, когда я пытаюсь расшифровать файл, процесс зависает. exitValue () всегда выдает исключение IllegalThreadStateException, и программа продолжает работать, как будто она все еще ждет. Код для этих методов прилагается ниже. Конечная цель программы - расшифровать файл и проанализировать его содержимое на Java.

Я пробовал три подхода, чтобы заставить работать метод gpgDecrypt. Первый подход заключался в удалении опции passphrase-fd и записи парольной фразы в gpg через поток gpgOutput в блоке catch, предполагая, что он запрашивал парольную фразу, как это было бы через командную строку. Это не сработало, поэтому я поместил кодовую фразу в файл и добавил параметр -passphrase-fd. В этом случае программа повторяется бесконечно. Если я напишу что-нибудь через поток gpgOutput, программа завершится. Напечатанное значение Exit будет иметь значение 2, а переменная результата будет пустой.

Третий вариант - BouncyCastle, но у меня возникают проблемы с его распознаванием моего закрытого ключа (который, вероятно, представляет собой отдельную публикацию вместе

Ключи, которые я использую для шифрования и дешифрования, - это 4096-битные ключи RSA, созданные GnuPG. В обоих случаях, используя парольную фразу и файл парольной фразы, я ' Я пробовал передать вывод в файл через > myFile.txt , но, похоже, это не имеет никакого значения.

Вот методы gpgEncrypt, gpgDecrypt и getStreamText. Я опубликовал оба, поскольку шифрование работает, и я не вижу явных различий между тем, как я выполняю и обрабатываю процесс между методами шифрования и дешифрования. getStreamText просто считывает содержимое потоков и возвращает строку.

EDIT: Краткое примечание, среда Windows. Если я скопирую вывод команды дешифрования, он отлично работает через консоль. Итак, я знаю, что команда действительна.


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();
}
5
задан Andrew Thompson 4 July 2012 в 05:43
поделиться