zipfile:将文件添加到加密的 zip
zipfile: Adding files to encrypted zip
我有一个加密的 ZIP 文件,出于某种原因,我输入的任何密码似乎都无关紧要,因为它无论如何都可以将文件添加到存档中。我检查了任何被忽略的异常或任何东西,但似乎没有什么是相当明显的。
我在下面发布了极简代码:
import zipfile
z = zipfile.ZipFile('test.zip', 'a') #Set zipfile object
zipPass = str(input("Please enter the zip password: "))
zipPass = bytes(zipPass, encoding='utf-8')
z.setpassword(zipPass) #Set password
z.write("test.txt")
我不确定我在这里遗漏了什么,但我在 zipfile 中寻找任何可以处理加密的 zipfile 并使用密码将文件添加到其中的东西,因为我唯一拥有的是``z.setpassword()` 函数在这里似乎不起作用。
TL;DR:z.write()
不会抛出异常,z.setpassword()
或任何 zipfile
相关的东西在输入不正确的密码时也不会抛出异常,并且无论如何都愿意添加文件。我期待得到 BadPasswordForFile
.
有什么办法吗?
我在 zipfile
的文档中发现,该库只支持 解密 密码。它不能加密。所以你将无法添加带密码的文件。
It supports decryption of encrypted files in ZIP archives, but it currently cannot create an encrypted file.
https://docs.python.org/3/library/zipfile.html
编辑:此外,查看 python 错误 Issue 34546: Add encryption support to zipfile 似乎为了不使 zip 中使用的弱密码方案永久存在,他们选择不包含它。
您可以使用 subprocess
添加带密码的文件。
此外,如果你想先“验证”输入的密码,你可以这样做,但你必须知道文件的内容,因为解密会愉快地用任何密码解密任何文件,明文结果将不是正确。
您必须解决的问题:
- 比较文件内容以验证密码
- 压缩文件中已存在文件时的处理
- 压缩文件已经存在和不存在时的处理。
import subprocess
import zipfile
def zip_file(zipFilename, filename):
zipPass = str(input("Please enter the zip password: "))
zipPass = bytes(zipPass, encoding='utf-8')
#If there is a file that we know the plain-text (or original binary)
#TODO: handle fipFilename not existing.
validPass=False
with zipfile.ZipFile(zipFilename, 'r') as zFile:
zFile.setpassword(zipPass)
with zFile.open('known.txt') as knownFile:
#TODO: compare contents of known.txt with actual
validPass=True
#Next to add file with password cannot use zipfile because password not supported
# Note this is a linux only solution, os dependency will need to be checked
#if compare was ok, then valid password?
if not validPass:
print('Invalid Password')
else:
#TODO: handle zipfile not-exist and existing may have to pass
# different flags.
#TODO: handle filename existing in zipFilename
#WARNING the linux manual page for 'zip' states -P is UNSECURE.
res = subprocess.run(['zip', '-e', '-P', zipPass, zipFilename, filename])
#TODO: Check res for success or failure.
编辑:
我研究了用 -P
修复整个“暴露密码”的问题。不幸的是,这很重要。您不能简单地将 zipPass
写入带有 input=
的 subprocess.run
的标准输入。我认为 pexpect
之类的东西可能是解决此问题的方法,但我还没有花时间来完成这项工作。有关如何使用 pexpect
完成此操作的示例,请参见此处:Use subprocess to send a password_
在所有可爱的回复之后,我确实找到了一个解决方法,以防万一有人需要答案!
我首先重试了 z.testzip()
,它确实捕获了错误的密码,但在看到它不可靠之后(显然哈希冲突允许错误密码以某种方式匹配小哈希),我决定使用密码,提取它在存档中看到的第一个文件,然后再提取它。如果有效,请删除提取的文件,如果无效,则没有任何危害。
代码如下:
try:
z = zipfile.ZipFile(fileName, 'a') #Set zipfile object
zipPass = bytes(zipPass, encoding='utf-8') #Str to Bytes
z.setpassword(zipPass) #Set password
filesInArray = z.namelist() #Get all files
testfile = filesInArray[0] #First archive in list
z.extract(testfile, pwd=zipPass) #Extract first file
os.remove(testfile) #remove file if successfully extracted
except Exception as e:
print("Exception occurred: ",repr(e))
return None #Return to mainGUI - this exits the function without further processing
谢谢大家的评论和回答!
我有一个加密的 ZIP 文件,出于某种原因,我输入的任何密码似乎都无关紧要,因为它无论如何都可以将文件添加到存档中。我检查了任何被忽略的异常或任何东西,但似乎没有什么是相当明显的。
我在下面发布了极简代码:
import zipfile
z = zipfile.ZipFile('test.zip', 'a') #Set zipfile object
zipPass = str(input("Please enter the zip password: "))
zipPass = bytes(zipPass, encoding='utf-8')
z.setpassword(zipPass) #Set password
z.write("test.txt")
我不确定我在这里遗漏了什么,但我在 zipfile 中寻找任何可以处理加密的 zipfile 并使用密码将文件添加到其中的东西,因为我唯一拥有的是``z.setpassword()` 函数在这里似乎不起作用。
TL;DR:z.write()
不会抛出异常,z.setpassword()
或任何 zipfile
相关的东西在输入不正确的密码时也不会抛出异常,并且无论如何都愿意添加文件。我期待得到 BadPasswordForFile
.
有什么办法吗?
我在 zipfile
的文档中发现,该库只支持 解密 密码。它不能加密。所以你将无法添加带密码的文件。
It supports decryption of encrypted files in ZIP archives, but it currently cannot create an encrypted file. https://docs.python.org/3/library/zipfile.html
编辑:此外,查看 python 错误 Issue 34546: Add encryption support to zipfile 似乎为了不使 zip 中使用的弱密码方案永久存在,他们选择不包含它。
您可以使用 subprocess
添加带密码的文件。
此外,如果你想先“验证”输入的密码,你可以这样做,但你必须知道文件的内容,因为解密会愉快地用任何密码解密任何文件,明文结果将不是正确。
您必须解决的问题:
- 比较文件内容以验证密码
- 压缩文件中已存在文件时的处理
- 压缩文件已经存在和不存在时的处理。
import subprocess
import zipfile
def zip_file(zipFilename, filename):
zipPass = str(input("Please enter the zip password: "))
zipPass = bytes(zipPass, encoding='utf-8')
#If there is a file that we know the plain-text (or original binary)
#TODO: handle fipFilename not existing.
validPass=False
with zipfile.ZipFile(zipFilename, 'r') as zFile:
zFile.setpassword(zipPass)
with zFile.open('known.txt') as knownFile:
#TODO: compare contents of known.txt with actual
validPass=True
#Next to add file with password cannot use zipfile because password not supported
# Note this is a linux only solution, os dependency will need to be checked
#if compare was ok, then valid password?
if not validPass:
print('Invalid Password')
else:
#TODO: handle zipfile not-exist and existing may have to pass
# different flags.
#TODO: handle filename existing in zipFilename
#WARNING the linux manual page for 'zip' states -P is UNSECURE.
res = subprocess.run(['zip', '-e', '-P', zipPass, zipFilename, filename])
#TODO: Check res for success or failure.
编辑:
我研究了用 -P
修复整个“暴露密码”的问题。不幸的是,这很重要。您不能简单地将 zipPass
写入带有 input=
的 subprocess.run
的标准输入。我认为 pexpect
之类的东西可能是解决此问题的方法,但我还没有花时间来完成这项工作。有关如何使用 pexpect
完成此操作的示例,请参见此处:Use subprocess to send a password_
在所有可爱的回复之后,我确实找到了一个解决方法,以防万一有人需要答案!
我首先重试了 z.testzip()
,它确实捕获了错误的密码,但在看到它不可靠之后(显然哈希冲突允许错误密码以某种方式匹配小哈希),我决定使用密码,提取它在存档中看到的第一个文件,然后再提取它。如果有效,请删除提取的文件,如果无效,则没有任何危害。
代码如下:
try:
z = zipfile.ZipFile(fileName, 'a') #Set zipfile object
zipPass = bytes(zipPass, encoding='utf-8') #Str to Bytes
z.setpassword(zipPass) #Set password
filesInArray = z.namelist() #Get all files
testfile = filesInArray[0] #First archive in list
z.extract(testfile, pwd=zipPass) #Extract first file
os.remove(testfile) #remove file if successfully extracted
except Exception as e:
print("Exception occurred: ",repr(e))
return None #Return to mainGUI - this exits the function without further processing
谢谢大家的评论和回答!