How to create an encrypted ZIP file?
Asked Answered
C

9

46

I am creating an ZIP file with ZipFile in Python 2.5, it works OK so far:

import zipfile, os

locfile = "test.txt"
loczip = os.path.splitext (locfile)[0] + ".zip"
zip = zipfile.ZipFile (loczip, "w")
zip.write (locfile)
zip.close()

But I couldn't find how to encrypt the files in the ZIP file. I could use system and call PKZIP -s, but I suppose there must be a more "Pythonic" way. I'm looking for an open source solution.

Coronado answered 20/8, 2008 at 0:16 Comment(1)
open-source solution #2196247Salim
M
30

I created a simple library to create a password encrypted zip file in python. - here

import pyminizip

compression_level = 5 # 1-9
pyminizip.compress("src.txt", "dst.zip", "password", compression_level)

The library requires zlib.

I have checked that the file can be extracted in WINDOWS/MAC.

Multilingual answered 17/4, 2013 at 1:39 Comment(4)
It is available via pip install pyminizipCessation
Does not work with the following: Python 3.5 via Anaconda (Jupyter Notebook): produced a secure zip file but the password I used to create it does not open the folder! Son of a pup!Revolutionize
pyminizip is also available via pypi.Mercier
SECURITY: According to Snyk, security issues have been found relating to interger overflow, stemming from zlib. The project appears to be no longer maintained.Rout
T
10

This thread is a little bit old, but for people looking for an answer to this question in 2020/2021.

Look at pyzipper

A 100% API compatible replacement for Python’s zipfile that can read and write AES encrypted zip files.

7-zip is also a good choice, but if you do not want to use subprocess, go with pyzipper...

Tip answered 11/2, 2021 at 16:27 Comment(1)
Oh man, this is such a great solution. pyminizip is nice, but limited in that its API can only handle actual files on disk. In contrast, I really appreciate that pyzipper mimics the standard ZipFile API.Nanceenancey
C
9

The duplicate question: Code to create a password encrypted zip file? has an answer that recommends using 7z instead of zip. My experience bears this out.

Copy/pasting the answer by @jfs here too, for completeness:

To create encrypted zip archive (named 'myarchive.zip') using open-source 7-Zip utility:

rc = subprocess.call(['7z', 'a', '-mem=AES256', '-pP4$$W0rd', '-y', 'myarchive.zip'] + 
                     ['first_file.txt', 'second.file'])

To install 7-Zip, type:

$ sudo apt-get install p7zip-full

To unzip by hand (to demonstrate compatibility with zip utility), type:

$ unzip myarchive.zip

And enter P4$$W0rd at the prompt.

Or the same in Python 2.6+:

>>> zipfile.ZipFile('myarchive.zip').extractall(pwd='P4$$W0rd')
Certie answered 20/8, 2008 at 0:16 Comment(0)
M
5

pyminizip works great in creating a password protected zip file. For unziping ,it fails at some situations. Tested on python 3.7.3

Here, i used pyminizip for encrypting the file.

import pyminizip
compression_level = 5 # 1-9
pyminizip.compress("src.txt",'src', "dst.zip", "password", compression_level)

For unzip, I used zip file module:

from zipfile import ZipFile

with ZipFile('/home/paulsteven/dst.zip') as zf:
    zf.extractall(pwd=b'password')
Maple answered 8/8, 2019 at 4:47 Comment(1)
For me, on Windows10 with Python 3.10, installing pyminizip requires VC Build tools that is expected to download and install over 6GB (too much for me as i need it on several PCs!), see comments on this answer. When these installed, the library works well, though.Cyclopean
C
3

You can use pyzipper for this task and it will work great when you want to encrypt a zip file or generate a protected zip file.

pip install pyzipper

import pyzipper

def encrypt_():

    secret_password = b'your password'

    with pyzipper.AESZipFile('new_test.zip',
                             'w',
                             compression=pyzipper.ZIP_LZMA,
                             encryption=pyzipper.WZ_AES) as zf:
        zf.setpassword(secret_password)
        zf.writestr('test.txt', "What ever you do, don't tell anyone!")

    with pyzipper.AESZipFile('new_test.zip') as zf:
        zf.setpassword(secret_password)
        my_secrets = zf.read('test.txt')

The strength of the AES encryption can be configure to be 128, 192 or 256 bits. By default it is 256 bits. Use the setencryption() method to specify the encryption kwargs:

def encrypt_():
    
    secret_password = b'your password'

    with pyzipper.AESZipFile('new_test.zip',
                             'w',
                             compression=pyzipper.ZIP_LZMA) as zf:
        zf.setpassword(secret_password)
        zf.setencryption(pyzipper.WZ_AES, nbits=128)
        zf.writestr('test.txt', "What ever you do, don't tell anyone!")

    with pyzipper.AESZipFile('new_test.zip') as zf:
        zf.setpassword(secret_password)
        my_secrets = zf.read('test.txt')

