How to create a password protected zipfile using the zipfile module - python

I have a password protected zip-file called important.zip, it contains 1 folder, the password for the zip-file is 123, however when I use run this code with a wrong password the folder is still getting extracted, how can I make it that I can not extract the folder without the correct password?
import zipfile
zFile=zipfile.ZipFile("important.zip")
try:
zFile.extractall(pwd="oranges")
except Exception as e:
print e

The zipfile module checks for this as well as it can it returns a 'Bad password for file' when the password doesn't match.
But it does this on a per file basis. As each file in a ZIP file can have its own different password which was the password that was given when the file was added to the archive.
I think that your zip file was not password protected as zipfile accepts a password when extracting for files that aren't password protected. It does not report an error when the password is not used because the file was not password protected.
To avoid extracting a zip file that is not password protected when a password is provided one has check if the files are password protected:
import zipfile
def all_files_are_password_protected(zf):
return all(zinfo.flag_bits & 0x1 for zinfo in zf.infolist())
zFile=zipfile.ZipFile("important.zip")
try:
if all_files_are_password_protected(zFile):
zFile.extractall(pwd="oranges")
except Exception as e:
import traceback
traceback.print_exc()
Based on:
zf = zipfile.ZipFile(archive_name)
for zinfo in zf.infolist():
is_encrypted = zinfo.flag_bits & 0x1
if is_encrypted:
print '%s is encrypted!' % zinfo.filename
From How to check if a zip file is encrypted using python's standard library zipfile?
Note that every file has their own password so some files might fail to be extracted if encrypted with a different password.

Related

Python Zipfile compression method is not supported

The times when this worked were when I used ZIPCrypto compression. It's with AES-256 that it fails. How to get around this please?
I previously had success using the following Python code to open a password protected .zip file created with 7-Zip:
import zipfile
zip_file = zipfile.ZipFile('crack_me.zip')
output_verbose = 1 # increase that for long password list
with open('passwords.txt', 'rb') as password_list:
for index, line in enumerate(password_list):
try:
pwd = line.strip(b'\r\n')
zip_file.extractall(pwd=pwd)
except RuntimeError as e:
print(e)
if index % output_verbose == 0:
print('{}. The {} word not matched.'.format(index + 1, pwd))
else:
print('{}. Wow ! found the password: {}'.format(index + 1, pwd))
break
zip_file.close()
However, for no understandable reason, it has only worked a couple of times out of many attempts. Most times is gives "That compression method is not supported" for the exception.
I've tried deleting, renaming, re-creating the .zip file but no success. It makes no sense to me that it works occasionally.
I tried to simplify the issue as below:
import zipfile
zip_file = zipfile.ZipFile('crack_me.zip')
try:
zip_file.extractall(pwd=b"password")
print('Opened')
except RuntimeError as e:
print(e)
But I get the same exception. I've tried variations of pwd such as bytes("password", "utf-8) and others.
The provided password opens the .zip file when opening with 7-Zip.
What is going on here please?
Try using pyzipper. Here is a sample script:
import pyzipper
password = 'abc'
with pyzipper.AESZipFile('yourdocument.zip', 'r', compression=pyzipper.ZIP_DEFLATED, encryption=pyzipper.WZ_AES) as extracted_zip:
extracted_zip.extractall(pwd=str.encode(password))
In order for the zipfile library to work on a password protected zip you need to have ticked the "Zip legacy encryption" option when setting up the password.

Unable to unzip a .zip file with a password with python zipfile library

