CCITT标准CRC16(1021) Java代码

背景:

与GPS运营商做数据对接,图片、GPS、轨迹所有数据数据包中都有CRC校验值,需要对数据包进行校验。

Java代码:

  1. package com.jst.util;  
  2.   
  3. /** 
  4.  * CRC-CCITT 算法校验类 
  5.  *  
  6.  * @author amadowang 
  7.  * @version [版本号, Aug 29, 2011] 
  8.  * @see [相关类/方法] 
  9.  * @since [产品/模块版本] 
  10.  * @date 2012-10-24 
  11.  */  
  12. public class CRCUtil {  
  13.     /* 
  14.      * CCITT标准CRC16(1021)余数表 CRC16-CCITT ISO HDLC, ITU X.25, x16+x12+x5+1 多项式 
  15.      * 高位在先时生成多项式 Gm=0x11021 低位在先时生成多项式,Gm=0x8408 本例采用高位在先 
  16.      */  
  17.     private static int crc16_ccitt_table[] = { 0x00000x10210x20420x30630x40840x50a50x60c60x70e70x81080x91290xa14a,  
  18.             0xb16b0xc18c0xd1ad0xe1ce0xf1ef0x12310x02100x32730x22520x52b50x42940x72f70x62d60x93390x83180xb37b,  
  19.             0xa35a0xd3bd0xc39c0xf3ff0xe3de0x24620x34430x04200x14010x64e60x74c70x44a40x54850xa56a0xb54b0x8528,  
  20.             0x95090xe5ee0xf5cf0xc5ac0xd58d0x36530x26720x16110x06300x76d70x66f60x56950x46b40xb75b0xa77a0x9719,  
  21.             0x87380xf7df0xe7fe0xd79d0xc7bc0x48c40x58e50x68860x78a70x08400x18610x28020x38230xc9cc0xd9ed0xe98e,  
  22.             0xf9af0x89480x99690xa90a0xb92b0x5af50x4ad40x7ab70x6a960x1a710x0a500x3a330x2a120xdbfd0xcbdc0xfbbf,  
  23.             0xeb9e0x9b790x8b580xbb3b0xab1a0x6ca60x7c870x4ce40x5cc50x2c220x3c030x0c600x1c410xedae0xfd8f0xcdec,  
  24.             0xddcd0xad2a0xbd0b0x8d680x9d490x7e970x6eb60x5ed50x4ef40x3e130x2e320x1e510x0e700xff9f0xefbe0xdfdd,  
  25.             0xcffc0xbf1b0xaf3a0x9f590x8f780x91880x81a90xb1ca0xa1eb0xd10c0xc12d0xf14e0xe16f0x10800x00a10x30c2,  
  26.             0x20e30x50040x40250x70460x60670x83b90x93980xa3fb0xb3da0xc33d0xd31c0xe37f0xf35e0x02b10x12900x22f3,  
  27.             0x32d20x42350x52140x62770x72560xb5ea0xa5cb0x95a80x85890xf56e0xe54f0xd52c0xc50d0x34e20x24c30x14a0,  
  28.             0x04810x74660x64470x54240x44050xa7db0xb7fa0x87990x97b80xe75f0xf77e0xc71d0xd73c0x26d30x36f20x0691,  
  29.             0x16b00x66570x76760x46150x56340xd94c0xc96d0xf90e0xe92f0x99c80x89e90xb98a0xa9ab0x58440x48650x7806,  
  30.             0x68270x18c00x08e10x38820x28a30xcb7d0xdb5c0xeb3f0xfb1e0x8bf90x9bd80xabbb0xbb9a0x4a750x5a540x6a37,  
  31.             0x7a160x0af10x1ad00x2ab30x3a920xfd2e0xed0f0xdd6c0xcd4d0xbdaa0xad8b0x9de80x8dc90x7c260x6c070x5c64,  
  32.             0x4c450x3ca20x2c830x1ce00x0cc10xef1f0xff3e0xcf5d0xdf7c0xaf9b0xbfba0x8fd90x9ff80x6e170x7e360x4e55,  
  33.             0x5e740x2e930x3eb20x0ed10x1ef0 };  
  34.   
  35.   
  36.     /** 
  37.      *  
  38.      * @param reg_init CRC校验时初值 
  39.      * @param message 校验值 
  40.      * @return 
  41.      */  
  42.     private static int do_crc(int reg_init, byte[] message) {  
  43.         int crc_reg = reg_init;  
  44.         for (int i = 0; i < message.length; i++) {  
  45.             crc_reg = (crc_reg >> 8) ^ crc16_ccitt_table[(crc_reg ^ message[i]) & 0xff];  
  46.         }  
  47.         return crc_reg;  
  48.     }  
  49.   
  50.     /** 
  51.      * 根据数据生成CRC校验码 
  52.      *  
  53.      * @param message 
  54.      *            byte数据 
  55.      *  
  56.      * @return int 返校验码 
  57.      */  
  58.     private static int do_crc(byte[] message) {  
  59.         // 计算CRC校验时初值从0x0000开始。  
  60.         int crc_reg = 0x0000;  
  61.         return do_crc(crc_reg, message);  
  62.     }  
  63.     /** 
  64.      * db44检验方法 
  65.      *  
  66.      * @param message 消息内容 
  67.      * @param crc 检验码值 
  68.      * @return 
  69.      */  
  70.     private static boolean do_crc(byte[] message,byte[] crc) {  
  71.         // 计算CRC校验时初值从0x0000开始。  
  72.         int crc_reg = 0x0000;  
  73.         int crc_value = (crc[0]&0xff)*256+(crc[1]&0xff);  
  74.         return crc_value ==do_crc(crc_reg, message);  
  75.     }  
  76.     /** 
  77.      * 供db44结构代码使用,数组后两位为CRC-校验码值 
  78.      * @param messages 
  79.      * @return 
  80.      */  
  81.     public static boolean do_crc_db44(byte[] messages) {  
  82.         // 计算CRC校验时初值从0x0000开始。  
  83.         byte[] messageArray = new byte[messages.length-2];  
  84.         byte[] crcArray = new byte[2];  
  85.         System.arraycopy(messages, 0, messageArray, 0, messageArray.length);  
  86.         System.arraycopy(messages, messages.length-2, crcArray, 02);  
  87.         return do_crc(messageArray, crcArray);  
  88.     }  
  89.   
  90.     public static void main(String[] args) {  
  91.         // 一个db44测试样本数据  
  92.         byte p[] = {71,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,68,31,32,0,1,2};  
  93.         int crc = do_crc(p); // 计算前两位的CRC码  
  94.         // 65336  
  95.         System.out.println(crc);  
  96.           
  97.     }  
  98.   
  99. }  
