0

I need to calculate the crc8 dvb s2 checksum in python but I can't find any useful information on how this checksum really works, so I tried to convert this working C code:

uint8_t crc8_dvb_s2(uint8_t crc, unsigned char a)

    {
        crc ^= a;
        for (int ii = 0; ii < 8; ++ii) {
            if (crc & 0x80) {
                crc = (crc << 1) ^ 0xD5;
            } else {
                crc = crc << 1;
            }
        }
        return crc;
    }

in python code:

import crc8
import operator 
def bxor(b1, b2): # use xor for bytes
    return bytes(map(operator.xor, b1, b2))
def blshift(b1, b2): # use shift left for bytes
    return (int.from_bytes( b1, byteorder='little') << int.from_bytes( b2, byteorder='little')).to_bytes(1, byteorder='little')
def _checksum(message): 
    #calculate crc
    crc = crc8.crc8()
    crc.update(message)
    crc_result = crc.digest()
    #calculate dvb
    crc_result = bxor(crc_result , message)
    for i in range(0, 7):
        if (crc_result == b'\x80') :
            crc_result = bxor((blshift(crc_result, b'\x01')) , b'\xD5')
        else:
            crc_result = blshift(crc_result, b'\x01')
    #-------------
    return crc_result;

But there is something wrong with it that I can't seem to understand. If I give the C function the bytes '\x00d\x00\x00\x00' it gives my as a result '\x8f' ( which is right), while the Python function gives me the OverflowError: int too big to convert.

There's clearly something wrong with my code that makes the numbers bigger and bigger but I wasn't able to figure out what exactly.

Full backtrace:

---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-226-8288eada1ce9> in <module>
----> 1 _checksum(b'\x00d\x00\x00\x00')

<ipython-input-225-2e5beaea293f> in _checksum(message)
     18             crc_result = bxor((blshift(crc_result, b'\x01')) , b'\xD5')
     19         else:
---> 20             crc_result = blshift(crc_result, b'\x01')
     21     #-------------
     22     return crc_result;

<ipython-input-225-2e5beaea293f> in blshift(b1, b2)
      6     return bytes(map(operator.and_, b1, b2))
      7 def blshift(b1, b2): # use shift left for bytes
----> 8     return (int.from_bytes( b1, byteorder='little') << int.from_bytes( b2, byteorder='little')).to_bytes(1, byteorder='little')
      9 def _checksum(message):
     10     #calculate crc

OverflowError: int too big to convert
  • Please show the full traceback of the error. Specifically, you have shown multiple Python functions, and didn't tell us *which one* gives this error message. – mkrieger1 Oct 25 '18 at 19:49

1 Answers1

1

The documentation of int.to_bytes says:

An OverflowError is raised if the integer is not representable with the given number of bytes.

It seems as if the number on which you use .to_bytes(1, byteorder='little') is larger than 255 (the highest number representable by one byte).

This:

int.from_bytes( b2, byteorder='little')).to_bytes(1, byteorder='little')

can only work if b2 is between 0 and 255, and I don't understand what would be the point of converting the same value from integer to bytes and back.

Do you intend to calculate the lowest 8 bits of the binary representation of b2? Then you should use b2 % 256.


You should be able to translate this C function almost literally to Python, without the need for helper functions like bxor or blshift:

def crc8_dvb_s2(crc, a):
    crc ^= a
    for _ in range(8):
        if crc & 0x80:
            crc = ((crc << 1) ^ 0xD5) % 256
        else:
            crc = (crc << 1) % 256
    return crc
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • Yes, That doesn't give an error but the output is not correct, I need a unit8 int not an unit16 int(just like the c code).I'm not just converting bytes to int and that back to bytes.I'm converting b1 and b2 to int, performing a left shift and than converting the result back to bytes. – Nicola Guerrera Oct 25 '18 at 20:40
  • Thank you very much!That almost works but there is a small problem: The crc value keeps getting bigger than 1 byte. This doesn't happen in C because the C xor function "cuts off" the end of the XORd value to fit in the char. – Nicola Guerrera Oct 26 '18 at 13:36
  • Ah, I missed that. Truncation to one byte happens by assigning to an `uint8_t` variable, not by using xor. You can emulate that in Python by using the modulo operator, as I suggested before. See updated answer. – mkrieger1 Oct 26 '18 at 14:45