I created a zip file with Gnome Archive Manager (Ubuntu OS). I created the zip file with a password and I am trying to unzip it using the zipfile Python library:
import zipfile
file_name = '/home/mahmoud/Desktop/tester.zip'
pswd = 'pass'
with zipfile.ZipFile(file_name, 'r') as zf:
zf.printdir()
zf.extractall(path='/home/mahmoud/Desktop/testfolder', pwd = bytes(pswd, 'utf-8'))
When I run this code I get the following error and I am pretty sure that the password is correct. The error is:
File "/home/mahmoud/anaconda3/lib/python3.7/zipfile.py", line 1538, in open
raise RuntimeError("Bad password for file %r" % name)
RuntimeError: Bad password for file <ZipInfo filename='NegSkew.pdf' compress_type=99 filemode='-rw-rw-r--' external_attr=0x8020 file_size=233252 compress_size=199427>
How can I unzip the file?
zipfile library doesn't support AES encryption (compress_type=99) and only supports CRC-32 as mentioned in the _ZipDecrypter code (https://hg.python.org/cpython/file/a80c14ace927/Lib/zipfile.py#l508). _ZipDecrypter is called and used right before that particular RuntimeError is raised in ZipFile.open which can be traced from extractall.
You can use pyzipper library (https://github.com/danifus/pyzipper) instead of zipfile to unzip the file:
import pyzipper
file_name = '/home/mahmoud/Desktop/tester.zip'
pswd = 'pass'
with pyzipper.AESZipFile(file_name) as zf:
zf.extractall(path='/home/mahmoud/Desktop/testfolder', pwd = bytes(pswd, 'utf-8'))

Python ftplib error 426 when putting files on iSeries

Have a peculiar issue that I can't seem to fix on my own..
I'm attempting to FTP a list of files in a directory over to an iSeries IFS using Python's ftplib library.
Note, the files are in a single subdirectory down from the python script.
Below is an excerpt of the code that is giving me trouble:
from ftplib import FTP
import os
localpath = os.getcwd() + '/Files/'
def putFiles():
hostname = 'host.name.com'
username = 'myuser'
password = 'mypassword'
myftp = FTP(hostname)
myftp.login(username, password)
myftp.cwd('/STUFF/HERE/')
for file in os.listdir(localpath):
if file.endswith('.csv'):
try:
file = localpath + file
print 'Attempting to move ' + file
myftp.storbinary("STOR " + file, open(file, 'rb'))
except Exception as e:
print(e)
The specific error that I am getting throw is:
Attempting to move /home/doug/Files/FILE.csv
426-Unable to open or create file /home/doug/Files to receive data.
426 Data transfer ended.
What I've done so far to troubleshoot:
Initially I thought this was a permissions issue on the directory containing my files. I used chmod 777 /home/doug/Files and re-ran my script, but the same exception occured.
Next I assumed there was an issue between my machine and the iSeries. I validated that I could indeed put files by using ftp. I was successfully able to put the file on the iSeries IFS using the shell FTP.
Thanks!
Solution
from ftplib import FTP
import os
localpath = os.getcwd() + '/Files/'
def putFiles():
hostname = 'host.name.com'
username = 'myuser'
password = 'mypassword'
myftp = FTP(hostname)
myftp.login(username, password)
myftp.cwd('/STUFF/HERE/')
for csv in os.listdir(localpath):
if csv.endswith('.csv'):
try:
myftp.storbinary("STOR " + csv, open(localpath + csv, 'rb'))
except Exception as e:
print(e)
As written, your code is trying to execute the following FTP command:
STOR /home/doug/Files/FILE.csv
Meaning it is trying to create /home/doug/Files/FILE.csv on the IFS. Is this what you want? I suspect that it isn't, given that you bothered to change the remote directory to /STUFF/HERE/.
If you are trying to issue the command
STOR FILE.csv
then you have to be careful how you deal with the Python variable that you've named file. In general, it's not recommended that you reassign a variable that is the target of a for loop, precisely because this type of confusion can occur. Choose a different variable name for localpath + file, and use that in your open(..., 'rb').
Incidentally, it looks like you're using Python 2, since there is a bare print statement with no parentheses. I'm sure you're aware that Python 3 is recommended by now, but if you do stick to Python 2, it's recommended that you avoid using file as a variable name, because it actually means something in Python 2 (it's the name of a type; specifically, the return type of the open function).

Load credentials in python package

I'm developing a Python package to communicate with an API. In order not to hard code the username and password I would like to read the credentials from a JSON file loacated in a 'conf' directory. So if no username and pasword are given it tries to load the credentials from the file:
def __init__(self, user=None, pswd=None):
""" Illustrate method-level docstring."""
if pswd is None:
try:
with open('conf/credentials.json') as data_file:
data = json.load(data_file)
user = data['user']
pswd = data['password']
print('You will log in with user', user)
except IOError:
print("Could not read file: credentials.json. Please Instantiate object with your username and password")
This solution works fine when executing the code in the same directory, but once the package is installed the system doesn't find the file:
Could not read file: credentials.json. Please Instantiate object with
your username and password
How can I overcome this problem? Is it possible to refer to the installation path? I don't want to encrypt the password, I just want to have the credentials in a separate file and add the file in the .gitignore file to prevent sharing this information.
You may try using 'file' which stores filename (with absolute or relative path) and build your path based on this.
You may also store your secret data in other directory (outside of your codebase) like ~/. It may be even better to pass this filename as environmental variable (see os.environ) so users may point to the right file.

RarFile Python Module

I am trying to make a simple bruteforcer for rar files. My code is...
import rarfile
file = input("Password List Directory: ")
rarFile = input("Rar File: ")
passwordList = open(file,"r")
for i in passwordList:
try :
rarfile.read(rarFile, psw=i)
print('[+] Password Found: '+i)
except Exception as e:
print('[-] '+i+' is not a password ')
passwordList.close()
I think this has to do with my use of the module, because when I input a password list that I am 10000% sure contains the password to the rarFile, it prints the exception.
The real problem here is that you are catching all exceptions, not just the one you want. So use except rarfile.PasswordRequired: That will show you that the error is not a missing password. Instead there is no function read in the rarfile module.
Have a look at some Documentation. Rar encryption is per file, not per archive.
You need to create a object from the RarFile class and try the password on each file in the archive. (or just the first if you know that is encrypted)
import rarfile
file = input("Password List Directory: ")
rarFilename = input("Rar File: ")
rf = rarfile.RarFile(rarFilename)
passwordList = open(file,"r")
first_file = next(rf.infolist)
for i in passwordList:
password = i.rstrip()
try:
rf.open(first_file, psw=password)
print(password, "found")
except rarfile.PasswordRequired:
print(password,"is not a password")
When you open and read lines from a file, the "new line" character is kept
at the end of the line. This needs to be stripped from each line.
for i in passwordList:
password = i.rstrip()
try :
rarfile.read(rarFile, psw=password)
print('[+] Password Found: '+password)

Categories