转载

Java中的CRC校验

最近客户有CRC校验的需求,即希望Android端对字符串进行校验,并将生成的2个字节的CRC校验码追加到字符串中,然后一起写入文件。当系统联网后,会通过写入的字符串去向服务器请求设备序列号,服务器会根据该字符串的原始字符串(不含校验码)进行校验,如果校验出来的值跟最后两个字节的校验码匹配上,则下发一个序列号,否则为空。

概述

CRC的校验方式多种多样,每个客户都有自己的校验方式。此次客户提供了C语言版本的校验方式,这边要将C语言版本的校验转化为Java版本。

但由于C语言和Java的基本类型对不上,如C语言的变量类型有符号之分,而Java则统一都带符号,并没有所谓的无符号类型变量。若未接触过的同学可能要费点时间去做转化,这里给出转化的技巧。

C语言版本的校验

这里先上C语言版本的校验,代码如下:

unsigned short int CRC_TABLE[16]={0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7,
0x8108,0x9129,0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF};

 unsigned int getCRC( char *pbuffer,  unsigned int buff_len)
{
    unsigned short int mCRC;
    unsigned char mTemp;

    mCRC=0x0;
    
    while(buff_len--)
    {
        mTemp=(unsigned char)(mCRC>>0x0C);
        mCRC<<=4;
        mCRC^=CRC_TABLE[mTemp^((*pbuffer)>>0x04)];
        mTemp=(unsigned char)(mCRC>>0x0C);
        mCRC<<=4;
        mCRC^=CRC_TABLE[mTemp^((*pbuffer)&0x0F)];
        pbuffer++;
    }
    
    return (unsigned int)mCRC;
}
复制代码

一般CRC校验都会有一个码表,用于生成校验码。

由于C语言有有符号和无符号之分,而Java则没有这种区分,那么在转化的时候,要注意符号的问题。这里有个技巧,转化时,C语言和Java的类型对应关系如下:

int->int
short->int
char*->String/byte[]
char->short
复制代码

什么意思?即C语言使用int类型的变量时,Java也使用int类型变量,C语言使用short类型变量时,Java使用int类型变量。。。

Java版本的CRC校验

贴上Java的CRC校验代码,大家对照着看就明白:

private byte[] getCRC16(String data) {
    int crc = 0x0; //这里只需用到int的低16位即可
    short tem = 0x00;
    char[] ch = data.toCharArray();
    for (char c : ch) {
        byte b = (byte)c;
        tem = (short)((crc >> 0x0c) & 0x00ff); 
        crc <<= 4;
        crc &= 0x0000ffff;   //保证高16位一直为0
        crc ^=crc16tab[(tem ^ (b >> 0x04))&0x000000ff]; //获取高八位CRC校验码
        crc &= 0x0000ffff; 
        tem = (short)((crc >> 0x0c) & 0x00ff);
        crc <<= 4;
        crc &= 0x0000ffff;
        crc ^= crc16tab[(tem ^ (b & 0x0f)) & 0x000000ff]; //获取低八位CRC校验码
        crc &= 0x0000ffff;//只需低16位的CRC校验码
    }
    
    byte[] res = intToByteArray(crc);//将int类型转为byte数组 
    
    return res;
}
复制代码

需要注意的是,在CRC校验中,有针对16进制字节进行校验的,有针对字符进行校验的,比如需要校验如下内容:

0001020304050607
复制代码

那么这时需要确认清楚,到底是校验字节,还是逐个字符的进行校验。本文则是逐个字符进行校验。

结语

CRC校验多见于通讯协议中,会对通讯内容进行校验,然后将生成的校验码追加到通讯帧中。也有像本文这样子的,对某个文件中的内容进行校验,然后生成校验码,提高安全性。

原文  https://juejin.im/post/5e9d71fe518825738943c93a
正文到此结束
Loading...