2014-12-08 599 views
1

我有一個讀取文件(例如* .zip)的問題,並使用3DES對其進行加密,使用加密文件的名稱生成的secretKey。 然後我需要解密這個文件,然後把它寫在硬盤上。 我試圖解決這個問題,但解密文件時卡住了。3des加密/解密文件java

這裏是加密

public class Encryptor { 
    private static String inputFilePath = "D:/1.txt"; 
    public static void main(String[] args) { 
     FileOutputStream fos = null; 
     File file = new File(inputFilePath); 
     String keyString = "140405PX_0.$88"; 
     String algorithm = "DESede"; 
     try { 
      FileInputStream fileInputStream = new FileInputStream(file); 
      byte[] fileByteArray = new byte[fileInputStream.available()]; 
      fileInputStream.read(fileByteArray); 
      for (byte b : fileByteArray) { 
      System.out.println(b); 
      } 
      SecretKey secretKey = getKey(keyString); 
      Cipher cipher = Cipher.getInstance(algorithm); 
      cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
      ObjectOutputStream objectOutputStream = new ObjectOutputStream 
        (new CipherOutputStream 
          (new FileOutputStream 
            ("D:/Secret.file"), cipher)); 
      objectOutputStream.writeObject(fileByteArray); 
      objectOutputStream.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    public static SecretKey getKey(String message) throws Exception { 
     String messageToUpperCase = message.toUpperCase(); 
     byte[] digestOfPassword = messageToUpperCase.getBytes(); 
     byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); 
     SecretKey key = new SecretKeySpec(keyBytes, "DESede"); 
     return key; 
    } 
} 

的代碼這裏是解密

public class Decryptor { 
    public static void main(String[] args) { 
     try { 
      File inputFileNAme = new File("d:/Secret.file"); 
      FileInputStream fileInputStream = new FileInputStream(inputFileNAme); 
      FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath); 
      SecretKey secretKey = getKey(keyString); 
      Cipher cipher = Cipher.getInstance(algorithm); 
      cipher.init(Cipher.DECRYPT_MODE, secretKey); 
      ObjectInputStream objectInputStream = new ObjectInputStream 
        (new CipherInputStream(fileInputStream, cipher)); 
      System.out.println(objectInputStream.available()); 
      while (objectInputStream.available() != 0) { 
       fileOutputStream.write((Integer) objectInputStream.readObject()); 
       System.out.println(objectInputStream.readObject()); 
      } 
      fileOutputStream.flush(); 
      fileOutputStream.close(); 
      fileInputStream.close(); 
      objectInputStream.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    public static SecretKey getKey(String message) throws Exception { 
     String messageToUpperCase = message.toUpperCase(); 
     byte[] digestOfPassword = messageToUpperCase.getBytes(); 
     byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); 
     SecretKey key = new SecretKeySpec(keyBytes, "DESede"); 
     return key; 
    } 
} 

當我嘗試解密我的文件,我沒有得到在輸出文件中的任何代碼。
我試過做調試,並看到,objectInputStream.available()總是包含0.
請告訴我,我該如何解決這個問題,以及爲什麼會發生。

回答

2
  1. 的使用

    byte[] fileByteArray = new byte[fileInputStream.available()]; 
    

    specifically warned against in the Javadoc:「這是從來沒有正確的使用這個方法的返回值來分配打算持有該流中的所有數據的緩衝器。」

    文件應該一次處理記錄或緩衝區。

  2. 線:

    fileInputStream.read(fileByteArray); 
    

    不能保證填充緩衝區。你必須檢查返回值:for -1,意思是文件結尾,或> 0,表示實際傳輸的字節數。看到Javadoc。

  3. 同樣

    while (objectInputStream.available() != 0) { 
    

    不是流的末尾有效的測試。你應該叫readObject()直到它拋出EOFException.

1

這樣的quickfix,這個工程:

try { 
     File inputFileNAme = new File("d:/Secret.file"); 
     FileInputStream fileInputStream = new FileInputStream(inputFileNAme); 
     FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath); 
     SecretKey secretKey = getKey(keyString); 
     Cipher cipher = Cipher.getInstance(algorithm); 
     cipher.init(Cipher.DECRYPT_MODE, secretKey); 
     ObjectInputStream objectInputStream = new ObjectInputStream 
       (new CipherInputStream(fileInputStream, cipher)); 
     System.out.println(objectInputStream.available()); 
     fileOutputStream.write((byte[]) objectInputStream.readObject()); 
     fileOutputStream.flush(); 
     fileOutputStream.close(); 
     fileInputStream.close(); 
     objectInputStream.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

我所做的是去掉「.available() while循環」,並刪除該投給Integer,這是錯誤的。

我同意EJP的回答,特別是關於使用.available()

您也可以使用http://www.jasypt.org/,它提供了一個更簡單的API來加密文件。

+0

'close()'之前的'flush()'是多餘的,就像關閉包裝在其他流中的流一樣。這些都沒有解決發送方面的問題。 – EJP 2014-12-08 08:59:56

+0

這個解決方案不是一個不錯的和乾淨的解決方案,它是一個解決OP問題的_quickfix_。如果需要的話,它可以被很好地和乾淨地重寫。 (事實上​​,我爲你的答案+1了@EJP) – superbob 2014-12-08 10:00:08