To create a password protected zip file in Java, use the Zip4j library, enable encryption with EncryptionMethod.AES on a ZipParameters object and add the files to a ZipFile created with the password as a char[]. The JDK package java.util.zip can neither write nor read encrypted zip entries, so a library is required.
We protect zip files when an app sends reports with personal data by email, exports customer records for an auditor or stores backups on a shared drive that more people can open than should read the data.
The following example zips one CSV file with AES-256 encryption and checks the result.
Path dir = Files.createTempDirectory("payroll");
Path csv = Files.writeString(dir.resolve("salaries.csv"), "name,amount\nanna,4200\n");
Path zip = dir.resolve("salaries.zip");
ZipParameters params = new ZipParameters();
params.setEncryptFiles(true);
params.setEncryptionMethod(EncryptionMethod.AES);
try (ZipFile zipFile = new ZipFile(zip.toFile(), "S3cret-2026".toCharArray())) {
zipFile.addFile(csv.toFile(), params);
}
boolean encrypted;
try (ZipFile check = new ZipFile(zip.toFile())) {
encrypted = check.isEncrypted();
}
boolean result = encrypted; // true
Notice that the password goes to the ZipFile constructor and that the key strength is not set, because AES-256 is the Zip4j default. We cover the library features and dependency, adding several files and folders, extracting with the password, the wrong-password case, AES versus the older ZipCrypto and a real export job.
1. Zip4j Library
Zip4j is an open source Java library, under the Apache License 2.0, that reads and writes zip files with all the features of the format, including encryption. It is written in plain Java with no native code, and version 2.x, the current line, moved ZipFile to the package net.lingala.zip4j and replaced the 1.x constants with enums such as EncryptionMethod and AesKeyStrength.

