Skip to main content
🇪🇸 Español 🇧🇷 Português 🇩🇪 Deutsch
Image Converter Video Converter Audio Converter Document Converter
Tools Guides Formats Pricing API
Log In
Guide

Password-Protected ZIP with Python: pyzipper and AES-256

PC By Pablo Cirre

Related conversions

Put what you just learned into practice — convert your files now in seconds, free and without registration.

Frequently Asked Questions

The standard library zipfile only implements the legacy ZipCrypto algorithm and only on the read side — there is no API to write encrypted entries. The Python core team has explicitly declined to add ZipCrypto-write support because the algorithm is broken (vulnerable to known-plaintext attacks) and shipping it would imply endorsement. For encrypted ZIPs you must use a third-party library: pyzipper for AES-256 (most common), or chilkat for commercial environments needing strong support guarantees.

The AES-256 algorithm itself is identical — same mathematical strength. The difference is what gets protected. Full-disk encryption (BitLocker, LUKS, FileVault) protects everything including filenames, timestamps and free space. AES-256 ZIP encrypts file contents but leaves the central directory readable: an attacker can see filenames, sizes and timestamps inside the archive without the password. For sensitive metadata, encrypt the entire archive a second time with a tool that hides filenames (7z with the -mhe flag does this, age does it for tarballs).

No — macOS Archive Utility (the built-in unarchiver) does not support AES-256 ZIPs. The recipient needs a third-party tool: Keka (free, recommended), BetterZip, or The Unarchiver (also free). Windows 10/11 Explorer handles them natively since 2017. Linux unzip does not — use 7z (apt install p7zip-full) or pyzipper itself. If the recipient is on macOS by default, consider sending 7z instead, which Keka and others handle without configuration.

Use the standard library getpass module: <code>import getpass; password = getpass.getpass("Archive password: ").encode()</code>. This reads from stdin without displaying the input. For automated pipelines, read from environment variables (<code>os.environ["ZIP_PASSWORD"]</code>) or secrets managers (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager). Never hardcode passwords in source — git history is forever.

For text-heavy content (source code, JSON, CSV, logs) ZIP_LZMA gives 30-50% better compression than ZIP_DEFLATED at the cost of slower encoding. For mixed content default to ZIP_DEFLATED — it is universally supported and fast. For already-compressed files (JPG, MP4, MP3, PDF) use ZIP_STORED to skip compression entirely; trying to compress them just wastes CPU and can actually grow the file slightly. Encryption strength is independent of compression — AES-256 protects whatever you compress.

Read just one small file or use testzip(): <code>with pyzipper.AESZipFile(path) as zf: zf.setpassword(pw); zf.testzip()</code>. testzip() validates the CRC of every entry and returns None if all match (correct password) or the name of the first bad file (wrong password or corrupted entry). For very large archives this can be slow — alternative is to read just the smallest entry and catch RuntimeError. Note: a structurally valid AES ZIP with truly random data and a wrong password may not raise an error immediately — testzip() is the only reliable check.

We use cookies and similar technologies to personalise content and ads, and to analyse traffic. Learn more about cookies.