package com.jst.util;

/**
 * CRC-CCITT 算法校验类
 * 
 * @author amadowang
 * @version [版本号, Aug 29, 2011]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 * @date 2012-10-24
 */
public class CRCUtil {
	/*
	 * CCITT标准CRC16(1021)余数表 CRC16-CCITT ISO HDLC, ITU X.25, x16+x12+x5+1 多项式
	 * 高位在先时生成多项式 Gm=0x11021 低位在先时生成多项式,Gm=0x8408 本例采用高位在先
	 */
	private static int crc16_ccitt_table[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 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 };


	/**
	 * 
	 * @param reg_init CRC校验时初值
	 * @param message 校验值
	 * @return
	 */
	private static int do_crc(int reg_init, byte[] message) {
		int crc_reg = reg_init;
		for (int i = 0; i < message.length; i++) {
			crc_reg = (crc_reg >> 8) ^ crc16_ccitt_table[(crc_reg ^ message[i]) & 0xff];
		}
		return crc_reg;
	}

	/**
	 * 根据数据生成CRC校验码
	 * 
	 * @param message
	 *            byte数据
	 * 
	 * @return int 返校验码
	 */
	private static int do_crc(byte[] message) {
		// 计算CRC校验时初值从0x0000开始。
		int crc_reg = 0x0000;
		return do_crc(crc_reg, message);
	}
	/**
	 * db44检验方法
	 * 
	 * @param message 消息内容
	 * @param crc 检验码值
	 * @return
	 */
	private static boolean do_crc(byte[] message,byte[] crc) {
		// 计算CRC校验时初值从0x0000开始。
		int crc_reg = 0x0000;
		int crc_value = (crc[0]&0xff)*256+(crc[1]&0xff);
		return crc_value ==do_crc(crc_reg, message);
	}
	/**
	 * 供db44结构代码使用,数组后两位为CRC-校验码值
	 * @param messages
	 * @return
	 */
	public static boolean do_crc_db44(byte[] messages) {
		// 计算CRC校验时初值从0x0000开始。
		byte[] messageArray = new byte[messages.length-2];
		byte[] crcArray = new byte[2];
		System.arraycopy(messages, 0, messageArray, 0, messageArray.length);
		System.arraycopy(messages, messages.length-2, crcArray, 0, 2);
		return do_crc(messageArray, crcArray);
	}

