Вычисление CRC16 в Python

Я пытаюсь оценить соответствующую контрольную сумму на основе алгоритма CRC-16, используя crcmod Модуль Python и интерпретатор Python версии 2.7. Параметры контрольной суммы:

  • Порядок CRC: 16
  • Полином CRC: 0x8005
  • Исходное значение: 0xFFFF
  • Окончательное значение: 0x0000
  • Прямой: Правда

Код:

crc16 = crcmod.mkCrcFun(0x18005, rev=False, initCrc=0xFFFF, xorOut=0x0000)
print hex(crc16(str(int(0x5A0001))))

и для ввода 0x5A0001 он печатает 0x7E16, а я должен получить что-то вроде 0xCE0A.

Я проверил на http://www.lokker.net/Java/crc/CRCcalculation2.htm и вычисленное значение равно 0xACE, что является правильным (относительно порядка).


person Qrlet    schedule 04.02.2016    source источник
comment
Похоже, у вас есть 0x18005 в качестве полинома в коде Python, но вы указали 0x8005 в параметрах контрольной суммы выше.   -  person djhoese    schedule 04.02.2016
comment
Нет, 0x18005 правильно для crcmod. Этот пакет определяет количество битов в CRC из полного полинома. Обычно полином CRC предоставляется без старшего члена, например. 0x8005 и отдельно указать, что это 16-битная CRC.   -  person Mark Adler    schedule 05.02.2016
comment
Сначала вы создали c16, а затем попытались использовать crc16. Вы имели в виду c16? Во-вторых, как вы думаете, для чего вы вычисляете CRC? Вы знаете, что str(int(0x5A0001)) возвращает строку цифр ASCII 5898241, да? Что вы ввели в веб-калькулятор CRC?   -  person Mark Adler    schedule 05.02.2016
comment
Да, это была опечатка. Ввод в калькулятор был %5A%00%01 с соответствующими параметрами.   -  person Qrlet    schedule 05.02.2016
comment
Учтите также binascii.crc_hqx(data, 0): документы здесь   -  person hoc_age    schedule 24.10.2019


Ответы (4)


crcmod работает нормально. Вы не даете ему три байта, которые, как вы думаете, вы даете. Ваш str(int(0x5A0001)) предоставляет семь байтов, которые представляют собой символы ASCII 5898241 — преобразование 0x5a0001 в десятичное число.

Чтобы передать ему байты 0x5a 0x00 0x01, вы бы вместо этого (как один из подходов):

print hex(crc16("5a0001".decode("hex")))

Это печатает 0xace.

person Mark Adler    schedule 05.02.2016
comment
Спасибо, Марк! Теперь CRC рассчитывается правильно. Можно ли выразить эти 3 отдельных байта: 0x5a 0x00 0x01 как одно целое число, или я что-то упустил? - person Qrlet; 07.02.2016
comment
Конечно, вы можете написать что-нибудь, чтобы извлечь эти три байта из целого числа 0x5a0001, например. (x >> 16) & 0xff, (x >> 8) & 0xff и x & 0xff. Но зачем тебе это? - person Mark Adler; 07.02.2016
comment
Я думал, как разделить 0x5a0001 на эти 3 байта, не используя .decode(str). Другими словами, как я могу, например, вычислить контрольную сумму для 0x5a00 и 0x01? - person Qrlet; 09.02.2016
comment
Сначала вам нужно знать, как решить, сколько байтов использовать из каждого целого числа. Это 0x5a00 или 0x005a00 или 0x00005a00? Нет смысла спрашивать, что такое CRC 0x5a00, поскольку CRC применяется к последовательности байтов (или битов), а не к целым числам. - person Mark Adler; 09.02.2016

Вот реализация CRC-16/CCITT-FALSE на Python.

def crc16(data : bytearray, offset , length):
    if data is None or offset < 0 or offset > len(data)- 1 and offset+length > len(data):
        return 0
    crc = 0xFFFF
    for i in range(0, length):
        crc ^= data[offset + i] << 8
        for j in range(0,8):
            if (crc & 0x8000) > 0:
                crc =(crc << 1) ^ 0x1021
            else:
                crc = crc << 1
    return crc & 0xFFFF
  • data : bytearray данных, для которых вы хотите рассчитать CRC
  • offset : с какого смещения вы хотите начать вычисление CRC
  • length : до какого смещения вы хотите вычислить CRC
person Amin Saidani    schedule 25.04.2019

Пример работающей отдельной функции для CRC-16-ANSI, CRC-16-IBM на основе кода pycrc.

Его легко изменить, но возможность отражения ввода или вывода не включена:

def crc16(data: bytes):
    xor_in = 0x0000  # initial value
    xor_out = 0x0000  # final XOR value
    poly = 0x8005  # generator polinom (normal form)

    reg = xor_in
    for octet in data:
        # reflect in
        for i in range(8):
            topbit = reg & 0x8000
            if octet & (0x80 >> i):
                topbit ^= 0x8000
            reg <<= 1
            if topbit:
                reg ^= poly
        reg &= 0xFFFF
        # reflect out
    return reg ^ xor_out

person Sz'    schedule 09.03.2020

person    schedule
comment
Код не работает + можете добавить краткое описание? - person RtmY; 01.05.2019