Official Python ZipFile documentation is available here: https://docs.python.org/3/library/zipfile.html

Cleanser answered 17/12, 2021 at 6:57 Comment(0)
H
0

@tripleee's answer helped me, see my test below.

This code works for me on python 3.5.2 on Windows 8.1 ( 7z path added to system).

rc = subprocess.call(['7z', 'a', output_filename + '.zip', '-mx9', '-pSecret^)'] + [src_folder + '/'])

With two parameters:

  1. -mx9 means max compression
  2. -pSecret^) means password is Secret^). ^ is escape for ) for Windows OS, but when you unzip, it will need type in the ^.

Without ^ Windows OS will not apply the password when 7z.exe creating the zip file.

Also, if you want to use -mhe switch, you'll need the file format to be in 7z instead of zip.

I hope that may help.

Hamish answered 20/10, 2016 at 21:18 Comment(0)
T
0

2022 answer:

I believe this is an utterly mundane task and therefore should be oneliner. I abstracted away all the frevolous details in a library that is as powerfull as a bash terminal.

from crocodile.toolbox import Path

file = Path(r'my_string_path')
result_file = file.zip(pwd="lol", use_7z=True)
  • when the 7z flag is raised, it gets called behind the scenes.
    • You don't need to learn 7z command line syntax.
    • You don't need to worry about installing 7z, does that automatically if it's not installed. (tested on windows so far)
Therewith answered 24/6, 2022 at 13:40 Comment(0)
I
0

You can now use https://github.com/uktrade/stream-zip (full disclosure: made/maintained mostly by me) to make AES-256 encrypted ZIP files that adhere to WinZip's AE-2 spec.

A small bit of specific documentation is at https://stream-zip.docs.trade.gov.uk/advanced-usage/#password-protection-%2F-encryption, but to make a fully working example:

import secrets
from datetime import datetime
from stat import S_IFREG

from stream_zip import ZIP_32, stream_zip

member_files = (
    (
        'my-file-1.txt',     # File name
        datetime.now(),      # Modification time
        S_IFREG | 0o600,     # Mode - regular file that owner can read and write
        ZIP_32,              # ZIP_32 has good support but limited to 4GiB
        (b'Some bytes 1',),  # Iterable of chunks of contents
    ),
    (
        'my-file-2.txt',
        datetime.now(),
        S_IFREG | 0o600,
        ZIP_32,
        (b'Some bytes 2',),
    ),
)

# Should use a long and random password
password = secrets.token_urlsafe(32)
encrypted_zipped_chunks = stream_zip(member_files, password=password)

with open('password-protected-zip', 'wb') as f:
    for encrypted_zipped_chunk in encrypted_zipped_chunks:
        f.write(encrypted_zipped_chunk)

This example the source data is hard coded in memory, and then saves the ZIP disk, but this isn't required by stream-zip. The source data has to be an iterable of bytes, and then can be sent do any code that accepts an iterable of bytes instances.

Warning AE-2 is better than ZipCryto, but it has flaws and so isn't suitable for all cases. Very briefly:

  • Metadata (like file names) are not encrypted
  • If someone can intercept the ZIP and replace parts of it, this can go undetected and can itself lead to information leakage
  • The more files there are in the ZIP, then there is a higher risk of information leakage. But for AES-256 like in stream-zip, the risk is probably low enough to be acceptable for most use cases.

See “Attacking and Repairing the WinZip Encryption Scheme” by Tadayoshi Kohno for more details

Impotent answered 10/1 at 10:42 Comment(0)
D
-1

You can use the Chilkat library. It's commercial, but has a free evaluation and seems pretty nice.

Here's an example I got from here:

import chilkat

# Demonstrates how to create a WinZip-compatible 128-bit AES strong encrypted zip
zip = chilkat.CkZip()
zip.UnlockComponent("anything for 30-day trial")

zip.NewZip("strongEncrypted.zip")

# Set the Encryption property = 4, which indicates WinZip compatible AES encryption.
zip.put_Encryption(4)
# The key length can be 128, 192, or 256.
zip.put_EncryptKeyLength(128)
zip.SetPassword("secret")

zip.AppendFiles("exampleData/*",True)
zip.WriteZip()
Decoct answered 20/8, 2008 at 1:20 Comment(1)
I already saw the Chilkat examples, but I'm looking for an open source option (sorry didn't mention this in my original post) I keep looking in google, but without luck.Coronado

© 2022 - 2024 — McMap. All rights reserved.