	public static void main(String[] args) {
		// 一个db44测试样本数据
		byte p[] = {71,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,68,31,32,0,1,2};
		int crc = do_crc(p); // 计算前两位的CRC码
		// 65336
		System.out.println(crc);
		
	}

}


原文地址:http://blog.csdn.net/javaee_ssh/article/details/27202753


  • 2
    点赞
  • 2
    收藏
  • 0
    评论
易语言 CRC32.ec校验模块 林子深作品 比其他的都便宜 CRC32.ec校验模块 林子深作品 下载 CRC32.ec校验模块下载 我们很有必要给自己的软件加上更好的保护。CRC校验就是其中的一种不错的方法。 CRC是什么东西呢?其实我们大家都不应该会对它陌生,回忆一下?你用过RAR和ZIP等压缩软件吗?它们是不是常常会给你一个恼人的“CRC校验错误”信息呢?我想你应该明白了吧,CRC就是块数据的计算值,它的全称是“Cyclic Redundancy Check”,中文名是“循环冗余码”,“CRC校验”就是“循环冗余校验”。 CRC有什么用呢?它的应用范围很广泛,最常见的就是在网络传输中进行信息的校对。其实我们大可以把它应用到软件保护中去,因为它的计算是非常非常非常严格的。严格到什么程度呢?你的程序只要被改动了一个字节(甚至只是大小写的改动),它的值就会跟原来的不同。呵呵,是不是很厉害呢?所以只要给你的“原”程序计算好CRC值,储存在某个地方,然后在程序中随机地再对文件进行CRC校验,接着跟第一次生成并保存好的CRC值进行比较,如果相等的话就说明你的程序没有被修改/破解过,如果不等的话,那么很可能你的程序遭到了病毒的感染,或者被奸人用16进制工具暴力破解过了。 CRC的本质是进行XOR运算,运算的过程我们不用管它,因为运算过程对最后的结果没有意义;我们真正感兴趣的只是最终得到的余数,这个余数就是CRC值。 易语言用户林子深提供了一个CRC32.EC的易模块,这个模块可以在论坛上或资源网上搜索到。大家可以直接拿过来用,导入易语言后如下图所示: 调用方式可为如下代码: 判断(取循环风俗冗余校验和(读入文件(取执行文件名()))= 18293823767) 其中上述的数字为主程序的CRC码值。 大家可以利用上述特性,即结果是数值的特性,不用进行比较,而是用加减法的方法得出前后两个CRC验的差值,如果为0,那说明两个数字是相等的,主程序没有被改动过。否则就是被改过的。 例如下述代码: 程序被改 = 1 计次循环首(取绝对值(取循环风俗冗余校验和(读入文件(取执行文件名()))- 18293823767),) 程序被改 = 0- 跳出循环() 计次循环尾() 返回(程序被改) 上述代码中,“取绝对值()”是将负数也转换为正数,以方便进行计次循环。 上述代码中,数值型变量“程序被改”为1表示没有被改动过,如果为0表示被改动过。返回的数值就可以进行一些陷阱的计算了。 我的方案的缺点分析: CRC-32的值其实可以由奸人自行计算得出后,重新写入到程序验证处。这样的话,我们做的工作岂不是没有意义了? 其实解决的方法还是有的,我们可以在计算CRC-32值之前,对参与转换的字符串加点手脚,例如对这个字符串进行移位、xor等操作,或者把自己的生日等信息加入到字符串中,随你的便什么都行,总之不是单纯的文件的内容就行了,然后在最后比较的时候,也用同样的方法反计算出CRC-32值。这样得到的CRC-32就不是由文件的内容计算出来的,相信对破解者的阻力也会加大不少。 总结: 以上的方法大家都可以在软件中采用,最好写到一个DLL文件中,然后多放几个需要验证的子程序,随时以备调用即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值