2009-11-13 85 views
2

我基本上是試圖做在Java/JSP驅動的網站如下:如何打包/加密/解壓縮/ Java解密一堆文件?

  • 用戶提供了密碼
  • 密碼被用來建立一個強加密的檔案文件(ZIP,或任何其他)包含一個文本文件以及存儲在服務器上的許多二進制文件。它本質上是用戶文件和設置的備份。
  • 稍後,用戶可以上傳文件,提供原始密碼,網站將解密並解壓縮存檔,將提取的二進制文件保存到服務器上相應的文件夾中,然後閱讀文本文件,以便網站可以恢復用戶關於二進制文件的舊設置和元數據。

這是建築/加密檔案,然後提取其內容,我試圖找出如何做。我真的不關心檔案格式,除非它非常安全。

我的問題的理想解決方案將很容易實現,並且只需要經過免費和非限制性許可證(例如apache,berkeley,lgpl)的久經考驗的庫。

我知道TrueZIP和WinZipAES庫;前者似乎是大規模的矯枉過正,我不能說出後者有多穩定......是否還有其他解決方案能夠很好地工作?

回答

6

如果你知道如何使用java.util.zip包來創建一個zip文件,你可以創建一個PBE Cipher並傳遞到CipherOutputStream或CipherInputStream(取決於如果你正在讀或寫)。

下面應該讓你開始:

public class ZipTest { 

    public static void main(String [] args) throws Exception { 
     String password = "password"; 
     write(password); 
     read(password); 
    } 

    private static void write(String password) throws Exception { 
     OutputStream target = new FileOutputStream("out.zip"); 
     target = new CipherOutputStream(target, createCipher(Cipher.ENCRYPT_MODE, password)); 
     ZipOutputStream output = new ZipOutputStream(target); 

     ZipEntry e = new ZipEntry("filename"); 
     output.putNextEntry(e); 
     output.write("helloWorld".getBytes()); 
     output.closeEntry(); 

     e = new ZipEntry("filename1"); 
     output.putNextEntry(e); 
     output.write("helloWorld1".getBytes()); 
     output.closeEntry(); 

     output.finish(); 
     output.flush(); 
    } 

    private static Cipher createCipher(int mode, String password) throws Exception { 
     String alg = "PBEWithSHA1AndDESede"; //BouncyCastle has better algorithms 
     PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray()); 
     SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(alg); 
     SecretKey secretKey = keyFactory.generateSecret(keySpec); 

     Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede"); 
     cipher.init(mode, secretKey, new PBEParameterSpec("saltsalt".getBytes(), 2000)); 

     return cipher; 
    } 

    private static void read(String password) throws Exception { 
     InputStream target = new FileInputStream("out.zip"); 
     target = new CipherInputStream(target, createCipher(Cipher.DECRYPT_MODE, password)); 
     ZipInputStream input = new ZipInputStream(target); 
     ZipEntry entry = input.getNextEntry(); 
     while (entry != null) { 
      System.out.println("Entry: "+entry.getName()); 
      System.out.println("Contents: "+toString(input)); 
      input.closeEntry(); 
      entry = input.getNextEntry(); 
     } 
    } 

    private static String toString(InputStream input) throws Exception { 
     byte [] data = new byte[1024]; 
     StringBuilder result = new StringBuilder(); 

     int bytesRead = input.read(data); 
     while (bytesRead != -1) { 
      result.append(new String(data, 0, bytesRead)); 
      bytesRead = input.read(data); 
     } 

     return result.toString(); 
    } 
} 
+0

客戶端將使用什麼軟件來解密已加密的ZIP文件? – 2009-11-13 16:58:36

+0

@PP不要以爲這個解決方案可以做到這一點,因爲這個文件只是一個加密的blob。 OP表示他想控制解密/解包自己,而不是第三方 – Kevin 2009-11-13 17:09:58

4

答案已經給出(使用的密碼凱文指出的),所以我只能做一個建議,關於這似乎是缺少一個重要的問題您的topicstart:確保您使用HTTPS而不是HTTP。否則,使用網絡嗅探器的用戶將能夠從數據包中獲取用戶提供的密碼。如何做到這一點取決於有問題的應用程序服務器。最好的是參考它的文檔。如果它是例如Apache Tomcat,那麼您可以在Tomcat SSL HOW-TO中找到所有內容。

希望這會有所幫助。

0

雖然它可能不是特定於您的查詢,我不知道是否truecrypt可能有用。你的網絡服務器可以創建一個加密的容器,壓縮文件將被複制到其中。然後可以下載加密的容器。可能有點麻煩,但加密應該很強大,下載的映像可以安裝在各種操作系統上。

0

這裏肯定有一些關於如何解決你的問題的建議,但是我在答覆中錯過了一個很大的答案。對於「強加密」的任何合理定義,您無法同時實現「基於密碼」和「強加密」。

+0

這不一定是真的。如果你可以提供給你256個甚至192比特熵的密碼短語,你可以將它提供給任何適當的塊密碼。 – Kevin 2009-11-13 17:15:34

+0

準確地說,「如果你可以......」並且在大多數實際情況下不切合實際。英語熵(作爲一種自然語言)的估計低至0.6位/字符,這意味着你需要一個430字符長的短語來處理256位熵,這比我通常理解的要多一點作爲密碼。 – jarnbjo 2009-11-13 18:02:19

+0

當然,如果你讓人們使用英文單詞作爲密碼。只要加上一些簡單的限制 - 例如至少需要一個大寫字母和一個特殊字符 - 並且你獲得了很多熵。 – DanM 2009-11-18 13:14:40