Как упаковать / зашифровать / распаковать / расшифровать кучу файлов в Java? - PullRequest
3 голосов
/ 13 ноября 2009

По сути, я пытаюсь сделать следующее на веб-сайте, управляемом Java / JSP:

  • Пользователь вводит пароль
  • Пароль используется для создания сильно зашифрованного архивного файла (zip или чего-либо еще), содержащего текстовый файл, а также ряд двоичных файлов, которые хранятся на сервере. По сути это резервная копия файлов и настроек пользователя.
  • Позже пользователь может загрузить файл, предоставить исходный пароль, а сайт расшифрует и распакует архив, сохранит извлеченные двоичные файлы в соответствующую папку на сервере, а затем прочитает текстовый файл, чтобы сайт мог восстановить старые настройки пользователя и метаданные о двоичных файлах.

Это создание / шифрование архива, а затем извлечение его содержимого, которое я пытаюсь выяснить, как это сделать. Мне действительно безразличен формат архива, кроме того, что он очень безопасен.

Идеальное решение моей проблемы будет очень легко реализовать, и для него потребуются только проверенные библиотеки с бесплатными и неограниченными лицензиями (например, apache, berkeley, lgpl).

Мне известны библиотеки TrueZIP и WinZipAES; первое кажется огромным излишним, и я не могу сказать, насколько стабильным является последнее ... Существуют ли другие решения, которые будут работать хорошо?

Ответы [ 4 ]

6 голосов
/ 13 ноября 2009

Если вы знаете, как создать zip-файл с помощью пакета java.util.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();
    } 
}
4 голосов
/ 13 ноября 2009

Ответ уже дан (используйте шифр, как указал Кевин), поэтому я делаю только предложение по важному вопросу, который, по-видимому, отсутствует в вашей теме: убедитесь, что вы используете HTTPS вместо HTTP. В противном случае тот, у кого есть сетевой сниффер, сможет получить предоставленный пользователем пароль из пакетов. Как это сделать, зависит от рассматриваемого сервера приложений. Лучше всего обратиться к его документации. Если это, например, Apache Tomcat, то вы можете найти все в Tomcat SSL HOW-TO .

Надеюсь, это поможет.

0 голосов
/ 13 ноября 2009

Конечно, здесь есть несколько предложений о том, как решить вашу проблему, но я упускаю очень большое НО в ответах. Вы не можете использовать как «основанный на пароле», так и «надежное шифрование» для любого разумного определения «надежного шифрования».

0 голосов
/ 13 ноября 2009

Хотя это может не относиться к вашему запросу, мне интересно, может ли truecrypt быть полезным. Ваш веб-сервер может создать зашифрованный контейнер, в который будет скопирован zip-файл. Зашифрованный контейнер может быть загружен. Потенциально немного грязно, однако шифрование должно быть надежным, и загруженный образ может быть смонтирован в различных операционных системах.

...