计算CRC初始值,而不是将CRC附加到有效载荷 [英] Calculating CRC initial value instead of appending the CRC to payload

查看:537
本文介绍了计算CRC初始值,而不是将CRC附加到有效载荷的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实现的大多数CRC是附加计算出的CRC值到消息中(有效负载),并在包括所有字节在内的接收器处检查零结果。 CRC值通过CRC寄存器馈入。
显然,这是一种非常标准的方法。



现在,我想使用另一种方法:


  1. 从有效负载中计算出一个值。

  2. 将该值用作CRC寄存器之前
    的初始值消息字节(有效负载)通过CRC寄存器
    进行馈送,这样,在馈入有效负载
    的最后一个字节之后的结果将为零。

执行此操作的最佳方法是什么?
有一个好主意或一些指向何处进行更深入研究的指针吗?



ps:为什么我要这样做?在某些应用程序(ROM)中,由于数据存储在ROM地址空间的末尾,因此我无法追加数据。因此,我想预加载CRC寄存器或将该值添加到消息中。

解决方案

我现在已经编写了一个解决上述问题的方法比我最初想象的要容易。



我找到了几篇有关如何伪造CRC的文章。这意味着如何通过修补数据的方式使计算出的CRC值具有预定义的
值。



使用这种方法,我只需要使用最后一个字节

最后,我只需要使用有效载荷数据来计算反向 CRC。
此计算的结果是
计算CRC时必须使用的初始值。



由于我正在处理非常内存受限的系统中,我将256个条目(CRC32为1024字节)的CRC表的
大小减小为16个条目(64字节),将
分为两个步骤,现在

  // Castagnoli多项式(0x1EDC6F41)的反向CRC表
静态const无符号long crc32c_revTable [16] =
{
0x00000000L,0x05EC76F1L,0x0BD8EDE2L,0x0E349B13L,
0x17B1DBC4L,0x125DAD35L,0x1C693626L,0x198540D7L,$ b21C6L,$ b21C6L,$ b21C6L b 0x38D26C4CL,0x3D3E1ABDL,0x330A81AEL,0x36E6F75FL
};

无符号长calcReverseCRC32C(无符号长crc32c,
const无符号char * pData,
无符号长len)
{
而(len--)
{
crc32c =(crc32c<< 4)^ crc32c_revTable [crc32c>> 28];
crc32c =(crc32c<< 4)^ crc32c_revTable [crc32c>> 28];
crc32c ^ = * pData--;
}

return crc32c;
}

用法:

  {
//此数组包含带有4个字节CRC的测试数据
//使用此数据进行CRC-32C计算的结果为零
无符号char arr [] = {'1','2','3','4','5','6','7','8','9',
0x7c,0x6d, 0xf9,0x1c};

无符号长ExpectedResultOfCRC = 0;
unsigned long init = calcReverseCRC32C(expectedResultOfCRC,
& arr [sizeof(arr)-1],
sizeof(arr));
}


Most of the CRCs I've implemented were appending the calculated CRC value to the message (payload) and checking for a zero result at the receiver after all bytes incl. CRC value were fed through the CRC register. Obviously this is a quite standard approach.

Now I would like to use a different approach:

  1. Calculate a value from the payload.
  2. Use that value as initial value for the CRC register before the message bytes (payload) are fed through the CRC register such that the result after the last byte of the payload was fed through will be zero.

What is the best approach to do this? Does one have a good idea or some pointers where to dig deeper?

ps: Why I want to do this? In some applications (ROM) I cannot append data as the data is stored at the end of address space of a ROM. So I'd like to either preload the CRC register or prepend the value to the message.

解决方案

I've now programmed a solution for the above mentioned problem which was easier than I initially thought it would be.

I found several articles about how one can forge a CRC. That means how to patch data that way that the calculated CRC value will have a predefined value.

Using such an approach I simply had to use the last bytes of my actual payload as CRC value which is quite obvious.

Finally I only needed to calculate the "reverse" CRC using my payload data. The result of this calculation is the initial value I have to use when calculating the CRC.

As I'm working on a very memory constrained system I reduced the size of the CRC table with 256 entries (1024 bytes for CRC32) down to 16 entries (64 bytes) and now process each byte in two steps now which still is much faster than shifting the bits.

// 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;
}

Usage:

{
    // 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) );
}

这篇关于计算CRC初始值,而不是将CRC附加到有效载荷的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