modulus_polynomial = 0x01
init_val = 0x0
final_xor = 0x0
def crc32(message):
reg_val = init_val
for byte in message:
for i in range(8):
reg_top_bit = reg_val & (1 << 31)
reg_val ^= reg_top_bit
reg_val <<=1
if reg_top_bit:
reg_val ^= modulus_polynomial
reg_val ^= byte
return reg_val ^ final_xor
def attach_crc32(message):
crc = crc32(message + bytes(4))
return message + crc.to_bytes(4, "big")
def run_crc_tests(polynomial, rule1_enabled, rule2_enabled):
global modulus_polynomial, init_val, final_xor
print(f"==== RUNNING TEST [Polynomial = {hex(polynomial)}, Rule 1 = {rule1_enabled}, Rule 2 = {rule2_enabled}] =====")
modulus_polynomial = polynomial
init_val = 0xFFFFFFFF if rule1_enabled else 0x0
final_xor = 0xFFFFFFFF if rule2_enabled else 0x0
message = b"Hello!!!"
print(f"CRC of Message: {hex(crc32(message))}")
message = attach_crc32(message)
print(f"CRC of Message after appending CRC (should be 0 now): {hex(crc32(message))}")
print(f"CRC of Message with Prepended null bytes: {hex(crc32(bytes(3) + message))}")
print(f"CRC of Message with Appended null bytes: {hex(crc32(message + bytes(3)))}")
print(f"CRC of Message with Prepended and Appended null bytes: {hex(crc32(bytes(3) + message + bytes(3)))}")
print("")
print("* Showing off the polynomial that handles all null bytes")
run_crc_tests(0x1, True, True) # (x + 1)^32, or equivalently x^32 + 1
print("* Now showing off polynomials that only handles prepending bytes")
run_crc_tests(0x10000, True, True) # (x + 1)^16 * x^16
run_crc_tests(0xFFFFFFFE, True, True) # (x + 1)^31 * x
run_crc_tests(0x80018000, True, True) # (x + 1)^17 * x^15
print("* Now showing off some random polynomial, and what happens if we change rules")
run_crc_tests(0x4CABDEA1, True, True)
run_crc_tests(0x4CABDEA1, False, True)
run_crc_tests(0x4CABDEA1, True, False)
run_crc_tests(0x4CABDEA1, False, False)