如何打包/加密/解压缩/ Java解密一堆文件?

问题描述:

我基本上是试图做在Java/JSP驱动的网站如下:如何打包/加密/解压缩/ Java解密一堆文件?

  • 用户提供了密码
  • 密码被用来建立一个强加密的档案文件(ZIP,或任何其他)包含一个文本文件以及存储在服务器上的许多二进制文件。它本质上是用户文件和设置的备份。
  • 稍后,用户可以上传文件,提供原始密码,网站将解密并解压缩存档,将提取的二进制文件保存到服务器上相应的文件夹中,然后阅读文本文件,以便网站可以恢复用户关于二进制文件的旧设置和元数据。

这是建筑/加密档案,然后提取其内容,我试图找出如何做。我真的不关心档案格式,除非它非常安全。

我的问题的理想解决方案将很容易实现,并且只需要经过免费和非限制性许可证(例如apache,berkeley,lgpl)的久经考验的库。

我知道TrueZIP和WinZipAES库;前者似乎是大规模的矫枉过正,我不能说出后者有多稳定......是否还有其他解决方案能够很好地工作?

如果你知道如何使用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

答案已经给出(使用的密码凯文指出的),所以我只能做一个建议,关于这似乎是缺少一个重要的问题您的topicstart:确保您使用HTTPS而不是HTTP。否则,使用网络嗅探器的用户将能够从数据包中获取用户提供的密码。如何做到这一点取决于有问题的应用程序服务器。最好的是参考它的文档。如果它是例如Apache Tomcat,那么您可以在Tomcat SSL HOW-TO中找到所有内容。

希望这会有所帮助。

虽然它可能不是特定于您的查询,我不知道是否truecrypt可能有用。你的网络服务器可以创建一个加密的容器,压缩文件将被复制到其中。然后可以下载加密的容器。可能有点麻烦,但加密应该很强大,下载的映像可以安装在各种操作系统上。

这里肯定有一些关于如何解决你的问题的建议,但是我在答复中错过了一个很大的答案。对于“强加密”的任何合理定义,您无法同时实现“基于密码”和“强加密”。

+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