custom crc32 calculation in python without libs

0

I have been looking for a simple python code which can generate a crc32-sum. It is for a stm32 and i dont find a good example which is adjustable.

To get the right settings for my calculation i used following side.

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

The settings would be the following:

Polynomial: 0x4C11DB7, Initial Value: 0xFFFFFFFF and no Xor Value or 0x00, also the Input and result are not reflected.

Does someone know where i could get a simple adjustable algorithm or where i can learn how to write one?

Edit: I use this function to create the table

def create_table():
    a = []
    for i in range(256):
        k = i
        for j in range(8):
            if k & 1:
                k ^= 0x4C11DB7
            k >>= 1
        a.append(k)
    return a

and the following for generating the crc-sum

def crc32(bytestream):
    crc_table = create_table()


    crc32 = 0xffffffff

    for byte in range( int(len(bytestream)) ):
        lookup_index = (crc32 ^ byte) & 0xff
        crc32 = (crc32 >> 8) ^ crc_table[lookup_index]

    return crc32

and call the function with this

print(hex(crc32(b"1205")))

the result is: 0x9f8e7b8c

but the website gives me: 0xA7D10A0A

can someone help me?

python
python-3.x
stm32
crc32
asked on Stack Overflow Sep 2, 2020 by tryanderror • edited Sep 2, 2020 by tryanderror

1 Answer

1

First off, what you have is for a reflected CRC, not a non-reflected CRC. Though there is an error in your table construction. This:

if k & 1:
    k ^= 0x4C11DB7
k >>= 1

is wrong. The exclusive-or must be done after the shift. So it would need to be (for the reflected case):

k = (k >> 1) ^ 0xedb88320 if k & 1 else k >> 1

Note that the polynomial also needs to be reflected in this case.

Another error in your code is using range to make the integers 0, 1, ..., and using those instead of the actual data bytes to compute the CRC on! What you want for your for loop is simply:

for byte in bytestream:

The whole point of using a table is to make the CRC calculation faster. You don't want to regenerate the table every time you do a CRC. You want to generate the table once when your program starts, and then use it multiple times. Or you can generate the table separately from your program, and then put the table itself in your program. That's what's usually done.

Anyway, to do the non-reflected case, you need to flip things around. So to make the table:

def create_table():
    a = []
    for i in range(256):
        k = i << 24;
        for _ in range(8):
            k = (k << 1) ^ 0x4c11db7 if k & 0x80000000 else k << 1
        a.append(k & 0xffffffff)
    return a

To use the table:

def crc32(bytestream):
    crc_table = create_table()
    crc = 0xffffffff
    for byte in bytestream:
        lookup_index = ((crc >> 24) ^ byte) & 0xff
        crc = ((crc & 0xffffff) << 8) ^ crc_table[lookup_index]
    return crc

Now it correctly implements your specification, which happens to be the MPEG-2 32-bit CRC specification (from Greg Cook's CRC catalogue):

width=32 poly=0x04c11db7 init=0xffffffff refin=false refout=false xorout=0x00000000 check=0x0376e6e7 residue=0x00000000 name="CRC-32/MPEG-2"

For the code above, if I do:

print(hex(crc32(b'123456789')))

I get 0x376e6e7, which matches the check value in the catalog.

Again, you need to take the create_table() out of the crc32() routine and do it somewhere else, once.

answered on Stack Overflow Sep 2, 2020 by Mark Adler • edited Sep 3, 2020 by Mark Adler

User contributions licensed under CC BY-SA 3.0