Как применить xmodem CRC при генерации и проверке - PullRequest
0 голосов
/ 06 июля 2018

Я перебрал много статей - по какой-то причине я не смог найти ни одной, которая бы описывала простую процедуру: как объединить вычисленный CRC с исходным сообщением, чтобы вычисление CRC снова привело к 0 (= проверено как правильное)?Я нашел несколько примеров с «длинными» вычислениями (только 2- или 3-битные CRC), но ни один пример, в котором используется библиотечная функция, такая как [crcmod][1] (библиотека Python).

Вот простая программа, в которую я написалпроверьте это:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#

import crcmod

def test_cycle():
    test_str = b"123456789"
    orig_msg = test_str
    print("Original message: {:s}".format(orig_msg.hex()))

    #~ crc_calc = crcmod.predefined.Crc('xmodem')
    crc_calc = crcmod.Crc(
                0x11021,
                rev = False,
                initCrc = 0x0000,
                xorOut = 0x0000)

    crc_calc.update(orig_msg)
    print("CRC: {:04x}".format(crc_calc.crcValue))

    lo = crc_calc.crcValue & 0xff
    hi = crc_calc.crcValue >> 8
    new_msg = test_str + bytes((hi, lo))
    print("Crc appended: {:s}".format(new_msg.hex()))

    crc_calc.update(new_msg)
    print("CRC: {:04x}".format(crc_calc.crcValue))


def main(args):
    test_cycle()
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Есть несколько закомментированных строк из экспериментов с различным порядком байтов.Результаты программы:

Original message: 313233343536373839
CRC: 31c3
Crc appended: 31323334353637383931c3
CRC: 00ef

Первый CRC (31C3), кажется, проверяется в соответствии с ожидаемыми значениями для xmodem-CRC .Я пытался разными способами объединить полученный CRC с исходной строкой, но никогда не получал «0».Я что-то здесь упускаю?

Ответы [ 2 ]

0 голосов
/ 07 июля 2018

Немного предыстории для тех, кто придет к этому вопросу и задается вопросом о добавлении CRC.

Если CRC правильно , добавленный к сообщению о том, что он является CRC, и в сообщении или CRC нет ошибок, CRC всего этого будет константа зависит только от определения этого CRC.

К правильно добавить CRC требует осторожности в порядке следования битов. Для общего определения CRC, предоставленного crcmod, если rev ложно, то сначала должны быть добавлены биты наиболее значащие. Если rev истинно, то сначала необходимо добавить биты наименее значащие. Для байтово-ориентированных сообщений это, во-первых, означает, что ширина CRC должна быть кратна восьми битам (что, кстати, все, что разрешено crcmod), и что CRC добавляется в порядке с прямым порядком байтов или порядок с прямым порядком байтов соответственно.

Результирующая константа не всегда равна нулю, в зависимости от определения CRC. Это равно нулю, если значение xorOut для CRC равно нулю. В противном случае константа является CRC n нулевых битов, где n - ширина CRC, а начальное значение CRC равно нулю ( не initCrc). Например, для стандарта CRC-32 CRC-32 сообщения с его CRC-32, добавленным в порядке с прямым порядком байтов, всегда равен 0x2144df1c.

Для этого конкретного вопроса CRC добавляется в порядке с прямым порядком байтов, поэтому 31 c3, и CRC полученного сообщения + CRC тогда равен нулю.

0 голосов
/ 06 июля 2018

crc_calc.update(new_msg) добавляет все содержимое new_msg в CRC. Поскольку crc_calc уже содержит результат 313233343536373839, вы эффективно рассчитываете CRC 31323334353637383931323334353637383931c3, и это действительно 00ef.

Чтобы добавить в расчет только два байта, используйте

crc_calc.update(bytes((hi, lo)))

Либо используйте новый экземпляр crcmod.Crc() или сбросьте crcValue существующего экземпляра перед выполнением нового вычисления

crc_calc.crcValue = 0
crc_calc.update(new_msg)

Оба приведут к результату 0

...