2010-12-06 29 views
5

注意:稍後回顧,因爲我找不到工作解決方案。因爲inputStream.read()方法永久阻止程序,所以手動排空輸入流而不是使用BufferedReaders似乎沒有幫助。我將gpg調用放在一個批處理文件中,並從Java調用該批處理文件以獲得相同的結果。一旦使用解密選項調用gpg,輸入流似乎變得無法訪問,從而阻止了整個程序。當我有更多時間專注於這項任務時,我必須回到這個問題。同時,我必須通過其他方式解密工作(可能是BouncyCastle)。在Java中通過運行時進程調用GnuPG以加密和解密文件 - 解密始終掛起

最後一個選項可能會嘗試是調用CMD.EXE,並通過這一過程產生的輸入流寫入命令

我明白在這個問題上的援助。


我一直在這個問題上幾天,並沒有取得任何進展,所以我想我會轉向exeprtise這裏一些幫助。

我創建一個簡單的程序,將通過Java運行過程調用的GnuPG。它需要能夠加密和解密文件。加密工作,但我有一些解密文件的問題。每當我嘗試解密文件時,該過程都會掛起。 exitValue()總是拋出它的IllegalThreadStateException,並且程序突然發生,好像它仍在等待。這些方法的代碼附在下面。該程序的最終目標是解密文件,並用Java解析它的內容。

我已經嘗試了三種方法來獲得gpgDecrypt方法工作。第一種方法是通過刪除passphrase-fd選項並通過catch塊中的gpgOutput流將密碼寫入gpg,假設它通過命令行提示輸入密碼。這不起作用,所以我把密碼放在一個文件中並添加了-passphrase-fd選項。在這種情況下,程序無限重複。如果我通過gpgOutput流寫入任何內容,程序將完成。打印的出口值將爲2,結果變量將爲空白。

第三個選項是BouncyCastle的,但我有得到它的問題認識我的私有密鑰(這可能是一個獨立的後一起)。

我使用的加密和解密的密鑰是4096位RSA密鑰,通過GnuPG的產生。在使用密碼和密碼文件的兩種情況下,我都嘗試通過> myFile.txt將輸出傳輸到文件,但似乎沒有任何區別。

這裏有gpgEncrypt,gpgDecrypt和getStreamText方法。自從加密工作後,我都發布了兩篇文章,而且在執行和處理加密和解密方法之間的過程之間我看不到任何明顯的差異。 getStreamText只是讀取流的內容並返回一個字符串。

編輯:快速筆記,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(); 
} 
+3

我已經完成了從Java批量/腳本調用**很多**。我可以告訴你一件事:試圖構建一個包含間距字符的字符串是災難的祕訣。做**永遠不要**調用* Runtime.getRuntime()。exec(String)*方法。你**應該做的是分割你的String並調用* Runtime.getRuntime()。exec(String [])*方法。請注意,我並不是說它會解決您在此處遇到的問題:我所說的是,如果您按照當前的方式繼續調用批處理/腳本,您將會受到某種程度的影響。 – SyntaxT3rr0r 2010-12-06 14:20:51

+0

感謝您的意見。我會重構這個。不管它是否解決了這個問題,我同意它確實需要完成。 – framauro13 2010-12-06 15:19:06

+0

你有沒有找到答案,我也遇到過同樣的事情!我開始編碼,看到你的例子看到[溪流狼吞虎嚥](http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4#codewrap144)問題,我用那個太。但是,當文件已經存在並且我gpg.exe正在等待用戶點擊'y '時,這個懸掛問題依然存在。但令人不快的部分是提示選擇Y/N永遠不會出現在控制檯(Stream Gobbler)中,所以我無法通過編程來處理。流gobbler確實顯示gpg.exe是否成功完成。 – 2011-11-25 18:27:40

回答

1

你試過從命令行運行該命令,而不是從Java代碼? 當GnuPG等待控制檯輸出時,可能會出現'僅限於您的眼睛'選項的問題。

1

這可能是也可能不是問題(在解密函數)

BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream())); 
    BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream())); 
    BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream())); 

你包裹的getInputStream結果的兩倍。顯然gpgErrorOutput應該包裝錯誤流,而不是輸入流。

0
int exitValue = gpgProcess.exitValue(); 

//它給進程還沒有退出異常

0

它的工作對我來說,當我更換以下命令

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

解密命令我忘了你是如何處理它在Java中,有是100個方法。但我堅持瞭解密命令本身,這是非常有幫助的,雖然你並不需要所有的報價,如果你想解密大文件,它是這樣的:

gpg --passphrase-fd 0 --output yourfile.txt --decrypt /encryptedfile.txt.gpg/ 0</passwrdfile.txt 
1

我偶然發現了這個線程今天是因爲我在程序掛起時遇到了完全相同的問題。 Cameron上面的線程包含解決方案,這就是您必須從流程中消耗inputStream。如果你不這樣做,那麼這個小河就會填滿並掛起。只需加入

String line = null; 
while ((line = gpgOutput.readLine()) != null) { 
    System.out.println(line); 
} 

在檢查exitValue之前,確定了它。