繁体   English   中英

Python 3 zipfile 添加文件到加密 zip

[英]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添加带有密码的文件。 此外,如果你想先“验证”输入的密码,你可以这样做,但你必须知道文件的内容,因为解密会很高兴地用任何密码解密任何文件,明文结果将不是正确的。

您必须解决的问题:

  • 比较文件内容以验证密码
  • zip 文件中已存在文件时的处理
  • 处理 zipfile 已经存在和不存在时的处理。
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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM