encrypted-zip-files

Zur Zeit arbeite ich an einem spannenden Projekt: Ziel ist die Erstellung einer Java basierten Webanwendung, die verschiedene Workflows inkl. LDAP-basiertem Rechtemanagement für Softwarereleases abbildet. Im Kontext dieser Workflows müssen Daten aus unterschiedlichen Quellen (z.B. SVN, Git, Jenkins) abgerufen, aufbereitet, paketiert und in definierten Formaten an bestimmte Ziele (FTP-Server, Network-shares etc.) geschickt werden. U.a. ist als Format hier das ZIP-Format (mit Verschlüsselung) vorgesehen.

Das klingt zunächst sehr simpel, jedoch unterstützt Java in der Version 8 (Projektvorgabe) zwar das Erstellen von zip Files (package: java.util.zip), jedoch keine Verschlüsselung. Ein Blick auf mvnrepository.com liefert hierzu einige Treffer.

Mit am populärsten dürfte sicherlich ‘Apache Commons Compress’ sein, jedoch zeigt ein Blick in die Dokumentation, dass die Verschlüsselung von Zip-files nicht unterstützt wird (wohl aber von anderen Formaten wie 7z, was mir jedoch leider nicht weiter hilft). Gleiches gilt für ‘Snappy Java’, hier lässt sich bereits in der Liste der Features kein Wort zum Thema Verschlüsselung finden. Nach einem kurzen Vergleich der unterschiedlichen Bibliotheken habe ich mich schließlich für Zip4J von Lingala entschieden. Die Verwendung ist simpel, jedoch enthält der Konstruktor der Klasse ZipFile, der einen String als Argument entgegen nimmt, meiner Ansicht nach einen Fehler:

1
2
ZipFile zip = new ZipFile("C:\\test\\test.zip");
zip.addFile(srcFile, params);
1
2
Exception:
net.lingala.zip4j.exception.ZipException: Probably not a zip file or a corrupted zip file

Wie ich im Dateisystem sehen kann, wird zwar eine Datei test.zip erzeugt, diese ist jedoch leer und besitzt eine Größe von 0kb.
Nach einigen Tests habe ich festgestellt, dass der andere Konstruktor, der ein File-Objekt als Argument erwartet, besser funktioniert. Zunächst liefert

1
2
File ziel = new File("C:\\test\\", "test.zip");
ZipFile zip = new ZipFile(ziel.getAbsoluteFile());

jedoch wieder die gleiche Exception. Mangelnde Rechte im Dateisystem seitens der Anwendung habe ich durch einen kurzen Test ausgeschlossen, ein

1
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("C:\\test\\test.zip"))

legt problemlos die gewünschte Zip-Datei (allerdings unverschlüsselt) an und auch ein anschließendes Befüllen des Zips ist möglich. Nach einigen Tests hat sich herausgestellt, dass das Problem mit dem Pfad zu tun hat, denn die Verwendung des temp-Dirs funktioniert hier einwandfrei:

1
2
3
File ziel = new File(System.getProperty("java.io.tmpdir"), "test.zip");
ZipFile zip = new ZipFile(ziel.getAbsoluteFile());
zip.addFile(srcFile, params);

Wie erwähnt, ermöglicht es Zip4J verschlüsselte Zip-Archive zu erstellen. Hierzu muss lediglich ein ZipParameters-Objekt erzeugt und als zweites Argument z.B. an die addFile()-Funktion übergeben werden:

1
2
3
4
5
6
7
ZipParameters params = new ZipParameters();
params.setCompressionLevel(Zip4jConstants.COMP_DEFLATE);
params.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_MAXIMUM);
params.setEncryptFiles(true);
params.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
params.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
params.setPassword("Passw0rt");

Die maximal unterstützte Schlüssellänge im Fall von AES beträgt 256 bit. In Bezug auf das verschlüsselte zip-File ist zu beachten, dass nur die einzelnen im Archiv enthaltenen Dateien verschlüsselt werden, nicht jedoch der Index, d.h. eine Auflistung der Dateinamen ist auch ohne Passworteingabe möglich.

Sofern jemand noch eine bessere Lösung für das Generieren von verschlüsselten Zip-Archiven kennt, würde ich mich über einen entsprechenden Hinweisen in den Kommentaren freuen!