[英]Python 3 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()
function 似乎不在这里工作。
TL;DR:z.write() 不会抛出异常,当输入不正确的密码时 z.setpassword() 或任何与 zipfile 相关的东西也不会抛出异常,并且无论如何都愿意添加文件。 我期待得到 BadPasswordForFile?
有没有办法做到这一点?
谢谢。
我在zipfile
的文档中发现该库仅支持使用密码进行解密。 它不能加密。 因此,您将无法使用密码添加文件。
支持解密ZIP档案中的加密文件,但目前无法创建加密文件。 https://docs.python.org/3/library/zipfile.html
编辑:此外,查看 python 错误问题 34546:向 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
修复整个“暴露密码”问题。 不幸的是,这不是微不足道的。 您不能简单地使用input=
将subprocess.run
写入zipPass
的标准输入。 我认为像pexpect
这样的东西可能是一个解决方案,但我没有花时间来完成这项工作。 有关如何使用pexpect
完成此操作的示例,请参见此处: 使用子进程发送密码_
在所有可爱的回复之后,我确实找到了解决方法,以防万一有人需要答案!
我确实首先重试了z.testzip()
并且它确实捕获了错误的密码,但是在看到它不可靠之后(显然 hash 冲突允许错误的密码以某种方式匹配一个小哈希),我决定使用密码,提取它在存档中看到的第一个文件,然后提取它。 如果有效,请删除提取的文件,如果无效,则不会造成任何伤害。
代码工作如下:
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
谢谢大家的评论和回答!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.