ПРИМЕЧАНИЕ: Вернемся к этому позже, так как я не смог найти рабочего решения. Осушение входных потоков вручную вместо использования 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();
}