ПРИМЕЧАНИЕ: Возвращаясь к этому позже, так как я не смог найти работающего решения.Удаление потоков ввода вручную вместо использования BufferedReaders, похоже, не помогает, так как метод inputStream.read () навсегда блокирует программу.Я поместил вызов gpg в пакетный файл и вызвал пакетный файл с Java, чтобы получить только тот же результат.Когда gpg вызывается с опцией decrypt, входной поток становится недоступным, блокируя всю программу.Я должен вернуться к этому, когда у меня будет больше времени, чтобы сосредоточиться на задаче.В то же время, мне нужно, чтобы расшифровка работала другими способами (вероятно, 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 просто читает содержимое потоков и возвращает строку.
РЕДАКТИРОВАТЬ: Краткое примечание, среда 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);
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();
}