打印

CRC16CCITT(1021)的16字表长查表程序

[复制链接]
4063|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hotpower|  楼主 | 2009-10-18 17:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hotpower 于 2009-10-18 18:26 编辑

CRC16CCITT(1021)的16字表长查表程序
此文依据: http://blog.**/hotpower/272834/message.aspx
CRC位域4单表查表及建表原则:
左移位域4取列表16个,大端存储模式。右移位域4取行表16个,小端存储模式。
在CRC16CCITT中CRC的多项式为:左移CRC16=X16+X12+X5+1,即权值=0x1021,故建立16字节的CRC表格:
(参见:http://zh.wikipedia.org/zh-cn/%E5%BE%AA%E7%8E%AF%E5%86%97%E4%BD%99%E6%A0%A1%E9%AA%8C)
特别注意:它的初值为0xFFFF,只用一次,本次的结果即为下次的初值,故与CRC表的构造无关。
网上CRC16的256个表为:
unsigned int CRC16Table[256] = {                                 
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,//注意本行的0x1021
    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 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,
    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
    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
};
即CRC位域8表:
CRC16Table[256]={CRC[0x0000],CRC[0x0001],CRC[0x0002],...CRC[0x00FD],CRC[0x00FE],CRC[0x00FF]};
特别注意对CRC表逆向出权值的方法(256表):
右移方式,CRC多项式即权值=CRC16Table[0x80]
左移方式,CRC多项式即权值=CRC16Table[0x01]=0x1021
本文采用CRC位域4查表方式,故表为:
CRC16Table[16]={CRC[0x0000],CRC[0x0001],CRC[0x0002],...CRC[0x000D],CRC[0x000E],CRC[0x000F]};
即左移方式取列表:
CRC16Table[16]={
  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,//注意本行的0x1021
  0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
};
unsigned int GetCRC16(unsigned int crcinit, unsigned int crcval)
{//(可以不要初值crcinit,多字节CRC16时入口需要对crcval做处理)
unsigned int i, crc=0;
  crcval = crcinit ^ crcval;//初值为0xFFFF,只用一次,函数下次调用时crcinit=crc
  for(i = 0;i < 4;i ++)//2个字节位域4需要4次完成
  {//左移12次可认为是大端存储模式
    crc = (crc << 4) ^ CRC16Table[((crc ^ crcval) >> 12) & 0x0F];//位域宽4单表16个字节
    crcval <<= 4;//准备下一个位域,域宽4
  }
  return crc;//本次crc结果,做为下次GetCRC16()调用的初值crcinit,切记!!!
}

菜农HotPower@126.com  2009.10.18 于雁塔菜地

相关帖子

沙发
红金龙吸味| | 2009-10-18 17:50 | 只看该作者
哈哈,终于见到hot前辈出来了。

使用特权

评论回复
板凳
shopping.w| | 2009-10-18 18:02 | 只看该作者
^_^ hot大叔好

使用特权

评论回复
地板
jerkoh| | 2009-10-18 21:12 | 只看该作者
大叔 这个实用收下了~

使用特权

评论回复
5
hotpower|  楼主 | 2009-10-18 22:12 | 只看该作者
本帖最后由 hotpower 于 2009-10-18 22:38 编辑

哈哈~~~既然大家喜欢,俺就表演个“手动的”CRC16CCITT(1021)的16字表长查表演算过程:

CRC16Table[16]={
  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,//注意本行的0x1021
  0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
};

例如 CRC16,初值为0x0000, 求CRC16[0x1234]=0x13C6:

第1步:
CRC[0x1234>>12]=CRC[0x01]=0x1021
0x1234变为0x2340

第2步:
(0x1021<<4) ^ CRC[(0x1021>>12) ^ (0x2340>>12)]=0x0210 ^ CRC[0x01 ^ 0x02]
=0x0210 ^ CRC[0x03]=0x0210 ^ 0x3063 = 0x3273
0x2340变为0x3400

第3步:
(0x3273<<4) ^ CRC[(0x3273>>12) ^ (0x3400>>12)]=0x2730 ^ CRC[0x03 ^ 0x03]
=0x2730 ^ CRC[0x00]=0x2730 ^ 0x0000 = 0x2730
0x3400变为0x4000

第4步:
(0x2730<<4) ^ CRC[(0x2730>>12) ^ (0x4000>>12)]=0x7300 ^ CRC[0x02 ^ 0x04]
=0x7300 ^ CRC[0x06]=0x7300 ^ 0x60C6 = 0x13C6

例如 CRC16,初值为0xFFFF, 求CRC16[0x1234]=0x0EC9:

初始化: 0x1234 ^ 0xFFFF = 0xEDCB
第1步:
CRC[0xEDCB>>12]=CRC[0x0E]=0xE1CE
0xEDCB变为0xDCB0

第2步:
(0xE1CE<<4) ^ CRC[(0xE1CE>>12) ^ (0xDCB0>>12)]=0x1CE0^ CRC[0x0E ^ 0x0D]
=0x1CE0^ CRC[0x03]=0x1CE0^ 0x3063 = 0x2C83
0xDCB0变为0xCB00

第3步:
(0x2C83<<4) ^ CRC[(0x2C83>>12) ^ (0xCB00>>12)]=0xC830^ CRC[0x02 ^ 0x0C]
=0xC830 ^ CRC[0x0E]=0xC830 ^ 0xE1CE= 0x29FE
0xCB00变为0xB000

第4步:
(0x29FE<<4) ^ CRC[(0x29FE>>12) ^ (0xB000>>12)]=0x9FE0^ CRC[0x02 ^ 0x0B]
=0x9FE0^ CRC[0x09]=0x9FE0^ 0x9129= 0x0EC9


使用演算工具:http://www.hotc51.com/HotPower_HotWC3.html

或查表:
CRC16Table[16]={
  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,//注意本行的0x1021
  0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
};

本贴可以证明菜农的脑浆是“红色的”~~~
16*2个字节“比拼”256*2个字节的结果:
循环次数是4次,而后者为2次。即速度降低1倍但空间被压缩16倍,不知菜农失败否~~~

使用特权

评论回复
6
hotpower|  楼主 | 2011-12-26 13:14 | 只看该作者
顶起来,掀起密码安全教育风暴~~~

使用特权

评论回复
7
tl5324260| | 2011-12-26 13:22 | 只看该作者
楼上 刷屏?

使用特权

评论回复
8
dengm| | 2011-12-26 13:33 | 只看该作者
用 4个 16*2 bytes 的表,  能快一点点吗?
PS: 每4bits, 对应一个表.

使用特权

评论回复
9
hotpower|  楼主 | 2012-10-23 18:54 | 只看该作者
挖墓为2012.10.25菜农个人版《HotWC3密码体系》开版搜索

使用特权

评论回复
10
lhchen922| | 2013-11-16 20:29 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1460

主题

21619

帖子

506

粉丝