2016-03-03 76 views
0

我正在與Cipher在底層socketdataoutputstream之間進行連接。現在根據CipherOutputStream的說明文件,爲了讓最後一個塊加密掉,我們需要調用close()。所以在try-with-resource中使用它也會關閉底層的流,我不想因爲我需要它們進行進一步的操作。

那麼是否有任何方法或實施,這將有助於我在沒有dataoutputstreamsocket的情況下關閉cipheroutputstream。我聽說FilterOutputStream,但我不知道如何與他們合作。

我的代碼:關閉沒有DataOutputStream和套接字的CipherOutputStream

public class ClientHandler implements Runnable { 
Socket msock; 
DataInputStream dis; 
DataOutputStream dos; 
String ip; 
private miniClientHandler(Socket msock) { 
      this.msock = msock; 
     } 
@Override 
public void run() { 
    try { 
     dis = new DataInputStream(msock.getInputStream()); 
     dos = new DataOutputStream(msock.getOutputStream()); 

     ip = msock.getInetAddress().getHostAddress(); 

     String msg = dis.readLine(); 
     System.out.println(msg); 

     if (msg.equals("Download")) { 

        String file2dl = dis.readLine(); //2 
        File file = new File(sharedDirectory.toString() + "\\" + file2dl); 
        dos.writeLong(file.length()); //3+ 

        //AES-128 bit key initialization. 
        byte[] keyvalue = "AES128BitPasswd".getBytes(); 
        SecretKey key = new SecretKeySpec(keyvalue, "AES"); 

        //Initialize the Cipher. 
        Cipher encCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
        encCipher.init(Cipher.ENCRYPT_MODE, key); 

        //Get the IV from cipher. 
        IvParameterSpec spec = null; 
        try { 
         spec = encCipher.getParameters().getParameterSpec(IvParameterSpec.class); 
        } catch (InvalidParameterSpecException ex) { 
         Logger.getLogger(PeersController.class.getName()).log(Level.SEVERE, null, ex); 
        } 

        byte[] iv = spec.getIV(); 

        dos.write(iv, 0, iv.length); //4+ 

        //Encryption Mechanism. 
        try (FileInputStream fis = new FileInputStream(file)) { 
         try (CipherOutputStream cos = new CipherOutputStream(dos, encCipher)) { 
          int read; 
          byte[] buffer = new byte[1024 * 1024]; 
          while ((read = fis.read(buffer)) != -1) { 
           cos.write(buffer, 0, read); //5+ due to dos as underlying parameter of cos. 
          } 
         } 
        } 

        String message = dis.readLine(); 
        System.out.println(message); 
        if (message.equals("Fetching Done")) { 
         System.out.println("Fetching Done!"); 
        } else if (message.equals("Fetching Drop")) { 
         System.out.println("Fetching Denied!"); 
        } 
       } 
      } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { 
       System.out.println(e.getMessage()); 
      } 
     } 

    } 


現在,因爲COS被包裹在試穿與資源,當while循環結束,它會關閉流和潛在的dos流已進一步包裹msock導致整個套接字關閉,剩下的代碼沒用了。

其餘代碼:

String message = dis.readLine(); 
    System.out.println(message); 
    if (message.equals("Fetching Done")) { 
     System.out.println("Fetching Done!"); 
    } else if (message.equals("Fetching Drop")) { 
       System.out.println("Fetching Denied!"); 
    } 
+0

你必須運行你自己的'Cipher'對象,然後調用'更新()'和'doFinal()'就可以了,而不是使用密碼輸出流,但你爲什麼不使用SSL? – EJP

+0

@EJP只是在正常的大學項目上工作。而且,到現在爲止,還沒有任何關於SSL的經驗。無論如何,我會研究它。你能否提供一些片段實施,以便我可以將其標記爲最終答案。 – androizer

回答

0

不知何故,我設法解決我的問題,我自己用@EJP推薦的幫助下通過update() & doFinal()創建自己的Cipher對象。

代碼:

//Encryption Mechanism. 
    try (FileInputStream fis = new FileInputStream(file)) { 

     byte[] buffer = new byte[1024 * 1024]; 
     byte[] cipherBlock = new byte[encCipher.getOutputSize(buffer.length)]; 
     int cipherBytes; 
     int read; 
     while ((read = fis.read(buffer)) != -1) { 
       cipherBytes = encCipher.update(buffer, 0, read, cipherBlock); 
       dos.write(cipherBlock, 0, cipherBytes); 
     } 
     cipherBytes = encCipher.doFinal(cipherBlock, 0); //let out the last block out of the encryptor. 
     dos.write(cipherBlock, 0, cipherBytes); 
    } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException ex) { 
       Logger.getLogger(PeersController.class.getName()).log(Level.SEVERE, null, ex); 
     }