Вычисление начального значения CRC вместо добавления CRC к полезной нагрузке

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

Теперь я хотел бы использовать другой подход:

  1. Рассчитайте значение из полезной нагрузки.
  2. Используйте это значение в качестве начального значения для регистра CRC до байтов сообщения (полезной нагрузки), пропущенных через регистр CRC, так что результат после того, как последний байт полезной нагрузки был пропущен, будет равен нулю.

Как лучше всего это сделать? Есть ли у кого-то хорошая идея или какие-то указания, куда копать глубже?

ps: Почему я хочу это сделать? В некоторых приложениях (ПЗУ) я не могу добавлять данные, поскольку данные хранятся в конце адресного пространства ПЗУ. Поэтому я хотел бы либо предварительно загрузить регистр CRC, либо добавить значение к сообщению.


person fhw72    schedule 25.02.2015    source источник


Ответы (1)


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

Я нашел несколько статей о том, как можно подделать CRC. Это означает, как исправлять данные таким образом, чтобы вычисленное значение CRC имело предопределенное значение.

Используя такой подход, мне просто пришлось использовать последние байты моей фактической полезной нагрузки в качестве значения CRC, что довольно очевидно.

Наконец, мне нужно было только вычислить "обратную" CRC, используя мои данные полезной нагрузки. Результатом этого вычисления является начальное значение, которое я должен использовать при вычислении CRC.

Поскольку я работаю над системой с очень ограниченным объемом памяти, я уменьшил размер таблицы CRC с 256 записей (1024 байта для CRC32) до 16 записей (64 байта) и теперь обрабатываю каждый байт в два этапа, что по-прежнему намного быстрее чем сдвиг бит.

// Reverse CRC table for Castagnoli polynomial (0x1EDC6F41)
static const unsigned long crc32c_revTable[16] =
{
    0x00000000L, 0x05EC76F1L, 0x0BD8EDE2L, 0x0E349B13L,
    0x17B1DBC4L, 0x125DAD35L, 0x1C693626L, 0x198540D7L,
    0x2F63B788L, 0x2A8FC179L, 0x24BB5A6AL, 0x21572C9BL,
    0x38D26C4CL, 0x3D3E1ABDL, 0x330A81AEL, 0x36E6F75FL
};

unsigned long calcReverseCRC32C(unsigned long crc32c, 
                                const unsigned char* pData,
                                unsigned long len)
{
    while (len--)
    {
        crc32c = (crc32c << 4) ^ crc32c_revTable[crc32c >> 28];
        crc32c = (crc32c << 4) ^ crc32c_revTable[crc32c >> 28];
        crc32c ^= *pData--;
    }

    return crc32c;
}

Использование:

{
    // This array contains test data with 4 bytes CRC appended
    // The result of CRC-32C calculation using this data is zero
    unsigned char arr[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9',
                           0x7c, 0x6d, 0xf9, 0x1c};

    unsigned long expectedResultOfCRC = 0;
    unsigned long init = calcReverseCRC32C(expectedResultOfCRC,
                                           &arr[sizeof(arr) -1],
                                           sizeof(arr) );
}
person fhw72    schedule 27.02.2015