Skip to content

Instantly share code, notes, and snippets.

@8051Enthusiast
Last active May 9, 2024 08:09
Show Gist options
  • Save 8051Enthusiast/80c044b3a6f6ad145617eebe11eb9fb1 to your computer and use it in GitHub Desktop.
Save 8051Enthusiast/80c044b3a6f6ad145617eebe11eb9fb1 to your computer and use it in GitHub Desktop.
# matrix from the `a^i` generator basis to the `a^(-2^i)` normal basis
to_normal = [0x7f50f7fd, 0x95ecaead, 0x495ffebe, 0x90618596, 0x6e0d0395, 0x527b6ec5, 0x563d1cac, 0x1ee02779,
0x287efd13, 0x5a66f53c, 0xdf3df773, 0xa0d25f82, 0x79357a5b, 0xe5c59050, 0x15508e51, 0x498da844,
0xcaf65756, 0x4830c2cb, 0xa93db762, 0x8f7013bc, 0x2d337a9e, 0x50692fc1, 0x72e2c828, 0x24c6d422,
0xa4186165, 0x47b809de, 0xa83497e0, 0x12636a11, 0x23dc04ef, 0x8931b508, 0x4498da84, 0xffffffff]
# inverse of to_normal
from_normal = [0xdb710641, 0x6d930ac3, 0x6d3d2d4d, 0x6567cb95, 0xd7125358, 0x5b358fd3, 0x2e9bb40b, 0x12a59a49,
0x8df9403d, 0x5139de12, 0xba340226, 0x29c45641, 0x12fbc105, 0xecd30c55, 0x3755ebd8, 0x24ee460c,
0x23783fcf, 0x479933fc, 0xa39442a5, 0x9ea0056d, 0xf42608f6, 0x20cacf04, 0x2a0cf83d, 0xeffd8645,
0x2a39a67d, 0x640ebd82, 0x9dfd8792, 0x277402ab, 0xad31bc4f, 0x31536354, 0x5ea35fca, 0x52b55e39]
# multiplication by a in the normal basis
shift = [0xffffffff, 0x00000001, 0x94397e07, 0xa61f509a, 0xa5e6fdbb, 0xcebff8ed, 0x8c596f2f, 0x22e9c80d,
0xbbab17bd, 0xef34b18b, 0x3fb74ec0, 0x33fa9bbf, 0xf4770a92, 0x6ecfe923, 0x9506c497, 0x0b497ad5,
0xa68938da, 0x9a9596e9, 0xa144fe2c, 0x75e642f6, 0xdbf0bde6, 0xb4206bbb, 0x8976cdf0, 0x9aab05a2,
0x90c19016, 0xb8cfff29, 0x755d666f, 0xebfa87bf, 0x6caf6575, 0xb4830c2c, 0xc8f7013b, 0x224c6d42]
# applies matrix bitwise to n
def apply(matrix, n):
ret = 0
for i in range(32):
if n & (1 << i):
ret ^= matrix[i]
return ret
def shift_bytes(sum, count):
# crc32 has a blocksize of 2^32 - 1, and we multiply by 8 to get the bit count
count = (count * 8) % 0xFFFFFFFF
ret = apply(to_normal, sum)
# basically exponentiation by squaring
for i in range(32):
if count & (1 << i):
ret = apply(shift, ret)
ret = (ret >> 1) | (ret << 31)
return apply(from_normal, ret)
# takes a zlib checksum and a count of bytes, and returns the checksum
# of the data with the given number of `0xff` bytes appended.
# example usage: `append_crc32_ff(zlib.crc32(b'hello'), 3)` will return the
# checksum of `b'hello\xff\xff\xff'`
def append_crc32_ff(sum, count):
# corresponds to 1 / (a + 1)
offset = 0x492f023f
return shift_bytes(sum ^ offset, count) ^ offset
# matrix from the `a^i` generator basis to the `a^(-2^i)` normal basis
from_normal = [0x82608edb, 0xc350c9b6, 0xb2b4bcb6, 0xa9d3e6a6, 0x1aca48eb, 0xcbf1acda, 0xd02dd974, 0x9259a548,
0xbc029fb1, 0x487b9c8a, 0x64402c5d, 0x826a2394, 0xa083df48, 0xaa30cb37, 0x1bd7aaec, 0x30627724,
0xf3fc1ec4, 0x3fcc99e2, 0xa54229c5, 0xb6a00579, 0x6f10642f, 0x20f35304, 0xbc1f3054, 0xa261bff7,
0xbe659c54, 0x41bd7026, 0x49e1bfb9, 0xd5402ee4, 0xf23d8cb5, 0x2ac6ca8c, 0x53fac57a, 0x9c7aad4a]
# inverse of from_normal
to_normal = [0xffffffff, 0x4498da84, 0x8931b508, 0x23dc04ef, 0x12636a11, 0xa83497e0, 0x47b809de, 0xa4186165,
0x24c6d422, 0x72e2c828, 0x50692fc1, 0x2d337a9e, 0x8f7013bc, 0xa93db762, 0x4830c2cb, 0xcaf65756,
0x498da844, 0x15508e51, 0xe5c59050, 0x79357a5b, 0xa0d25f82, 0xdf3df773, 0x5a66f53c, 0x287efd13,
0x1ee02779, 0x563d1cac, 0x527b6ec5, 0x6e0d0395, 0x90618596, 0x495ffebe, 0x95ecaead, 0x7f50f7fd]
# multiplication by a in the normal basis
shift = [0xffffffff, 0x00000001, 0x94397e07, 0xa61f509a, 0xa5e6fdbb, 0xcebff8ed, 0x8c596f2f, 0x22e9c80d,
0xbbab17bd, 0xef34b18b, 0x3fb74ec0, 0x33fa9bbf, 0xf4770a92, 0x6ecfe923, 0x9506c497, 0x0b497ad5,
0xa68938da, 0x9a9596e9, 0xa144fe2c, 0x75e642f6, 0xdbf0bde6, 0xb4206bbb, 0x8976cdf0, 0x9aab05a2,
0x90c19016, 0xb8cfff29, 0x755d666f, 0xebfa87bf, 0x6caf6575, 0xb4830c2c, 0xc8f7013b, 0x224c6d42]
# applies matrix bitwise to n
def apply(matrix, n):
ret = 0
for i in range(32):
if n & (1 << i):
ret ^= matrix[i]
return ret
def shift_bytes(sum, count):
# crc32 has a blocksize of 2^32 - 1, and we multiply by 8 to get the bit count
count = (count * 8) % 0xFFFFFFFF
ret = apply(to_normal, sum)
# basically exponentiation by squaring
for i in range(32):
if count & (1 << i):
ret = apply(shift, ret)
ret = (ret >> 1) | (ret << 31)
return apply(from_normal, ret)
# takes a reflected crc32 and a count of bytes, and returns the checksum
# of the data with the given number of `0xff` bytes appended
def append_crc32_ff(sum, count):
# corresponds to crc([0xff]) / (a^8 + 1)
offset = 0xfc40f492
return shift_bytes(sum ^ offset, count) ^ offset
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment