`
f543711700
  • 浏览: 329166 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Tools.java

 
阅读更多
[size=x-large][size=large]
package com.ghca.policeintf;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Vector;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class Tools {

	public static String constant_encoding = "gbk";
	
	private static ThreadLocal threadLocal = new ThreadLocal();
	public static ThreadLocal getThreadLocal() {
		return threadLocal;
	}

	public static int unsignedByte(byte b)
	{
		return 0x000000ff & (int)b;
	}
	
	
	
	public static byte[] int2byteArr(int i) {
		ByteBuffer bb = ByteBuffer.allocate(4);
		bb.putInt(i);
		return bb.array();
	}
	
	public static byte[] short2byteArr(short i) {
		ByteBuffer bb = ByteBuffer.allocate(2);
		bb.putShort(i);
		return bb.array();
	}
	
	
	public static int byteArr2unsignedInt(byte[] arr) throws Exception {
		if(arr == null) {
			throw new Exception("byteArr2unsignedInt() find arr is null");
		}
		if(arr.length > 4 || arr.length <=0 ) {
			throw new Exception("byteArr2unsignedInt() find arr.length invalid:" + arr.length);
		}
		DataInputStream dis = new DataInputStream(new ByteArrayInputStream(arr));
		int r = -2000;
		if(arr.length == 1) {
			r = dis.readUnsignedByte();
		} else if(arr.length == 2) {
			r = dis.readUnsignedShort();
		} else if(arr.length == 3) {
			byte[] newarr = new byte[] {0x00,arr[0],arr[1],arr[2]};
			dis.close();
			dis = null;
			dis = new DataInputStream(new ByteArrayInputStream(newarr));
			r = dis.readInt();
		} else {
			r = dis.readInt();
		}
		dis.close();
		dis = null;
		if(r < 0) {
			throw new Exception("byteArr2unsignedInt() find int result < 0 : " + r);
		}
		return r;
	}
	
	
	public static void log(String log,Exception e) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sdf.format(new Date()) + " " + log);
		if(e != null) {
			e.printStackTrace(System.out);
		}
	}
	
	
	/**
	 * 检查ber编码是不定长、长定长还是短定长,并返回value的长度
	 * @param buf
	 * @param whatLen
	 * @throws Exception
	 */
	public static int checkBerLen(ByteBuffer buf,String whatLen) throws Exception {
		byte len = buf.get();
		
		//不定长方式这个字节固定是0x80
		//但是在java里面byte的0x80应该是-128,所以这里进行了一个无符号的转换,后续同理
		int  intLen = unsignedByte(len);
		if(intLen == 0x80) {
			throw new Exception(whatLen + " find len is 0x80:" + len);
		}
		
		if((intLen & 128) == 128) {//高位等于1->长定长
			Tools.log(whatLen + " find long fix len:" + len, null);
			//取出低7位查看后续有多少个字节的 len
			int nextLen = intLen & 127;
			if(nextLen > 2) {//后续的len超过2个字节,则认为错误
				throw new Exception(whatLen + " find next-len too long:" + len);
			} else {
				byte[] lenValueArr = new byte[nextLen];
				buf.get(lenValueArr, 0, nextLen);//执行这个之后,buf会向后移动nextLen个字节,指向value的开头
				int lenValue = byteArr2unsignedInt(lenValueArr);
				return lenValue;
			}
		} else if((intLen & 128) == 0) {//高位等于0 -> 短定长
			//取出低7位得到value的长度
			return intLen & 127;
		} else {
			throw new Exception(whatLen + " find neither long fix len nor short fix len:" + len);
		}
	}
	
	
	/**
	 * 检查该字节是否是context-specific,并返回context-specific的低5位的值, 从而对应文档
	 * @param buf
	 * @param what
	 * @return
	 * @throws Exception 
	 */
	public static int checkBerContextSpecific(ByteBuffer buf,String what) throws Exception {
		byte type = buf.get();
		int  intType = unsignedByte(type);
		
		if((intType & 192) != 128) {//取高两位看是不是 10 (context-specific)
			throw new Exception(what + " not context-specific:" + type);
		}
		
		//取低5位作为context-specific的值返回
		return (intType & 31);
	}
	
	
	public static byte[] md5(byte[] b) throws NoSuchAlgorithmException
	{
		byte[] val = null;
		MessageDigest md5 = MessageDigest.getInstance("md5");
		val = md5.digest(b);
		return val;
	}
	
	
	/**
	 * 比较两个byte数组是否相等
	 * @param a
	 * @param b
	 * @return
	 */
	public static boolean compareByteArr(byte[] a,byte[] b) {
		if(a.length != b.length) {
			return false;
		}
		for(int i = 0; i < a.length; i++) {
			if(a[i] != b[i]) {
				return false;
			}
		}
		return true;
	}
	
	
	
	public static byte[] encodeBer(byte tag,byte[] valueArr) throws Exception {
		if(valueArr.length <= 127) {//短定长
			ByteBuffer bb = ByteBuffer.allocate(1+1+valueArr.length);
			bb.order(ByteOrder.BIG_ENDIAN);
			bb.put(tag);
			bb.put((byte)valueArr.length);
			bb.put(valueArr);
			return bb.array();
		} else {//长定长
			if(valueArr.length <= 255) {//长定长--长度字段占两个字节
				ByteBuffer bb = ByteBuffer.allocate(1+2+valueArr.length);
				bb.order(ByteOrder.BIG_ENDIAN);
				bb.put(tag);
				bb.put((byte)0x81);//0x81:二进制高位为1(长定长),低7位值为1,代表后续有一个字节的len
				bb.put((byte)valueArr.length);//这个字节存放value的具体长度
				bb.put(valueArr);
				return bb.array();
			} else if(valueArr.length <= 65535) {//长定长--长度字段占三个字节
				ByteBuffer bb = ByteBuffer.allocate(1+3+valueArr.length);
				bb.order(ByteOrder.BIG_ENDIAN);
				bb.put(tag);
				bb.put((byte)0x82);//0x82:二进制高位为1(长定长),低7位值为2,代表后续有两个字节的len
				bb.putShort((short)valueArr.length);//这两个字节存放value的具体长度
				bb.put(valueArr);
				return bb.array();
			} else if(valueArr.length <= 16777215) {//长定长--长度字段占四个字节
				ByteBuffer bb = ByteBuffer.allocate(1+4+valueArr.length);
				bb.order(ByteOrder.BIG_ENDIAN);
				bb.put(tag);
				bb.put((byte)0x83);//0x83:二进制高位为1(长定长),低7位值为3,代表后续有三个字节的len
				//注意这里的实现
				//1.先将valueArr.length作为一个int值写入一个byte[]
				//2.然后获取到这个byte[]并将最高字节删除掉(其实最高字节就是0)放到另外一个byte[]中,则新的byte[]只剩下三个字节,就是长度值的三个字节
				//3.最后再将新的三个字节的byte[]填充到目标ByteBuffer里面去
				ByteBuffer tmpBuf = ByteBuffer.allocate(4);
				tmpBuf.putInt(valueArr.length);
				byte[] tmpByteArr = tmpBuf.array();
				byte[] inputLenArr = new byte[] {tmpByteArr[1],tmpByteArr[2],tmpByteArr[3]};
				bb.put(inputLenArr);
				bb.put(valueArr);
				return bb.array();
			} else {//长定长--长度字段超过4个字节,直接报错,因为此时的value值太大
				throw new Exception("encodeBer() find value.length too long:" + valueArr.length);
			}
		}
	}
	
	
	
	
	public static String toHex(byte[] v)
	{
		String vs = "";
		for(int i = 0; i < v.length - 1; i++)
		{
			vs += byteHEX(v[i]) + ",";
		}
		if(v.length >= 1)
			vs += byteHEX(v[v.length - 1]);
		return vs;
	}
	
	
	public static String byteHEX(byte ib) 
	{
		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
				'B', 'C', 'D', 'E', 'F' };
		char[] ob = new char[2];
		ob[0] = Digit[(ib >>> 4) & 0X0F];
		ob[1] = Digit[ib & 0X0F];
		String s = new String(ob);
		return "0x" + s;
	}
	
	
	
	/**
	 * 合并多个字节数组成为一个字节数组,多个字节数组存放在vector里面,按存入vector的顺序合并
	 * 即:先存入vector的合并之后在结果数组的前面
	 * @param v
	 * @return
	 * @throws Exception
	 */
	public static byte[] combineByteArr(Vector v) throws Exception {
		if(v == null || v.size() <= 0) {
			throw new Exception("combineByteArr() find vector is null or size() <= 0");
		}
		int totalLength = 0;
		for(int i = 0; i < v.size(); i++) {
			byte[] b = (byte[]) v.get(i);
			totalLength = totalLength + b.length;
		}
		byte[] resultArr = new byte[totalLength];
		int lastLen = 0;
		for(int i = 0; i < v.size(); i++) {
			byte[] tmpArr = (byte[]) v.get(i);
			System.arraycopy(tmpArr, 0, resultArr, lastLen, tmpArr.length);
			lastLen = lastLen + tmpArr.length;
		}
		return resultArr;
	}
	
	
	/**
	 * 3des加密算法
	 * @param keybyte
	 * @param src
	 * @return
	 * @throws Exception
	 */
	 public static byte[] encrypt3des(byte[] keybyte, byte[] src) throws Exception {
	    //生成密钥
		if(keybyte.length == 16) {//因为kc是16个字节,而java里面3des的key必须传入24个字节
			//根据3des算法,如果秘钥是16个字节,则后8个字节等于前8个字节,必须组成24个字节的秘钥
			byte[] b = new byte[24];
			System.arraycopy(keybyte, 0, b, 0, 16);
			System.arraycopy(keybyte, 0, b, 16, 8);
			keybyte = b;
		}
	    SecretKey deskey = new SecretKeySpec(keybyte,"DESede");
	    //加密
	    Cipher c1 = Cipher.getInstance("DESEDE/ECB/nopadding");
	    c1.init(Cipher.ENCRYPT_MODE, deskey);
	    
	    //因为采用nopadding加密填充算法,所以明文字节长度必须是8的倍数
	    //如果明文字节长度不是8的倍数,则在后面填补0xff(这是双方约定好的)
	    int mod = src.length % 8;
	    if(mod != 0) {//则需要填补(8-mod)个0xff
	    	int paddingLen = 8 - mod;
	    	byte[] paddingByte = new byte[paddingLen];
	    	for(int i = 0; i < paddingLen; i++) {
	    		paddingByte[i] = (byte) 0xff;
	    	}
	    	Vector v = new Vector();
	    	v.add(src);
	    	v.add(paddingByte);
	    	src = combineByteArr(v);
	    }
	    
	    return c1.doFinal(src);
	 }

	 
	 /**
	  * 3des解密算法
	  * @param keybyte
	  * @param src
	  * @return
	  * @throws Exception
	  */
     public static byte[] decrypt3des(byte[] keybyte, byte[] src) throws Exception {      
        //生成密钥
 		if(keybyte.length == 16) {//因为kc是16个字节,而java里面3des的key必须传入24个字节
 			//根据3des算法,如果秘钥是16个字节,则后8个字节等于前8个字节,必须组成24个字节的秘钥
 			byte[] b = new byte[24];
 			System.arraycopy(keybyte, 0, b, 0, 16);
 			System.arraycopy(keybyte, 0, b, 16, 8);
 			keybyte = b;
 		}
        SecretKey deskey = new SecretKeySpec(keybyte, "DESede");
        //解密
        Cipher c1 = Cipher.getInstance("DESEDE/ECB/nopadding");
        c1.init(Cipher.DECRYPT_MODE, deskey);
        return c1.doFinal(src);
     }
	
	
     /**
      * 接口的MD5算法,输入字节不够64个字节要用0xff补够64个字节
      * 传入的vector里面只需要存入有效的字节,该方法会自动补齐64个字节
      * @param v
      * @return
      * @throws Exception
      */
     @SuppressWarnings("unchecked")
	public static byte[] interfaceMd5(Vector v) throws Exception {
    	byte[] b = combineByteArr(v);
    	 
    	//协议上规定MD5输入如果不够64个字节则要用0xff补够64个字节
		int validLen = b.length;
		if(validLen < 64) {
			int paddingLen = 64 - validLen;
			byte[] paddingByte = new byte[paddingLen];
			for(int i = 0; i < paddingLen; i++) {
				paddingByte[i] = (byte) 0xff;
			}
			v.add(paddingByte);
		} else if(validLen == 64) {
			Tools.log("interfaceMd5() find validLen == 64,NoPadding", null);
		} else {
			throw new Exception("interfaceMd5() find validLen > 64");
		}
		
		b = combineByteArr(v);
		return md5(b);
		
     }
     
     
     private static Properties p = null;
     
     public static String getConfig(String configName) throws FileNotFoundException, IOException {
    	 if(p == null) {
    		 p = new Properties();
        	 p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties"));
    	 }
    	 return p.getProperty(configName);
     }
     
     
     public static byte[] ipToByteArr(String ip) {
    	 String[] arr = ip.split("\\.");
    	 int a = Integer.parseInt(arr[0]);
    	 int b = Integer.parseInt(arr[1]);
    	 int c = Integer.parseInt(arr[2]);
    	 int d = Integer.parseInt(arr[3]);
    	 
    	 byte[] r = new byte[] {(byte) a,(byte) b,(byte) c,(byte) d};
    	 return r;
     }
     
     
	
}
[/size][/size]
分享到:
评论

相关推荐

    Java8/java1.8的tools.jar

    《Java 8(Java 1.8)中的tools.jar详解》 在Java 8(也称为Java 1.8)的开发环境中,`tools.jar`是一个至关重要的组件,它是Java Development Kit (JDK)的一部分,包含了Java开发和运行时所需的工具类库。这个文件...

    SM4Tools.java

    SM4Tools.java

    Geotools Java API 开发gis的参考资料

    org.geotools org.geotools.arcsde org.geotools.arcsde.data org.geotools.arcsde.data.versioning org.geotools.arcsde.data.view org.geotools.arcsde.filter org.geotools.arcsde.gce org.geotools....

    maven项目所需的tools.jar文件

    maven项目里面pom文件所需的tools.java文件,百分之百管用,下载好直接复制到java安装目录下即可使用

    tools.jar(JDK1.6中的tools.jar)

    JDK1.6中的tools.jar //呵呵,今晚JCreator出错无数,检查了好久,才发现原来是我的tools.jar不见了,痛定思痛,决定将其收藏!

    JDK tools.jar

    JDK tools.jar

    tools.jar java上用到的包

    tools.jar java 上用到的包

    java的jdk7/jdk8通用tools.jar

    java的jdk7/jdk8通用tools.jar,解决maven项目打包或者启动报错时缺少启动jar包的问题。

    java1.8 tools.jar

    有时候装Java jdk的时候将jre与jdk的路径选择一致的时候,后出现覆盖,少这两个包,网上大多太旧且要积分,真扯蛋,这些人

    java8 tools.jar

    Java 8中的`tools.jar`是Java开发工具包(JDK)的重要组成部分,它包含了用于开发、编译、调试和管理Java应用程序的各种命令行工具的类库。这个库支持Java开发者执行诸如`javac`(Java编译器)、`javadoc`(文档生成...

    org.apache.tools.*需要的ant.jar包

    Apache Ant 是一个由Java编写的开源构建工具,它被广泛用于Java项目的构建、打包和部署。标题中的"org.apache.tools.*需要的ant.jar包"指的是Apache Ant的核心库,这个库包含了`org.apache.tools`包下的一系列类和...

    jdk1.6 tools.jar

    在JDK1.6版本中,一个重要的组成部分就是tools.jar,它是Java开发工具集的一部分,包含了Java编译器(javac)、Java文档生成器(javadoc)以及其他一些核心工具的类库。当JDK安装不完整或者配置出现问题时,可能会...

    jdk1.8下tools.jar(url)

    在JDK 8 (即jdk1.8)及之前版本中,`tools.jar`默认位于`&lt;JAVA_HOME&gt;/lib/tools.jar`路径下。从JDK 9开始,`tools.jar`被移除,其功能被集成到了`modules`中。 #### 解决“no compiler”错误 当遇到“No compiler ...

    AudioTools.java

    支持将两个PCM文件成一个PCM文件,解决语音群聊的时候技术难题。

    springBoot中pom需要的tools.jar

    springBoot的pom头部报tools.jar的错所需要的jar包 错误为Missing artifact com.sun:tools:jar:1.8.0

    org.apache.tools.zip解决解压乱码问题

    import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util....

    java压缩中文处理使用org.apache.tools.zip已经打包成jar

    &lt;%@ page language="java" import="java.sql.*,java.io.*,org.apache.tools.zip.Zip" pageEncoding="GBK"%&gt; out.println("正在备份网站..."); Zip zip=new Zip (); zip.zip(path, path+"/Sys/sys/backup/sql/...

    tools.jar jdk1.8

    《深入理解Java开发工具包:JDK1.8中的tools.jar》 在Java开发中,JDK(Java Development Kit)是不可或缺的一部分,它为开发者提供了编译、运行和调试Java程序所需的所有工具和库。在JDK1.8版本中,`tools.jar`是...

    JDK8.0(含tools.jar和dt.jar)

    新的Date和Time API也是JDK8的一大亮点,它提供了一套更强大、更易用的时间日期处理功能,替代了之前的java.util.Date和Calendar类。 总的来说,JDK8.0的发布对于Java开发者来说是一次重要的更新,它不仅提供了更...

Global site tag (gtag.js) - Google Analytics