Skip to content

Instantly share code, notes, and snippets.

@animetosho
Created January 1, 2023 04:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save animetosho/942a96ab3299c98ee35663208e00737b to your computer and use it in GitHub Desktop.
Save animetosho/942a96ab3299c98ee35663208e00737b to your computer and use it in GitHub Desktop.
CRC32 utility functions in Python
# 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