【问题标题】:CRC32 In Python (vs CRC32b)Python 中的 CRC32(对比 CRC32b)
【发布时间】:2018-11-23 08:13:41
【问题描述】:

我正在尝试生成一些 crc32 哈希,但似乎 zlibbinascii 使用 crc32b 算法,即使它们各自的函数只是 zlib.crc32binascii.crc32。我可以尝试其他用于哈希生成的 python 资源吗?有趣的是,我之前发现 R 的“digest”包也实现了 crc32b,但没有提及 crc32。

我所说的 CRC32 和 CRC32b 的一些例子:

您可以在下拉列表中看到这两者:http://www.md5calc.com/crc32

这里CRC32b在右边:https://hash.online-convert.com/crc32-generator

这是一个以 php 为中心的关于 distition 的讨论:What is the difference between crc32 and crc32b?

这里我们可以看到python正在实现CRC32b:How to calculate CRC32 with Python to match online results?

谢谢

【问题讨论】:

  • 您在哪里找到称为“crc32a”和“crc32b”的 CRC?我在pretty complete menagerie of CRCs 中没有看到这些名称的任何 CRC。 zlib 的 CRC-32 总是简称为 CRC-32。没有“a”或“b”。
  • 不确定通知在这里是如何工作的,但我用这些细节编辑了我的问题

标签: python-3.x zlib binascii


【解决方案1】:

他们所说的“crc32”是 CRC-32/BZIP2 in this catalog。他们所说的“crc32b”是 PKZip CRC-32 (ITU V.42),通常简称为 CRC-32,因为它在该目录中。 “crc32”和“crc32b”的这种用法显然是 PHP 作者发明的符号。

您可以在PHP documentation page for hash() 上找到一组示例哈希。在那里计算字符串“hello”的哈希值,并且可以根据实现进行检查。我链接的目录使用“123456789”进行检查。

您可以自己轻松计算 BZIP2 CRC。以下是一些 C 代码作为示例:

uint32_t crc32bzip2(uint32_t crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    crc = ~crc;
    while (len--) {
        crc ^= (unsigned)(*data++) << 24;
        for (unsigned k = 0; k < 8; k++)
            crc = crc & 0x80000000 ? (crc << 1) ^ 0x4c11db7 : crc << 1;
    }
    crc = ~crc;
    return crc;
}

如果你用NULL 作为数据指针调用它,它将返回CRC 的初始值,在这种情况下为零。然后你可以用当前的 CRC 和要更新 CRC 的字节调用它,它会返回结果 CRC。

从标准输入计算字节的 CRC-32/BZIP2 的 Python 版本:

#!/usr/local/bin/python3
import sys
a = bytearray(sys.stdin.buffer.read())
crc = 0xffffffff
for x in a:
    crc ^= x << 24;
    for k in range(8):
        crc = (crc << 1) ^ 0x04c11db7 if crc & 0x80000000 else crc << 1
crc = ~crc
crc &= 0xffffffff
print(hex(crc))

crcany 将根据需要生成更高效的基于表的版本(C 语言)。

【讨论】:

  • 基本上我正在使用一个库存系统,该系统使用 PHP 生成“crc32”(正如 PHP 所指的那样)散列,一旦特定项目在数据库中被清点。散列然后变成条形码并用于标记项目。目前,我想为我知道人类可读 ID 的项目抢先生成哈希(人类可读的 ID 对于条形码来说太长了),但由于 reasons 尚未清点。我的 PHP 知识有限,所以我希望使用 python 让我跳过盘点步骤并直接从人类可读的 ID 生成我的哈希条形码
  • 我很确定 md5calc 正在使用您发送 reveng.sourceforge.net/crc-catalogue/all.htm 的页面上的算法 CRC-32/BZIP2。别名之一是 CRC-32/AAL5
  • 是的,我查过了,它是 BZIP2 CRC。
  • 请注意,¨PHP crc32 输出是反向字节顺序 (source)。这是一个基于 @mark-adler 答案的 Python 实现,它反转了输出字节顺序:chezsoi.org/shaarli/?U7admg
【解决方案2】:

我对 Mark Adler 的回答做了一些改进,将数据拆分为分区后快了 20 倍以上,但我不知道为什么。

#!/usr/local/bin/python3
import random
import timeit

def crc32_bzip2(data, precrc=None, bs=None):
    def crc32_bzip2_block(data, precrc=None):
        crc = 0xFFFFFFFF if precrc is None else (precrc ^ 0xFFFFFFFF)
        for x in data:
            crc ^= x << 24
            for k in range(8):
                if crc & 0x80000000:
                    crc = (crc << 1) ^ 0x04C11DB7
                else:
                    crc = crc << 1
        crc = ~crc
        crc &= 0xFFFFFFFF
        return crc

    crc = None
    bs = bs if bs else len(data)
    blocks = [data[i:i+bs] for i in range(0, len(data), bs)]
    for b in blocks:
        crc = crc32_bzip2_block(b, crc)
    return crc


# testing
bs = 512
datasize = 1024 * 50
data = bytearray(random.getrandbits(8) for _ in range(datasize))

number = 1
setup = 'from __main__ import crc32_bzip2, data, bs'
a = timeit.timeit('crc32_bzip2(data)', setup=setup, number=number)
b = timeit.timeit('crc32_bzip2(data, bs=bs)', setup=setup, number=number)

print(f'{a:.3}', f'{b:.3}', f'{a/b:.3}', sep='\t')
# 3.66  0.127   28.8, on the environment:
#    Intel i5-6300U CPU notebook
#    Python 3.6.6 64bit
#    Windows 7 SP1 64bit

【讨论】:

  • 基于表格的版本会更快。
猜你喜欢
  • 1970-01-01
  • 2019-07-09
  • 2015-03-18
  • 1970-01-01
  • 2020-12-21
  • 2017-05-24
  • 1970-01-01
  • 2020-03-27
  • 2020-04-03
相关资源
最近更新 更多