ZipFile:检查密码是否正确

ZipFile: Check for correct Password

我有这个代码来解压一个用密码加密的 zip 文件:

import zipfile

def main(pswd):
    file_name = 'somefile.zip'
    with zipfile.ZipFile(file_name) as file:
       return file.extractall(pwd = bytes(pswd, 'utf-8'))
print(main("password"))

它有效,但我希望如果我给该函数一个正确的密码,它会提取它并 returns 例如“True”,或者使用错误的密码 returns “False” .我怎样才能改进我的代码?

extractall 函数在密码错误时引发 RuntimeError,因此您可以执行以下操作

def main(pswd):
    file_name = "somefile.zip"
    with zipfile.ZipFile(file_name) as file:
        try:
            file.extractall(pwd=bytes(pswd, "utf-8"))
            return True
        except RuntimeError:
            return False

TL;DR: 如果您想解压缩,请实施适当的异常处理。要仅测试密码,请使用 ZipFile.testzip() 和预设的默认密码。

改进意见

如果密码不正确,我会重新考虑 return 布尔值的决定。

布尔错误注意事项-returns

通常从一个方法中 return 布尔值只有一个原因:

  • 如果该方法应该测试 某些东西,例如谓词函数 hasError()isValid(input)。更多和进一步阅读在最后。

要么做要么失败

您需要一个布尔值作为 return 值,以便您可以对失败做出反应。 设计中可能存在逻辑缺陷。当我们调用该方法时,我们将其传递给它期望它成功,例如通过给定的密码解锁 zip 文件并解压缩。

但是,如果它失败了,我们希望对异常做出反应。这是通过异常处理完成的。

zipfile 的异常处理

在 Python 文档中:zipfile — Work with ZIP archives there are many reasons to raise exceptions during extract() or extractall(), e.g. ValueError or RuntimeError. One of the causes of those exceptions is bad password, see Decompression Pitfalls:

Decompression may fail due to incorrect password / CRC checksum / ZIP format or unsupported compression method / decryption.

您可以在 Python.

中使用 try-except 块在错误处理期间捕获这些错误
import zipfile

def is_correct(pswd): # renamed from `main`
    file_name = 'somefile.zip'
    with zipfile.ZipFile(file_name) as file:
        try:
            file.extractall(pwd = bytes(pswd, 'utf-8'))
            return True  # correct password, decrypted and extracted successfully
        except RuntimeError as e:
            if e.args[0].startswith('Bad password for file'):
                return False  # incorrect password
            raise e  # TODO: properly handle exceptions?


print(is_correct("password"))

正在测试密码 - 无需提取

Stack Exchange 网站 Code Reviewpython - Zipfile password recovery program 的回答建议:

Use Zipfile.setpassword() with ZipFile.testzip() to check password.

首先使用 .setpassword(pwd) 设置一个 默认密码 以用于此 zip 文件。 然后方法 .testzip() 测试它是否可以打开和读取 zip 文件 - 使用之前设置的 默认密码 :

Read all the files in the archive and check their CRC’s and file headers. Return the name of the first bad file, or else return None.

同样,引发异常或 return 非 None 的原因不仅仅是 密码错误 .

在这里,错误的密码也会引发RuntimeError,因此我们需要再次进行异常处理:

import zipfile

def is_correct(pswd):
    file_name = 'somefile.zip'
    pwd = bytes(pswd, 'utf-8')
    zip = zipfile.ZipFile(file_name)
    zip.setpassword(pwd)
    try:
        bad_file = zip.testzip() # if anything returned without error then password was correct
        return True  # ignore if bad file was found (integrity violated)
    except RuntimeError as e:
        if e.args[0].startswith('Bad password for file'):
            return False
        raise e  # throw any other exception to print on console 


passwords = ["password", "pass"]
for p in passwords:
   print(f"'{p}' is correct?",is_correct(p))

打印:

'password' is correct? False

'pass' is correct? True

另见

使用 ZipFile 和密码:

从干净代码的角度来看布尔值: