В настоящее время я работаю над проектом, который включает сжатие и шифрование в Java, а также дешифрование и инфляцию в C ++.
До того, над чем я работал, мы создавали сжатые файлы, используя ZipOutputStream в Java. Эти файлы будут раздувать zlib в C ++ просто отлично, используя код zpipe.c, приведенный в качестве примера на ZLib. Нашим последним изменением было сжатие этих файлов и их шифрование перед сохранением в родительском zip-архиве. При этом я переключился на использование класса DeflaterInputStream в Java для произвольного сжатия байтов до тех пор, пока мне не хватит для блочного шифра.
При переключении на этот класс «DeflaterInputStream» файлы больше не будут раздуваться с помощью ZLib. Zlib выбрасывает «Z_DATA_ERROR» в поток.
Для проверки до сих пор я убедился, что криптологическая логика действительна. Я могу просто накачать файлы в Java, используя класс «Inflater». Оба класса инфлатера начинаются с одного расшифрованного блока. Ex. Я убедился, что первый блок, который выходит из шифра, одинаков как для Java, так и для C ++. Мне кажется, что DeflaterInputStream не выводит истинный формат выкачки? Я не уверен.
РЕДАКТИРОВАТЬ: чтобы уточнить мою конкретную реализацию
Пример псевдо-кода:
Java (Работа с zpipe)
FileOutputStream dest = new FileOutputStream("zipfile.zip");
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
ZipEntry entry = new ZipEntry("filename");
out.putNextEntry(entry);
FileInputStream fileInputStream = new FileInputStream("file_to_compress");
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = fileInputStream.read(buf)) > 0) {
out.write(buf, 0, bytesRead);
}
out.closeEntry();
out.close();
fileInputStream.close();
Java (не работает с zpipe)
FileOutputStream dest = new FileOutputStream("zipfile.zip");
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
DeflaterInputStream deflater = new DeflaterInputStream("file_to_compress");
/* Redacted code to compress file, encrypt, write to file and calculate CRC
Assume encryptedFile is a reference to the result of this process */ZipEntry entry = new ZipEntry("filename");
entry.setCrc32(encryptedFile.getCrc32());
entry.setCompressedSize(encryptedFile.getLength());
entry.setMethod(ZipEntry.STORED); /* Should not try to compress encrypted file*/
out.putNextEntry(entry);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = encryptedFile.read(buf)) > 0) {
out.write(buf, 0, bytesRead);
}
out.closeEntry();
encryptedFile.close();
out.close();
Так что в значительной степени я использую DeflaterInputStream, чтобы сжать фиксированный размер для подачи в шифр, а затем сохранить в архиве. У меня это работает от начала до конца внутри Java, беря результаты DeflaterInputStream и шифра и записывая в файл, затем расшифровывая в буфер открытого текста и используя класс Inflater для обработки этого. Насколько я понимаю, классы Inflater и DeflaterInputStream обрабатывают необработанный поток deflate без учета или добавления какого-либо заголовка архива. Мы используем наш собственный код на C ++ для разбора заголовков архива и всего, что нужно для подачи в zpipe.
Я ожидаю, что Zlib / Zpipe сможет обрабатывать необработанный поток, который я создаю с использованием DeflaterInputStream, так же, как если бы я сжимал с использованием универсального объекта ZipEntry / ZipOutputStream.
С тех пор как я попытался использовать DeflaterInputStream, zlib / zpipe выдает ошибку при попытке прочитать поток.
ОБНОВИТЬ
Для устранения неполадок я сделал следующее:
Сохранен необработанный вывод DeflaterInputStream, сжимающего файл.
Использовал тот же файл в паре ZipOutputStream / ZipEntry для создания сжатого архива zip.
Использовал Hex Editor для удаления локальных заголовков файлов и центрального каталога архива, оставляя только необработанный поток deflate.
Запустил отредактированный файл (raw deflate stream) через zpipe: сработало
Запустил вывод DeflaterInputStream через zpipe: не работает
ОБНОВЛЕНИЕ 2
Так что я просто сравнил результаты двух.
DeflaterInputStream дает мне два дополнительных байта в начале потока. Я понятия не имею, что это за байты. Если я пропущу их с помощью fseek (), файл распаковывается очень хорошо. Значения 0x78 0x9C этих загадочных байтов …
ОБНОВЛЕНИЕ 3
Я ссылался на RFC 1951 на протяжении всего этого процесса, однако, похоже, что магические два байта взяты из RFC 1950. Было введено в заблуждение названием «DeflaterInputStream».
Инициализация DeflaterInputStream с помощью следующего решает мою проблему:
Deflater def = new Deflater(Deflater.DEFAULT_COMPRESSION,true);
DeflaterInputStream defIfs = new DeflaterInputStream(ifs,def);
Большое спасибо Марку за внимание к этому вопросу! Zlib — прекрасный проект.
Задача ещё не решена.
Других решений пока нет …