请教crc查表法原理计算CRC的原理

 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
crc8校验查表法 实现方法
下载积分:787
内容提示:crc8校验查表法 实现方法!
文档格式:DOC|
浏览次数:595|
上传日期: 00:35:31|
文档星级:
该用户还上传了这些文档
crc8校验查表法 实现方法
官方公共微信算法(11)
CRC是在通讯领域广泛采用的校验算法。原理我就不说了,这里说一下简单的实现。以下均采用CRC多项式为0x1021即:
g(x) = x16+x12+x5+x0;CRC的基本原理就不说了,那个搜一下就有了。
&&& && 最基本的算法应该是按位计算了,这个方法可以适用于所有长度的数据校验,最为灵活,但由于是按位计算,其效率并不是最优,只适用于对速度不敏感的场合。基本的算法如下:
unsigned short do_crc_16(unsigned char *message, unsigned int len)
&&& int i,
&&& unsigned short crc_reg = 0;
&&& for (i = 0; i & i++)
&&&&&&& current = message[i] && 8;
&&&&&&& for (j = 0; j & 8; j++)
&&&&&&&&&&& if ((short)(crc_reg ^ current) & 0)
&&&&&&&&&&&&&&& crc_reg = (crc_reg && 1) ^ 0x1021;
&&&&&&&&&&& else
&&&&&&&&&&&&&&& crc_reg &&= 1;
&&&&&&&&&&& current &&= 1;&&&&&&&&&&&
&&& return crc_
以是方法可以计算出任意长度数据的校验。但速度慢。下面介绍一种按字节计算的方法:
按字节校验是每次计算8位数据,多是基于查表的算法,首先要准备一个表,一共256项。
unsigned int crc_ta[256]={&&&&&&&&&&&&&& /* CRC余式表 */
&&& 0x1, 0x3, 0xa5, 0x60c6, 0x70e7,
&&& 0x9, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
&&& 0x0, 0x2, 0x52b5, 0xf7, 0x62d6,
&&& 0x8, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
&&& 0x3, 0x1, 0x64e6, 0x74c7, 0x44a4, 0x5485,
&&& 0xa56a, 0xb54b, 0x9, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
&&& 0x2, 0x0, 0x76d7, 0x66f6, 0xb4,
&&& 0xb75b, 0xa77a, 0x8, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
&&& 0x48c4, 0x58e5, 0xa7, 0x1, 0x3,
&&& 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x9, 0xa90a, 0xb92b,
&&& 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
&&& 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
&&& 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
&&& 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
&&& 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
&&& 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
&&& 0xa9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
&&& 0xa1, 0x30c2, 0x20e3, 0x5, 0x7,
&&& 0x83b9, 0xfb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
&&& 0x02b1, 0xf3, 0x32d2, 0x4, 0x6,
&&& 0xb5ea, 0xa5cb, 0x95a8, 0xe, 0xe54f, 0xd52c, 0xc50d,
&&& 0x34e2, 0x24c3, 0x14a0, 0x6, 0x4, 0x4405,
&&& 0xa7db, 0xb7fa, 0xb8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
&&& 0x26d3, 0x36f2, 0xb0, 0x6, 0x4,
&&& 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
&&& 0x5, 0x7, 0x18c0, 0x08e1, 0xa3,
&&& 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
&&& 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
&&& 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
&&& 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
&&& 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
&&& 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
unsigned short do_crc_table(unsigned char *ptr,int len)
&&& crc=0;
&& while(len--!=0)&
&& &&& da=(unsigned short)crc&&8;&&& /* 以8位二进制数的形式暂存CRC的高8位 */
&&& &&& crc&&=8;&&&&&&&&&&&&& /* 左移8位,相当于CRC的低8位乘以& */
&&& &&& crc^=crc_ta[da^*ptr];&& /* 高8位和当前字节相加后再查表求CRC ,再加上以前的CRC */
&&& &&& ptr++;
&& return(crc);
以上算法实现了按字节进行计算校验值。在使用的时候,把计算出来的校验值放在最后两个字节里,将其发送出去,接收端对所有的数据进行相同的校验,如校验值为0我们则认为其数据没有出错。这个是按高位到低位的发送顺序时使用的校验方法。
在实际应用中,还有一种按低位到高位的发送方法,这样 ,就要进行反相的校验,但如果把数据反相,显然加大计算量,故可以使用相应的查表算法来进行计算。只是计算方法与表不太一样,其实现算法如下:
unsigned short&crc16_ccitt_table[256] =
&&& 0x0000, 0x1189, 0xb, 0xad, 0xbf,
&&& 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
&&& 0x8, 0xa, 0x56a5, 0x472c, 0x75b7, 0x643e,
&&& 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
&&& 0xb, 0x9, 0xaf, 0xbd,
&&& 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
&&& 0xa, 0x8, 0x77a7, 0x662e, 0x54b5, 0x453c,
&&& 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
&&& 0xd, 0xf, 0xa9, 0xbb,
&&& 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0xe1, 0xab7a, 0xbaf3,
&&& 0xc, 0xe, 0x14a1, 0xb3, 0x263a,
&&& 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
&&& 0xf, 0xd, 0xab, 0xb9,
&&& 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
&&& 0xe, 0xc, 0x35a3, 0x242a, 0x16b1, 0x0738,
&&& 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
&&& 0x1, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
&&& 0xc9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
&&& 0x0, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
&&& 0x18c1, 0xbd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
&&& 0xa50a, 0xb483, 0x1, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
&&& 0xcb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
&&& 0xb58b, 0xa402, 0x0, 0xf3af, 0xe226, 0xd0bd, 0xc134,
&&& 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
&&& 0xc60c, 0xd785, 0xe51e, 0xf497, 0xa1, 0xa33a, 0xb2b3,
&&& 0x4a44, 0x5bcd, 0xdf, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
&&& 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0xbb, 0xa232,
&&& 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
&&& 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0xb1,
&&& 0x6b46, 0x7acf, 0xdd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
&&& 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
&&& 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
unsigned short do_crc_table_1(unsigned char *pData,int nLength)
&&& unsigned short fcs = 0&&& // 初始化
&&& while(nLength&0)
&&&&&&& fcs = (fcs && 8) ^&crc16_ccitt_table[(fcs ^ *pData) & 0xff];
&&&&&&& nLength--;
&&&&&&& pData++;
&&& return ~&&& // 取反
检验的时候,只要用以下方法就可以
int IsCrc16Good(unsigned char* pData, int nLength)
&&& unsigned short fcs = 0&&& // 初始化
&&& while(nLength&0)
&&&&&&& fcs = (fcs && 8) ^&&crc16_ccitt_table[(fcs ^ *pData) & 0xff];
&&&&&&& nLength--;
&&&&&&& pData++;
& //& return ();& // 0xf0b8是CRC-ITU的&Magic Value&
&&& if(fcs == 0xf0b8)
&&& &&& return 1;
&&& &&& return -1;
返回1则数据无误,否则数据错误。
其表的生成方法也比较简单,对于前一种查表方法,其生成表的算法可以由按位生成算法来计算得到,对0~255的字节进行CRC校验,得到的校验值分别做为表的相应项。
对于后一种查表方法,其码表可以由以下方法计算得到,
void&crc16_ccitt()
&&& unsigned char index = 0;
&&& unsigned short to_
&&& printf(&unsigned short&crc16_ccitt_table[256] =/n{&);
&&& while (1)
&&&&&&& if (!(index % 8))
&&&&&&&&&&& printf(&/n&);
&&&&&&& to_xor =&&&&&&
&&&&&&& for (i = 0; i & 8; i++)
&&&&&&&&&&& if (to_xor & 0x0001)
&&&&&&&&&&&&&&& to_xor = (to_xor &&1) ^ 0x8408;
&&&&&&&&&&& else
&&&&&&&&&&&&&&& to_xor &&= 1;&&&&&&&&&&
&&&&&&& }&&&&&&&&&&&
&&&&&&& printf(&0x%04x&, to_xor);
&&&&&&& if (index == 255)
&&&&&&&&&&& printf(&/n&);
&&&&&&&&&&&
&&&&&&& else
&&&&&&&&&&& printf(&, &);
&&&&&&&&&&& index++;
&&& printf(&};&);
&&& //return 0;
这样,对CRC算法算是有一个新的认识了,至少是分清了对于同一个多项式,为什么会有不同的计算方法。弄清后,就会明白在什么场合用什么样的算法。
原文地址:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:66972次
积分:1996
积分:1996
排名:第15709名
原创:43篇
转载:608篇
(19)(38)(26)(12)(20)(30)(47)(90)(79)(75)(65)(45)(37)(44)(18)(12)(5)(6)(1)(1)【求助】请教查表法计算CRC的原理 - 看雪安全论坛
『软件调试逆向』 [综合性论坛]本版讨论的主题包括:调试逆向、系统底层、商业保护、虚拟机保护、.NET平台等安全相关的话题。
该主题: "【求助】请教查表法计算CRC的原理" 因在一定的时间里没有任何回复而自动关闭。如果您还对该主题感兴趣或者想参与对此主题的讨论,请您重新发表一篇相关的新主题。
注册日期: Apr 2008
现金: 201 Kx
获感谢文章数:0获会员感谢数:0
, 21:10:09
【求助】请教查表法计算CRC的原理
在学CRC算法原理,受挫啊,这么一个简单的算法竟然看不懂&
下面引用一下vipchenji&《CRC技术的实现与破解》的原文
-----------------------------------------------------------------------------------------------------
下面就给您介绍CRC检验码的计算过程(查表法)
(1)将上次计算出的CRC校验码右移一个字节;
(2)将移出的这个字节与新的要校验的字节进行XOR&运算;
(3)用运算出的值在预先生成码表中进行索引,获取对应的值(称为余式);
(4)用获取的值与第(1)步右移后的值进行XOR&运算;
(5)如果要校验的数据已经处理完,则第(4)步的结果就是最终的CRC校验码。如果还有数据&要进行处理,则再转到第(1)步运行。
CRC32=CRC_32_Tbl[(CRC32^((unsigned__int8*)p)[i])&0xff]^(CRC32&&8);
怎么样?简单吧。
下面是完整的一个实现函数,更加简单:
//--------------------------------------------
//CalcCRC32函数计算出给定数据串的CRC-32校验码
//Code&:&Chenji
//--------------------------------------------
unsigned&int&CalcCRC32(void&*DataBuff,unsigned&int&BufLen)
{//DataBuff是指向数据串的指针,BufLen是数据串的长度
&&&&unsigned&int&CRC32=0&//设置初始值
for(unsigned&long&i=0;&i&BufL&++i)
&&&CRC32&=&CRC_32_Tbl[(CRC32^((unsigned&__int8&*)DataBuff)[i])&&&0xff]&^&(CRC32&&8);&
//如果你的编译器不支持unsigned&__int8定义,请试用unsigned&char
&&&&return&CRC32;
-------------------------------------------------------------------------------------------
请知道的或看懂的各位给我详细讲解一下查表法计算CRC的这个过程是怎么来的,实在是资质欠佳,看了很多天没头绪,也参考了部分资料(附件里),还是不懂&,谢谢!
上传的附件
(152.7 KB, 109 次下载)
被 zyqex 最后编辑
注册日期: Nov 2004
现金: 79 Kx
获感谢文章数:0获会员感谢数:0
, 21:46:53
自己写过的,&希望对你有帮助
Cyclic&Redundancy&Check(CRC)&原理及实现
///////////////////////////////////////////////////////////////////////////
在数据传送过程中,为了能够进行错误检测,&往往在数据后追加一些检测码,
当接受方收到了数据后,&用同样的算法进行计算检测码,&如果一致说明数据
正确,&否则通知发送方重新发送。&现假定数据为6&23&44:
历史上出现过多个算法,&如:
累加求模:
(6+23+4)%256&==&33,&则发送数据6&23&44&33
(6^&23&^4)&=&21&则发送数据&6&23&4&21
然而,&这却不是好的算法,&好的算法要求数据的数据能散列的分布在检测码
中,&对于累加求模的(6&24&3&)以及xor的(6&22&5)都能输出同样的检测码
于是,&CRC诞生了。
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
2:CRC的背景理论
crc将数据追加结尾的wbit的0当作一个很大阶的多项式,&用它去除于另一个双方约定的多项式,
得到的余数,&则为检测码,其中w为约定多项式的最大阶数,&最后传输原始数据追加检测码,
其中任何一位发生变化,&都导致最后得到的结果差别很大,&
CRC因为容易简单实现以及容错性强,&而被广泛使用。
追加wbit的好处是,&整个传输的数据刚刚能够被约定的多项式
p1|00..00|&/&p2&=&p3&.....p4
则(p1|00.00|+p4)&/&p2&=&p3....0
p1|00.00|+p4&=&p1|p4|&&(后面的多项式运算能够证明)
这里为了方便说明,&下列进行运行的数据都没有追加结尾的0
这里有2个问题,&如何把数据流转换成多项式,&以及如何做多项式的除法。
数据流的转换:
假如有2个byte(6,23)我们把他转成16进制为0617,&二进制表示为
01&0111&对应多项式&x^10&+&x^9&+&x^4&+&x^2&+&x^1&+&1
多项式除法:
先说多项式加法,&多项式x^4&+&x^2&+&x&+&1&和多项式x^4+x^3+1
为&2*x^4&+&x^3&+&x^2&+&x^1&+&2*(x^0)
由于x是个未知数,&不知道怎么进行系数和阶的转换,&于是规定:
&&如果系数mod2==0,&那么则丢弃,&否则保留,&多项式不考虑系数&
所以上述2个多项式相加的结果为&x^3+x^2+x^1
同样根据规定可以知道,&多项式p1+p2&==&p1-p2,
即:&多项式相减等同于多项式相加.&
用2进制表示有&1011&+&1101&=&&-&1101&=&0110
这即等同与2进制的xor操作。
再来看看多项式乘法,&(x^4+x^2+x^1+1)&*&(x^2&+&x^1&+&1)
&=&(x^6+x^4+x^3+x^2)&+&(x^5+x^3+x^2+x^1)&+&(x^4+x^2+x^1+1)
&=&x^6&+&x^5&+&x^2&+&1
我们再来看看多项式除法
&&&&&&&&&&&&&&&x^2&+&x1&+&1
&&&&&&&&&&&&&&--------------------
x^4+x^2+x^1+1&)&x^6&+&x^5&+&x^2&+&1
&&&&&&&&&&&&&&&(x^6+x^4+x^3+x^2)&+&(x^5+x^3+x^2+x^1)&+&(x^4+x^2+x^1+1)
&&&&&&&&&&&&&&-(x^6&+&x^4&+&x^3&+&x^2)
&&&&&&&&&&&&&&&(x^5+x^3+x^2+x^1)&+&(x^4+x^2+x^1+1)
&&&&&&&&&&&&&&-(x^5+x^3+x^2+x^1)
&&&&&&&&&&&&&&&(x^4+x^2+x^1+1)
&&&&&&&&&&&&&&-(x^4+x^2+x^1+1)
&&&&&&&&&&&&&&&&0
根据乘/除法和加/减法的运算规则不难看出,&
a:&p1&%&p2&=&p3....p4&===&&p1&=&p2*p3&+&p4
b:&设p2是一个w阶的多项式,&那么余数是一个w-1阶的多项式。&w叫做多项式的位宽。
&&&比如&x^4+x^2+x^1+1的位宽为4,&余数为一个3阶的多项式。&占4个2进制位.
&&&crc中,&把w位宽的多项式叫做crcw,&如约定的除式为X^4+x^2+x^1+1&(10111)
&&&那么就叫crc4,&对于的余数则在(0000&...&1111)的范围内.
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
对于2中定义的多项式.&转成2进制的形式,&有
&&&&&&&&&&&&&111
&&&&&&&&&&&&-------------------
10111&(b)&&&)1100101&&&&&&&&&&&&&&&&&&&(a)
&&&&&&&&&&&&&10111..
&&&&&&&&&&&&&&11100.
&&&&&&&&&&&&&&10111.
&&&&&&&&&&&&&&&10111&
&&&&&&&&&&&&&&&10111
&&&&&&&&&&&&&&&&&&&0
不难看出,&设4bit的crc初始为0,&每次从crc中移走最高位,&从a中移走一位进最
低位,&&如果crc中移走的为1,&则将结果xor下10111的低4位(0111),&否则不处理
c语言描述有
while&(msg)
&&&crc&=&(crc&&1&|&get_msg_bit)&^&&(&(crc&1000)&?&()&:&0000)
for(int&i=0;&i&w;&++i)
&&crc&=&(crc&&1&|&0)&^&&(&(crc&1000)&?&()&:&0000)
上述即是crc的标准算法.&下面我们开始优化.
----------------------------------------
优化a:&查表法
设a,b,c都是4bit的数,&有
(a^b)&^&c&==&a&^&(b^c)&&&
证明:&因为xor都是位对其操作,&所以我们只要证明bit具有属性(b1^b2)^b3==b1^(b2^b3)
因&(b1^b2)^b3&==&((b1+b2)+b3)mod2,&&&b1^(b2^b3)&==&(b1+(b2+b3))mod2&
bit&operator&+&具有交换率,&&所以&(a^b)^c&==&a^(b^c)
因为计算机的操作单元一般都是byte,&如果每次都进行一次bit操作,&那么效率上
会大打折扣.
现在我们假设w是32,&即crc32.&有个4byte的寄存器R&[b1&b2&b3&b4]&用来存储CRC32的值
根据前面的交换率,&我们可以先计算出b1对于后4个字节的影响值来,&记做table[b1]
然后把b2&b3&b4&a&(a为读出的一个byte的msg)&跟&table[b1]来xor下.&有
while(msg)
&&&crc&=&&&&&(crc&&8&|&get_msg_byte)&^&&table[crc&&&&24];
for(int&i=0;&i&w/8;&++i)
&&&crc&=&&&&&(crc&&8&|&0)&^&table[crc&&24];
前提是要提前计算出一个静态的256项的表来,&当然你也可以计算出65536项的表来,&一次
update&2个byte,&但这样意义不大.
----------------------------------------
优化b:&&我们现在开始把后面烦琐的&for(int&i=0;&i&w/8;&++i)&给优化掉.
假如数据&aa&bb&cc&dd&..&xx&00&00&00&00&有crc32为&(a1&a2&a3&a4)&&&&&&&&&.....(1)
&&&&数据&aa&bb&cc&dd&..&xx&yy&00&00&00&00&有crc32为(b1&b2&b3&b4)&&&&&&&.....(2)
&&&&数据&aa&bb&cc&dd&..&xx&yy&00&00&00&有crc32(c1&c2&c3&c4)&&&&&&&&&&&&.....(3)
不难看出,&c1=a1^yy&c2=a2&c3=a3&c4=a4,&&这是因为yy处于最后w位移进R的,&他不会被R
移出左边,&所以他不会影响到后面3个0.&他只会被前面的值xor影响到,&由于xor具有
交换率,&所以c1=a1^yy,&现在..
&&&&&&&&&aa&bb&cc&dd&..&xx&yy&00&00&00&有crc32(a1^yy&a2&a3&a4)&&&&&&&&&.....(3)
&&&&&&&&&aa&bb&cc&dd&..&xx&yy&00&00&00&00&有crc32(b1&b2&b3&b4)&&&&&&&&&.....(2)
根据a的查表,&我们可以知道
(b1&b2&b3&b4)&&==&&&&&table[a1^yy]&^&(a2&a3&a4&00)
回到刚开始,&crc32&init&==&(x1&x2&x3&x4),&&那么&x1&x2&x3&x4&00&00&00&00&=&(y1&y2&y3&y4)
现在init=0,&所以x1x2x3x4y1y2y3y4&=&0
有&aa&00&00&00&00&为&table[aa],&也就是&table[aa^0]&^&(0)
while(msg)
&&crc&&=&table[crc&&24&^&get_msg_byte]&^&(crc&&8)
-------------------------------------------
优化c&:&Reflected
由于我们用字节存储的时候,&都是LSBF(least&significant&bit&first)
而我们b里面是用的MSBF,&&也就是说,&在算法b中,&我们需要:
把每次get_msg_byte都需要Reflected
initial&value需要reflected
最后的结果需要reflected下
byte&reflected(byte&b)
&&&byte&c;
&&&for(int&i=0;&i&8;&++i)
&&&&&&c&&&=&1;
&&&&&&if&(b&1)&c|=1;
&&&&&&b&&&=&1;
&&&return&c;
while(msg)
&&crc&=&table[crc&^&get_msg_byte]&^&(crc&&8)
注意这里的table,&是用reflected的多项式生成的.
initial&value也是reflected的.&为了get_msg_byte不需要reflect,&那么
table中,&index也是被reflected了.
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
4:&可变参数
我们知道了,&CRC算法受到下列形态的影响
*&多项式的w,&以及多项式
*&initial&value
*&做处理的时候是&MSBF还是LSBF
*&final&register&&
(同initial&value,&为了区分不同的crc,&当同一个消息时,
所以定义了最后的xor&final&register)
下面给出一种模型.
Rocksoft^tm&Model&CRC&Algorithm
Name,&Width,&Poly,&Init,&Refin,&Refout
下列是一份常用的CRC列表
&&&X25&&&standard&:&1021&&&&&&&[CRC-CCITT,&ADCCP,&SDLC/HDLC]
&&&X25&&&reversed&:&0811
&&&CRC16&standard&:&8005
&&&CRC16&reversed&:&4003&&&&&&&[LHA]
&&&Name&&&:&&CRC-16&
&&&Width&&:&16
&&&Poly&&&:&8005
&&&Init&&&:&0000
&&&RefIn&&:&True
&&&RefOut&:&True
&&&XorOut&:&0000
&&&Check&&:&BB3D
&&&Name&&&:&&CRC-16/CITT&
&&&Width&&:&16
&&&Poly&&&:&1021
&&&Init&&&:&FFFF
&&&RefIn&&:&False
&&&RefOut&:&False
&&&XorOut&:&0000
&&&Name&&&:&&XMODEM&
&&&Width&&:&16
&&&Poly&&&:&8408
&&&Init&&&:&0000
&&&RefIn&&:&True
&&&RefOut&:&True
&&&XorOut&:&0000
&&&Name&&&:&&ARC&
&&&Width&&:&16
&&&Poly&&&:&8005
&&&Init&&&:&0000
&&&RefIn&&:&True
&&&RefOut&:&True
&&&XorOut&:&0000
&&&Name&&&:&&CRC-32&
&&&Width&&:&32
&&&Poly&&&:&04C11DB7&&&&&&&&[PKZIP,&AUTODIN&II,&Ethernet,&FDDI]
&&&Init&&&:&FFFFFFFF
&&&RefIn&&:&True
&&&RefOut&:&True
&&&XorOut&:&FFFFFFFF
&&&Check&&:&CBF43926
///////////////////////////////////////////////////////////////////////////
注册日期: Mar 2006
现金: 288 Kx
获感谢文章数:0获会员感谢数:0
, 11:30:35
简单来说就是,你想求一个数X&=&A&xor&B&xor&C&xor&D&xor&E&xor&F,但是这样一次一次xor多麻烦啊,如果你知道&Y&=&B&xor&C&xor&D&xor&E,就是其中的某一段,那么就可以直接xor啦,比如X&=&A&xor&Y&xor&F。
CRC一次xor一位多麻烦啊,不如一次预先计算出8位也就是一个byte的xor结果,也就是256种,CRC的时候,你一看下面的8位是什么,直接去找事先计算好的就行啦。所以列表就好像是求出那个中间值Y,这样一次可以xor&8位。
注册日期: Apr 2008
现金: 201 Kx
获感谢文章数:0获会员感谢数:0
, 12:51:37
谢谢以上两楼的回帖,明白了一些,研读中!
该主题: "【求助】请教查表法计算CRC的原理" 因在一定的时间里没有任何回复而自动关闭。如果您还对该主题感兴趣或者想参与对此主题的讨论,请您重新发表一篇相关的新主题。
您不可以发表主题
您不可以回复帖子
您不可以上传附件
您不可以编辑自己的帖子
论坛论坛启用
用户控制面板
会员在线状态
『看雪众测/众包』
『Android 安全』
『iOS安全』
『求助问答』
『经典问答』
『资料导航』
『软件调试逆向』
『编程技术』
『加壳与脱壳』
『资源下载』
『WEB安全』
『漏洞分析』
『密码学』
『外文翻译』
『CrackMe&ReverseMe』
『招聘专区』
『职业生涯』
『15PB培训』
『麦洛克菲培训』
『茶余饭后』
『安全资讯』
『论坛活动』
6)PEDIY Crackme竞赛2009
7)看雪十周年专版
8)腾讯公司2010软件安全竞赛
9)2011 Exploit Me竞赛
『图书项目版』
《加密与解密(第三版)》
《C++反汇编与逆向分析技术揭秘》
《Android软件安全与逆向分析》
『论坛版务』
所有时间均为北京时间, 现在的时间是 .
&&& 看雪学院()
| 提供带宽资源
|&微信公众帐号:吕东杰的博客
CRC16是单片机程序中常用的一种校验算法。依据所采用多项式的不同,得到的结果也不相同。常用的多项式有CRC-16/IBM和CRC-16/CCITT等。本文代码采用的多项式为CRC-16/IBM: X16+X15+X2+1。闲言少叙,下面是查表法计算CRC16的代码:
/*******************************************************************************
Copyright (c) 2012 ICPUB.NET. All Rights Reserved.
文件名称: crc16.c
简要描述: CRC16查表算法
当前版本: 1.0
者: ICPUB.NET
*******************************************************************************/
#include &stdint.h&
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
static uint16_t const CRC16Table[256] = {
0xC1, 0xC181, 0x1, 0x03C0, 0x1,
0xC601, 0x06C0, 0x1, 0xC1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x1,
0xD801, 0x18C0, 0x1, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0xC1, 0xD581, 0x1, 0x17C0, 0x1,
0xD201, 0x12C0, 0x1, 0xC1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x1, 0xC1, 0xF281, 0x3240,
0xC1, 0xF781, 0x1, 0x35C0, 0x1,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0xC1, 0xF881, 0x3840,
0xC1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x1, 0xC1, 0xE681, 0x2640,
0xC1, 0xE381, 0x1, 0x21C0, 0x1,
0xA001, 0x60C0, 0x1, 0xC1, 0xA281, 0x6240,
0xC1, 0xA781, 0x1, 0x65C0, 0x1,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0xC1, 0xA881, 0x6840,
0xC1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x1, 0xC1, 0xB681, 0x7640,
0xC1, 0xB381, 0x1, 0x71C0, 0x1,
0xC1, 0x0, 0xC0, 0x1,
0xC0, 0x1, 0xC1, 0x0,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0xC0, 0x1,
0xC0, 0x1, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0xC1, 0x0, 0xC0, 0x1,
0xC0, 0x1, 0xC1, 0x0
/*******************************************************************************
函数名称: CRC16
功能描述: 查表法计算CRC16.
输入参数: dataIn -- 待校验数据
length -- 数据长度
返 回 值: 校验值
*******************************************************************************/
uint16_t CRC16(uint8_t* dataIn, int length)
uint16_t result
uint16_t tableNo = 0;
for(int i = 0; i & i++)
tableNo = ((result & 0xff) ^ (dataIn[i] & 0xff));
= ((result && 8) & 0xff) ^ CRC16Table[tableNo];
阅读(...) 评论()

我要回帖

更多关于 crc32算法原理 的文章

 

随机推荐