在Python中使用zlib crc32_组合
我试图使用Python中的在Python中使用zlib crc32_组合,python,ctypes,zlib,crc32,Python,Ctypes,Zlib,Crc32,我试图使用Python中的crc32\u combine函数。 尽管还有其他各种zlib功能可用, 这不是“含电池”标准库的一部分。 我尝试了两种方法:从C代码到Python的端口和 使用ctypes从Python调用zlib。两者都给了我不同的结果, 虽然不是我期望的结果。 我之所以介绍ctypes代码,是因为我认为它执行得更快,并且具有更好的性能 发生额外程序员错误的可能性较小 该算法可以在 提供第二散列的数据。定义如下: crc32(crc32(0, seq1, len1), seq2,
crc32\u combine
函数。
尽管还有其他各种zlib功能可用,
这不是“含电池”标准库的一部分。
我尝试了两种方法:从C代码到Python的端口和
使用ctypes从Python调用zlib。两者都给了我不同的结果,
虽然不是我期望的结果。
我之所以介绍ctypes代码,是因为我认为它执行得更快,并且具有更好的性能
发生额外程序员错误的可能性较小
该算法可以在
提供第二散列的数据。定义如下:
crc32(crc32(0, seq1, len1), seq2, len2) == crc32_combine(
crc32(0, seq1, len1), crc32(0, seq2, len2), len2)
这是输出:
Expected CRC: 45E57586
Combined CRC: 567EE4E4
在win32上使用Python 3.5.1运行时,第二行总是不同的。不是用Python2,但是结果也不是我所期望的。将脚本放在与脚本相同的目录中以进行尝试
import zlib
def crc32_combine_ctypes(crc1, crc2, len2):
import ctypes
from ctypes import util
lib = util.find_library('zlib1')
_zlib = ctypes.CDLL(lib)
assert _zlib._name, "Can't find zlib"
_zlib.crc32_combine.argtypes = [
ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
_zlib.crc32_combine.restype = ctypes.c_ulong
return _zlib.crc32_combine(crc1, crc2, len2)
testfile = "zlib1.dll"
with open(testfile, "rb") as tf:
data = tf.read()
print("Expected CRC: %0.8X" % (zlib.crc32(data) & 0xFFFFFFFF))
cut = len(data) // 2 - 100
p1 = data[0:cut]
p2 = data[cut:]
crc1 = zlib.crc32(p1)
crc2 = zlib.crc32(p2)
len1 = len(p1)
len2 = len(p2)
combined = crc32_combine_ctypes(crc1, crc2, len2)
print("Combined CRC: %0.8X" % (combined & 0xFFFFFFFF))
我做错了什么?有一个正确的想法:我使用了一个坏的旧DLL。
最后一个带有32位dll的zlib版本包括:
我的纯Python代码端口比使用ctypes调用库慢几百倍。(使用带有1k迭代和50m作为长度参数的timeit的数字)
纯Python代码:
def crc32_combine(crc1, crc2, len2):
"""Explanation algorithm: https://stackoverflow.com/a/23126768/654160
crc32(crc32(0, seq1, len1), seq2, len2) == crc32_combine(
crc32(0, seq1, len1), crc32(0, seq2, len2), len2)"""
# degenerate case (also disallow negative lengths)
if len2 <= 0:
return crc1
# put operator for one zero bit in odd
# CRC-32 polynomial, 1, 2, 4, 8, ..., 1073741824
odd = [0xedb88320] + [1 << i for i in range(0, 31)]
even = [0] * 32
def matrix_times(matrix, vector):
number_sum = 0
matrix_index = 0
while vector != 0:
if vector & 1:
number_sum ^= matrix[matrix_index]
vector = vector >> 1 & 0x7FFFFFFF
matrix_index += 1
return number_sum
# put operator for two zero bits in even - gf2_matrix_square(even, odd)
even[:] = [matrix_times(odd, odd[n]) for n in range(0, 32)]
# put operator for four zero bits in odd
odd[:] = [matrix_times(even, even[n]) for n in range(0, 32)]
# apply len2 zeros to crc1 (first square will put the operator for one
# zero byte, eight zero bits, in even)
while len2 != 0:
# apply zeros operator for this bit of len2
even[:] = [matrix_times(odd, odd[n]) for n in range(0, 32)]
if len2 & 1:
crc1 = matrix_times(even, crc1)
len2 >>= 1
# if no more bits set, then done
if len2 == 0:
break
# another iteration of the loop with odd and even swapped
odd[:] = [matrix_times(even, even[n]) for n in range(0, 32)]
if len2 & 1:
crc1 = matrix_times(odd, crc1)
len2 >>= 1
# if no more bits set, then done
# return combined crc
crc1 ^= crc2
return crc1
def crc32联合收割机(crc1、crc2、len2):
解释算法:https://stackoverflow.com/a/23126768/654160
crc32(crc32(0,序列1,len1),序列2,len2)=crc32\u(
crc32(0,序号1,第1组),crc32(0,序号2,第2组),第2组“
#退化情况(也不允许负长度)
如果len2 1和0x7FFFFFFF
矩阵_指数+=1
返回数和
#偶数-gf2_矩阵_平方中两个零位的put运算符(偶数、奇数)
偶数[:]=[范围(0,32)内n的矩阵_次(奇数,奇数[n])]
#奇数中四个零位的put运算符
奇数[:]=[范围(0,32)内n的矩阵_次(偶数,偶数[n])]
#对crc1应用len2零(第一个正方形将使运算符为1
#零字节,八个零位,偶数)
而len2!=0:
#对len2的此位应用零运算符
偶数[:]=[范围(0,32)内n的矩阵_次(奇数,奇数[n])]
如果len2和Len1:
crc1=矩阵_次(偶数,crc1)
len2>>=1
#如果未设置更多位,则完成
如果len2==0:
打破
#循环的另一次迭代,奇偶交换
奇数[:]=[范围(0,32)内n的矩阵_次(偶数,偶数[n])]
如果len2和Len1:
crc1=矩阵的_次(奇数,crc1)
len2>>=1
#如果未设置更多位,则完成
#返回组合crc
crc1^=crc2
返回crc1
这个32位的zlib1.dll版本有问题。在我自己的64位构建(仅此函数)中,组合结果与预期结果匹配。为了构建DLL,我从你的链接下载,从crc32.c复制了
crc32\u combine
、gf2\u matrix\u times
、和gf2\u matrix\u square
的定义,并将其构建为64位DLL。这也按预期工作。坏的DLL就是问题所在!不知何故,我没有看到zlib主页上的其他链接,而是挑了一个不好的:)来计算CRC,(简单的CRC计算)这就足够了吗CRC^=0x741B8CD7
我的意思是显示简单CRC计算的伪代码
def crc32_combine(crc1, crc2, len2):
"""Explanation algorithm: https://stackoverflow.com/a/23126768/654160
crc32(crc32(0, seq1, len1), seq2, len2) == crc32_combine(
crc32(0, seq1, len1), crc32(0, seq2, len2), len2)"""
# degenerate case (also disallow negative lengths)
if len2 <= 0:
return crc1
# put operator for one zero bit in odd
# CRC-32 polynomial, 1, 2, 4, 8, ..., 1073741824
odd = [0xedb88320] + [1 << i for i in range(0, 31)]
even = [0] * 32
def matrix_times(matrix, vector):
number_sum = 0
matrix_index = 0
while vector != 0:
if vector & 1:
number_sum ^= matrix[matrix_index]
vector = vector >> 1 & 0x7FFFFFFF
matrix_index += 1
return number_sum
# put operator for two zero bits in even - gf2_matrix_square(even, odd)
even[:] = [matrix_times(odd, odd[n]) for n in range(0, 32)]
# put operator for four zero bits in odd
odd[:] = [matrix_times(even, even[n]) for n in range(0, 32)]
# apply len2 zeros to crc1 (first square will put the operator for one
# zero byte, eight zero bits, in even)
while len2 != 0:
# apply zeros operator for this bit of len2
even[:] = [matrix_times(odd, odd[n]) for n in range(0, 32)]
if len2 & 1:
crc1 = matrix_times(even, crc1)
len2 >>= 1
# if no more bits set, then done
if len2 == 0:
break
# another iteration of the loop with odd and even swapped
odd[:] = [matrix_times(even, even[n]) for n in range(0, 32)]
if len2 & 1:
crc1 = matrix_times(odd, crc1)
len2 >>= 1
# if no more bits set, then done
# return combined crc
crc1 ^= crc2
return crc1