首页 > 解决方案 > ZIP 用于加密的 CRC-32 并不完全是 zlib 的 crc32 ......为什么?

问题描述

我正在编写自己的解压缩代码,并且(通过反复试验,无法理解)看起来解密所需的一个字节上的 CRC-32 算法与 zlib 的不太匹配。要从一种转换为另一种:

def crc32(ch, crc):
   crc = zlib.crc32(bytes([~ch & 0xFF]), crc)
   return (~crc & 0xFF000000) + (crc & 0x00FFFFFF)

为什么是这样?(/ 我错了吗?)


编辑:我认为至少有可能我是对的,在https://github.com/uktrade/stream-unzip/blob/d23400028abbe3b0d7e1951cb562cd0541bfc960/stream_unzip.py#L89我使用上述成功解密加密的原因压缩文件

def decrypt(chunks):
    key_0 = 305419896
    key_1 = 591751049
    key_2 = 878082192

    def crc32(ch, crc):
        crc = zlib.crc32(bytes([~ch & 0xFF]), crc)
        return (~crc & 0xFF000000) + (crc & 0x00FFFFFF)

    def update_keys(byte):
        nonlocal key_0, key_1, key_2
        key_0 = crc32(byte, key_0)
        key_1 = (key_1 + (key_0 & 0xFF)) & 0xFFFFFFFF
        key_1 = ((key_1 * 134775813) + 1) & 0xFFFFFFFF
        key_2 = crc32(key_1 >> 24, key_2)

    def decrypt(chunk):
        chunk = bytearray(chunk)
        for i, byte in enumerate(chunk):
            temp = key_2 | 2
            byte ^= ((temp * (temp ^ 1)) >> 8) & 0xFF
            update_keys(byte)
            chunk[i] = byte
        return chunk

    yield_all, _, get_num, _ = get_byte_readers(chunks)

    for byte in password:
        update_keys(byte)

    if decrypt(get_num(12))[11] != mod_time >> 8:
        raise ValueError('Incorrect password')

    for chunk in yield_all():
        yield decrypt(chunk)

但是,如果我crc32只用调用 zlib 替换上面的函数,它不会(例如,它会抱怨密码不正确)

标签: pythonzipzlibdeflatecrc32

解决方案


好吧,你并没有完全错。它确实是相同的 CRC-32 算法,但没有预处理和后处理(反转 CRC 的输入和输出)。这是真正奇怪的代码,它试图用zlib.crc32函数来复制它。你只需要这样:

def crc32(ch, crc):
    return ~zlib.crc32(bytes([ch]), ~crc) & 0xffffffff

推荐阅读