Created
January 1, 2023 04:29
-
-
Save animetosho/942a96ab3299c98ee35663208e00737b to your computer and use it in GitHub Desktop.
CRC32 utility functions in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# compute a*b | |
CRC32_POLYNOMIAL = 0xedb88320 | |
def crc_multiply(a: int, b: int): | |
prod = 0 | |
while b != 0: | |
prod ^= -(b>>31) & a | |
a = (a>>1) ^ (CRC32_POLYNOMIAL & -(a&1)) | |
b = (b<<1) & 0xffffffff | |
return prod | |
CRC32_POWER_TABLE = [ # pre-computed 2**(2**n) | |
0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, 0xedb88320, 0xb1e6b092, 0xa06a2517, | |
0xed627dae, 0x88d14467, 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, 0x09fe548f, | |
0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, | |
0xbad90e37, 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, 0xc40ba6d0, 0xc4e22c3c | |
] | |
""" | |
# (or calculate at runtime) | |
k = 0x80000000 >> 1 | |
for i in range(0, 32): | |
CRC32_POWER_TABLE[i] = k | |
k = crc_multiply(k, k) | |
""" | |
# compute 2**n | |
def crc_2pow(n: int): | |
result = 0x80000000 | |
power = 0 | |
while n != 0: | |
if n&1 != 0: | |
result = crc_multiply(result, CRC32_POWER_TABLE[power]) | |
n >>= 1 | |
power = (power+1) & 31 | |
return result | |
# append `zeroes` null bytes to `crc` | |
def crc_zero_pad(crc: int, zeroes: int): | |
return crc_multiply(crc ^ 0xffffffff, crc_2pow(zeroes*8)) ^ 0xffffffff | |
# remove `zeroes` null bytes from end of crc | |
def crc_zero_unpad(crc: int, zeroes: int): | |
inverse = ((zeroes*8) % 0xffffffff) ^ 0xffffffff | |
return crc_multiply(crc ^ 0xffffffff, crc_2pow(inverse)) ^ 0xffffffff | |
# compute CRC(A + B) given CRC(A) and CRC(B) (and byte length of B) | |
def crc_concat(crc1: int, crc2: int, len2: int): | |
return crc_multiply(crc1, crc_2pow(len2*8)) ^ crc2 | |
### example ### | |
from zlib import crc32 | |
text1 = b"this is some text" | |
text2 = b"even more text" | |
crc1 = crc32(text1) | |
crc2 = crc32(text2) | |
print("Test concat: " + str( crc32(text1 + text2) == crc_concat(crc1, crc2, len(text2)) )) | |
print("Test zero pad: " + str( crc32(text1 + (b'\0' * 123)) == crc_zero_pad(crc1, 123) )) | |
print("Test zero unpad: " + str( crc1 == crc_zero_unpad(crc32(text1 + (b'\0' * 123)), 123) )) | |
print("Test zero un+pad: " + str( crc1 == crc_zero_unpad(crc_zero_pad(crc1, 0x300000000), 0x300000000) )) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment