【问题标题】:Calculate CRC32, MD5 and SHA1 of zip content without decompression in PythonPython中无需解压即可计算zip内容的CRC32、MD5和SHA1
【发布时间】:2017-10-21 14:43:00
【问题描述】:

我需要计算 zip 文件内容的 CRC32、MD5 和 SHA1,而不需要解压。

到目前为止,我发现了如何为 zip 文件本身计算这些,例如:

CRC32:

import zlib


zip_name = "test.zip"


def Crc32Hasher(file_path):

    buf_size = 65536
    crc32 = 0

    with open(file_path, 'rb') as f:
        while True:
            data = f.read(buf_size)
            if not data:
                break
            crc32 = zlib.crc32(data, crc32)

    return format(crc32 & 0xFFFFFFFF, '08x')


print(Crc32Hasher(zip_name))

SHA1:(类似MD5)

import hashlib


zip_name = "test.zip"


def Sha1Hasher(file_path):

    buf_size = 65536
    sha1 = hashlib.sha1()

    with open(file_path, 'rb') as f:
        while True:
            data = f.read(buf_size)
            if not data:
                break
            sha1.update(data)

    return format(sha1.hexdigest())


print(Sha1Hasher(zip_name))

对于zip文件的内容,我可以直接从zip中读取CRC32,无需计算如下:

读取 zip 内容的 CRC32:

import zipfile

zip_name = "test.zip"

if zip_name.lower().endswith(('.zip')):
    z = zipfile.ZipFile(zip_name, "r")

for info in z.infolist():

    print(info.filename,
          format(info.CRC & 0xFFFFFFFF, '08x'))

但我不知道如何在不先解压缩压缩文件的情况下计算 zip 文件内容的 SHA1(或 MD5)。 这有可能吗?

【问题讨论】:

    标签: python hash md5 sha1 crc32


    【解决方案1】:

    这是不可能的。您可以获得 CRC,因为它是在创建存档时为您仔细预先计算的(用于完整性检查)。任何其他校验和/哈希都必须从头开始计算,并且至少需要归档内容的流式传输,即解包。

    UPD:可能的实现

    libarchive:额外依赖,支持多种归档格式

    import libarchive.public as libarchive
    with libarchive.file_reader(fname) as archive:
        for entry in archive:
            md5 = hashlib.md5()
            for block in entry.get_blocks():
                md5.update(block)
            print(str(entry), md5.hexdigest())
    

    原生zipfile:无依赖,仅压缩

    import zipfile
    
    archive = zipfile.ZipFile(fname)
    blocksize = 1024**2  #1M chunks
    for fname in archive.namelist():
        entry = archive.open(fname)
        md5 = hashlib.md5()
        while True:
            block = entry.read(blocksize)
            if not block:
                break
            md5.update(block)
        print(fname, md5.hexdigest())
    

    【讨论】:

    • 感谢您的回答。什么是最节省内存的方法?
    猜你喜欢
    • 1970-01-01
    • 2011-07-31
    • 2016-04-04
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多