1.1. Features
Zip4j covers the whole zip format, and its README lists these features for version 2.11.
- Create, add, extract, update and remove files in a zip file.
- Read and write password-protected zip files.
- AES encryption with 128-bit or 256-bit keys, and AES-192 for extracting only.
- Standard zip encryption, also called ZipCrypto.
- Zip64 format for archives and entries larger than 4 GB.
- Store (no compression) and Deflate compression methods.
- Create and extract split zip files, such as z01, z02 and zip.
- Unicode file names and a configurable charset for old archives.
- Progress monitor for long operations and stream classes for zipping data in memory.
1.2. Dependency
Add the zip4j artifact from Maven Central. Version 2.11.6 is the latest release at the time of writing, and it needs Java 8 or later for all features, so it runs on Java 25 without changes.
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.11.6</version>
</dependency>
With Gradle, the same coordinates go into implementation(“net.lingala.zip4j:zip4j:2.11.6”). Code written for Zip4j 1.x, with classes such as net.lingala.zip4j.core.ZipFile and Zip4jConstants, does not compile against 2.x.
2. Creating Password Protected Zip Files
Three objects take part in every encrypted zip. The ZipFile points to the archive and holds the password, a ZipParameters object holds the encryption and compression settings for the entries we add, and the add methods write the entries.
The examples use a folder with two reports and a subfolder of receipts.
static Path reportsFolder() throws IOException {
Path dir = Files.createTempDirectory("reports");
Files.writeString(dir.resolve("q1.csv"), "month,total\njan,100\n");
Files.writeString(dir.resolve("q2.csv"), "month,total\napr,140\n");
Files.createDirectories(dir.resolve("receipts"));
Files.writeString(dir.resolve("receipts/r-001.txt"), "paid 40");
return dir;
}
The helper aesParams() creates the encryption settings once, so every example uses the same AES-256 setup. Setting the key strength is optional, and we write it out to make the choice visible in code reviews.
static ZipParameters aesParams() {
ZipParameters params = new ZipParameters();
params.setEncryptFiles(true);
params.setEncryptionMethod(EncryptionMethod.AES);
params.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
params.setCompressionLevel(CompressionLevel.NORMAL);
return params;
}
2.1. Zipping Several Files
The method addFiles() takes a List<File> and puts each file in the root of the archive. The password is a char[], so the caller can clear it after use, which a String does not allow.
Path dir = reportsFolder();
Path zip = dir.resolve("quarterly.zip");
char[] password = "S3cret-2026".toCharArray();
try (ZipFile zipFile = new ZipFile(zip.toFile(), password)) {
zipFile.addFiles(List.of(dir.resolve("q1.csv").toFile(), dir.resolve("q2.csv").toFile()), aesParams());
}
Arrays.fill(password, '0');
List<String> names;
try (ZipFile check = new ZipFile(zip.toFile())) {
names = check.getFileHeaders().stream().map(FileHeader::getFileName).sorted().toList();
}
String entries = names.toString(); // "[q1.csv, q2.csv]"
The ZipFile class implements Closeable, so we open it in try-with-resources. Closing releases the input streams that Zip4j opened on the archive, for example through getInputStream().
2.2. Zipping a Folder with Subfolders
The method addFolder() adds a folder with all its subfolders and keeps the relative paths. By default, the folder name becomes the first path element of every entry, and setIncludeRootFolder(false) puts the contents into the root of the archive without that folder name.
Path dir = reportsFolder();
Path zip = Files.createTempDirectory("out").resolve("all-reports.zip");
ZipParameters params = aesParams();
params.setIncludeRootFolder(false);
try (ZipFile zipFile = new ZipFile(zip.toFile(), "S3cret-2026".toCharArray())) {
zipFile.addFolder(dir.toFile(), params);
}
List<String> names;
try (ZipFile check = new ZipFile(zip.toFile())) {
names = check.getFileHeaders().stream().map(FileHeader::getFileName).sorted().toList();
}
String entries = names.toString(); // "[q1.csv, q2.csv, receipts/, receipts/r-001.txt]"
Since version 2.6, ZipParameters.setExcludeFileFilter() takes a filter that leaves out files such as .DS_Store or temporary files while the folder is added.
2.3. Encrypting Data from a Stream
When the content is generated in memory, such as a CSV built from a database query, addStream() writes it without a temporary file. The entry name must be set with setFileNameInZip(), because a stream has no name.
Path zip = Files.createTempDirectory("export").resolve("export.zip");
byte[] csv = "id,email\n1,anna@example.com\n".getBytes(StandardCharsets.UTF_8);
ZipParameters params = aesParams();
params.setFileNameInZip("customers.csv");
try (ZipFile zipFile = new ZipFile(zip.toFile(), "S3cret-2026".toCharArray())) {
zipFile.addStream(new ByteArrayInputStream(csv), params);
}
long entryCount;
try (ZipFile check = new ZipFile(zip.toFile())) {
entryCount = check.getFileHeaders().size();
}
long count = entryCount; // 1
3. Extracting a Password Protected Zip File
Extraction mirrors the writing side. We open the archive with the password and call extractAll() for everything or extractFile() for one entry. Zip4j rejects entry names that point outside the destination folder, so it is protected against the zip slip attack that plain java.util.zip code has to check for itself.
Path dir = reportsFolder();
Path zip = dir.resolve("quarterly.zip");
try (ZipFile zipFile = new ZipFile(zip.toFile(), "S3cret-2026".toCharArray())) {
zipFile.addFile(dir.resolve("q1.csv").toFile(), aesParams());
}
Path out = Files.createTempDirectory("extracted");
try (ZipFile zipFile = new ZipFile(zip.toFile(), "S3cret-2026".toCharArray())) {
zipFile.extractAll(out.toString());
}
String header = Files.readAllLines(out.resolve("q1.csv")).get(0); // "month,total"
For an archive without encryption, the steps for subfolders, target folders and safe paths are the same as in unzipping a file with subdirectories using the JDK alone.
3.1. Handling a Wrong Password
A wrong or missing password ends in a ZipException whose getType() returns ZipException.Type.WRONG_PASSWORD, so the app can show a clear message instead of a stack trace. The ZipException class extends IOException.
static String tryExtract(Path zip, char[] password, Path target) {
try (ZipFile zipFile = new ZipFile(zip.toFile(), password)) {
zipFile.extractAll(target.toString());
return "extracted";
} catch (ZipException e) {
return e.getType() == ZipException.Type.WRONG_PASSWORD ? "wrong password" : "broken zip: " + e.getMessage();
} catch (IOException e) {
return "I/O error: " + e.getMessage();
}
}
Path dir = reportsFolder();
Path zip = dir.resolve("locked.zip");
try (ZipFile zipFile = new ZipFile(zip.toFile(), "S3cret-2026".toCharArray())) {
zipFile.addFile(dir.resolve("q2.csv").toFile(), aesParams());
}
String wrong = tryExtract(zip, "guess".toCharArray(), Files.createTempDirectory("a")); // "wrong password"
String right = tryExtract(zip, "S3cret-2026".toCharArray(), Files.createTempDirectory("b")); // "extracted"
The JDK cannot open such an archive at all. The constructor new java.util.zip.ZipFile(file) throws ZipException: invalid CEN header (encrypted entry) as soon as one entry is encrypted.
4. AES vs ZipCrypto Encryption
Zip files support two families of encryption, and the choice decides how safe the data is. ZipCrypto, the original zip encryption, has a known-plaintext weakness, so an attacker who knows part of one file, such as a standard CSV header, can recover the keys without guessing the password. AES encryption, in the WinZip AE-2 format that Zip4j writes, has no such shortcut.
| AES (EncryptionMethod.AES) | ZipCrypto (EncryptionMethod.ZIP_STANDARD) | |
|---|---|---|
| Strength | Strong, 128-bit or 256-bit keys | Weak, broken by known-plaintext attacks |
| Opens with built-in Windows zip support | Not in older Windows versions, 7-Zip, WinZip and WinRAR open it | Yes |
| Integrity check | HMAC on every entry | CRC only |
| Use for | Personal, financial and business data | Only when the receiver cannot install a zip tool and the data is not sensitive |
Use AES unless a receiver depends on the built-in zip support of an older Windows version. In that case, tell the receiver that ZipCrypto keeps out casual readers only, not a determined attacker.
5. Sending a Monthly Export Safely
Say an HR app emails the monthly payroll CSV to an external accountant. The job builds the CSV in memory, encrypts it with AES-256 and attaches the zip, while the password reaches the accountant through a separate channel, such as a phone call or a password manager share. The password comes from configuration, never from source code, and the default value in the snippet exists only for local test runs.
static Path encryptExport(String fileName, byte[] content, char[] password, Path outDir) throws IOException {
Path zip = outDir.resolve(fileName + ".zip");
ZipParameters params = aesParams();
params.setFileNameInZip(fileName);
try (ZipFile zipFile = new ZipFile(zip.toFile(), password)) {
zipFile.addStream(new ByteArrayInputStream(content), params);
} finally {
Arrays.fill(password, '0');
}
return zip;
}
char[] password = Optional.ofNullable(System.getenv("EXPORT_ZIP_PASSWORD")).orElse("dev-only-pass").toCharArray();
byte[] payroll = "name,amount\nanna,4200\n".getBytes(StandardCharsets.UTF_8);
Path zip = encryptExport("payroll-2026-09.csv", payroll, password, Files.createTempDirectory("mail"));
boolean cleared = password[0] == '0'; // true
String attachment = zip.getFileName().toString(); // "payroll-2026-09.csv.zip"
The finally block clears the password array after the archive is written, so the secret does not stay in the heap longer than needed. A zip password protects the file in transit and at rest, and it is not a replacement for access control on the server that stores the original data.
6. Password Protected Zip FAQs
Questions about encrypted zip files focus on the limits of the JDK, opening the archive on the receiving side and the strength of the protection.
6.1. Can Java Create a Password-Protected Zip Without a Library?
No. The java.util.zip package has no API for encryption, and java.util.zip.ZipFile refuses to open archives with encrypted entries. Zip4j is the common choice, because Apache Commons Compress cannot encrypt or decrypt zip entries either.
6.2. Which Zip Tools Can Open an AES-Encrypted Zip?
7-Zip, WinZip and WinRAR open AES-encrypted zip files on Windows, and 7z does on Linux and macOS. The classic Windows Explorer zip support handles only ZipCrypto, so test the archive with the tool the receiver uses.
6.3. Does Zip4j Encrypt the File Names?
No. Zip encryption protects the content of each entry, while the names, sizes and dates of the entries stay readable to anyone who opens the archive. Put sensitive information in the content, not in file names, or zip an inner zip file.
6.4. Can I Add Files to an Existing Encrypted Zip?
Yes. Open the archive with new ZipFile(file, password) and call addFile() with encryption parameters. Each entry is encrypted separately, so new entries can even use a different method, although one method per archive is easier for the receiver.
7. Conclusion
Java needs a library for password-protected zip files, and Zip4j 2.x covers both sides. Set setEncryptFiles(true) and EncryptionMethod.AES on ZipParameters, pass the password as a char[] to ZipFile, and use addFile(), addFiles(), addFolder() or addStream() to write the entries.
On the reading side, extractAll() and extractFile() take the same password, and a ZipException of type WRONG_PASSWORD tells us when it does not match. Prefer AES over ZipCrypto, keep passwords out of source code and send them separately from the file. For unencrypted archives and other file work, start from the Java IO overview.
8. References
- Zip4j on GitHub
- Zip4j on Maven Central
- java.util.zip package (Java 25)
- WinZip AES Encryption Information
Happy Learning !!
This code allows to open the zip file and be able to see the list of files and password is protected for the files only inside the zip…how to put a password for the zip archive ??? (i.e) password should be prompted when a zip file is clicked to open.
Hi Lokesh,
Thanks for sharing useful example.
i have one requirement in my project like i need to send a mail with attached zipped password protected file.
i am using JavaMailSenderImpl & MimeMessageHelper to send a TXT, CSV & XML file in mail but now client requested to send in password protected zipped file.
i am trying to use your code but problem is MimeMessageHelper dose not allow to attach zipped file.
did lot of search but not able to come to the Solution.
could you please guide here if it possible ASAP.
Note :- i already have generated file in my application(File type) just need to zipped with password and send to mail.
Hi have u found the solution for this?
Is there a program to decode, thank you very much
I guess… no.
Hi,
Whether this can be supported in java1.4? Are we able to do this password protected in Java 1.4 version. Kindly share if any example is there
I have not tried with 1.4 – I have no plan to find and install 1.4 as of now. Please try and share with us.
Hi there,
Very good example with proper comments.
Can you please help me making a “Exiting Zip file” password protected?
Thanks in advance!!
Hi Lokesh,
Again very clean and simple example. zip4j has a overloaded setpassword() with char[] to avoid immutable property of string.
Regards,
Himansu
Good catch. Thanks for sharing.