HINWEIS: Ich komme später zurück, da ich keine funktionierende Lösung gefunden habe. Das manuelle Löschen der Eingabeströme anstelle der Verwendung von BufferedReaders scheint nicht hilfreich zu sein, da die Methode inputStream.read() das Programm permanent blockiert. Ich legte den GPG-Aufruf in eine Batch-Datei und rief die Batch-Datei von Java, um nur das gleiche Ergebnis zu erhalten. Sobald gpg mit der Entschlüsselungsoption aufgerufen wird, scheint der Eingabestream nicht mehr zugänglich zu sein und blockiert das gesamte Programm. Ich muss darauf zurückkommen, wenn ich mehr Zeit habe, mich auf die Aufgabe zu konzentrieren. In der Zwischenzeit muss ich die Entschlüsselung mit anderen Mitteln (wahrscheinlich BouncyCastle) arbeiten lassen.Aufruf von GnuPG in Java über einen Laufzeitprozess zum Verschlüsseln und Entschlüsseln von Dateien - Entschlüsseln bleibt immer hängen
Die letzte Option wahrscheinlich versuchen, ist cmd.exe zu nennen, und den Befehl über den Eingangsstrom durch dieses Verfahren erzeugte schreiben ...
ich die Hilfe zu diesem Thema zu schätzen wissen.
Ich habe für ein paar Tage an diesem Problem gearbeitet und haben keine Fortschritte gemacht, so dass ich dachte, dass ich auf die exeprtise für etwas Hilfe hier drehen würde.
Ich erstelle ein einfaches Programm, das GnuPG über einen Java-Laufzeitprozess aufruft. Es muss in der Lage sein, Dateien zu verschlüsseln und zu entschlüsseln. Verschlüsselung funktioniert, aber ich habe einige Probleme beim Entschlüsseln von Dateien. Immer wenn ich versuche, eine Datei zu entschlüsseln, hängt der Prozess. exitValue()
löst immer IllegalThreadStateException aus und das Programm tuckert weiter, als würde es immer noch warten. Der Code für diese Methoden ist unten aufgeführt. Das ultimative Ziel des Programms ist es, die Datei zu entschlüsseln und ihre Inhalte in Java zu parsen.
Ich habe drei Ansätze ausprobiert, um die gpgDecrypt-Methode zum Laufen zu bringen. Der erste Ansatz beinhaltete das Entfernen der Passphrase-fd-Option und das Schreiben der Passphrase in gpg über den gpgOutput-Stream im catch-Block, wobei angenommen wurde, dass die Passphrase wie über die Befehlszeile abgefragt wurde. Das hat nicht funktioniert, also habe ich die Passphrase in eine Datei geschrieben und die Option -passphrase-fd hinzugefügt. In diesem Fall wird das Programm unendlich wiederholt. Wenn ich irgendetwas über den gpgOutput-Stream schreibe, wird das Programm beendet. Der ausgegebene Exit-Wert hat den Wert 2, und die Ergebnisvariable ist leer.
Die dritte Option ist BouncyCastle, aber ich habe Probleme, es meinen privaten Schlüssel zu erkennen (was wahrscheinlich ein separater Beitrag alle zusammen ist).
Die Schlüssel, die ich zum Verschlüsseln und Entschlüsseln verwende, sind 4096-Bit-RSA-Schlüssel, die von GnuPG generiert werden. In beiden Fällen, in denen ich die Passphrase und die Passphrase-Datei verwende, habe ich versucht, die Ausgabe über > myFile.txt
in eine Datei zu leiten, aber es scheint keinen Unterschied zu machen.
Hier sind die Methoden gpgEncrypt, gpgDecrypt und getStreamText. Ich habe beide gepostet, seit die Verschlüsselung funktioniert, und ich kann keine eklatanten Unterschiede zwischen der Ausführung und der Verarbeitung des Prozesses zwischen den Verschlüsselungs- und Entschlüsselungsmethoden feststellen. getStreamText liest nur den Inhalt der Streams und gibt eine Zeichenfolge zurück.
EDIT: Schnelle Notiz, Windows-Umgebung. Wenn ich die Ausgabe des Entschlüsselungsbefehls kopiere, funktioniert es über die Konsole einwandfrei. Ich weiß also, dass der Befehl gültig ist.
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();
}
Ich habe eine Menge Batch/Script-Aufrufe von Java gemacht. Ich kann Ihnen eines sagen: Der Versuch, einen String mit Leerzeichen zu erstellen, ist ein Rezept für ein Desaster. Rufen Sie ** NIEMALS ** die Methode * Runtime.getRuntime() .exec (String) * auf. Was Sie ** SOLLTEN ** ist, teilen Sie Ihre Zeichenfolge und rufen Sie die * Runtime.getRuntime() .Exec (String []) * -Methode. Beachten Sie, dass ich nicht sage, dass es das Problem lösen soll, das Sie hier haben: Alles, was ich sage, ist, dass Sie irgendwann leiden werden, wenn Sie Charge/Skripte so aufrufen, wie Sie es gerade tun. – SyntaxT3rr0r
Danke für die Eingabe. Ich werde das umgestalten. Unabhängig davon, ob es das Problem behebt oder nicht, stimme ich zu, dass es getan werden muss. – framauro13
Haben Sie irgendwelche Antworten gefunden, bin ich auch auf dasselbe gestoßen! Ich fing an zu codieren, als ich dein Beispiel sah, als ich das [stream gobbler] (http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4#codewrap144) Problem sah, das ich benutzt habe auch. Aber dieses hängende Problem blieb bestehen, als es bereits eine Datei gab und i gpg.exe darauf wartete, dass der Benutzer 'y' schlug. Aber der irritierende Teil war die Aufforderung zu wählen, dass y/N niemals in der Konsole erscheint (Stream Gobbler), also kann ich das programmatisch nicht handhaben. Der Stream-Gobbler zeigt an, ob gpg.exe erfolgreich abgeschlossen wurde. –