Java DeflaterInputStream() в ZlibInflation
В настоящее время я работаю над проектом, который включает сжатие и шифрование в Java, а также дешифрование и инфляцию в C++.
До того, над чем я работал, мы создавали сжатые файлы, используя ZipOutputStream в Java. Эти файлы будут раздувать zlib в C++ просто отлично, используя код zpipe.c, приведенный в качестве примера на ZLib. Нашим последним изменением было сжатие этих файлов и их шифрование перед сохранением в родительском zip-архиве. При этом я переключился на использование класса DeflaterInputStream в Java для произвольного сжатия байтов до тех пор, пока мне не хватит для блочного шифра.
При переключении на этот класс "DeflaterInputStream" файлы больше не будут раздуваться с помощью ZLib. Zlib выбрасывает "Z_DATA_ERROR" в поток.
Для проверки до сих пор я убедился, что криптологическая логика действительна. Я могу просто накачать файлы в Java, используя класс "Inflater". Оба класса инфлатера начинаются с одного расшифрованного блока. Ex. Я убедился, что первый блок, который выходит из шифра, одинаков как для Java, так и для C++. Мне кажется, что DeflaterInputStream не выводит истинный формат выкачки? Я не уверен.
РЕДАКТИРОВАТЬ: Чтобы уточнить мою конкретную реализацию Пример Pseduo Code:
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 - прекрасный проект.