[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]
分享到:
相关推荐
《Java 8(Java 1.8)中的tools.jar详解》 在Java 8(也称为Java 1.8)的开发环境中,`tools.jar`是一个至关重要的组件,它是Java Development Kit (JDK)的一部分,包含了Java开发和运行时所需的工具类库。这个文件...
SM4Tools.java
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项目里面pom文件所需的tools.java文件,百分之百管用,下载好直接复制到java安装目录下即可使用
JDK1.6中的tools.jar //呵呵,今晚JCreator出错无数,检查了好久,才发现原来是我的tools.jar不见了,痛定思痛,决定将其收藏!
JDK tools.jar
tools.jar java 上用到的包
java的jdk7/jdk8通用tools.jar,解决maven项目打包或者启动报错时缺少启动jar包的问题。
有时候装Java jdk的时候将jre与jdk的路径选择一致的时候,后出现覆盖,少这两个包,网上大多太旧且要积分,真扯蛋,这些人
Java 8中的`tools.jar`是Java开发工具包(JDK)的重要组成部分,它包含了用于开发、编译、调试和管理Java应用程序的各种命令行工具的类库。这个库支持Java开发者执行诸如`javac`(Java编译器)、`javadoc`(文档生成...
Apache Ant 是一个由Java编写的开源构建工具,它被广泛用于Java项目的构建、打包和部署。标题中的"org.apache.tools.*需要的ant.jar包"指的是Apache Ant的核心库,这个库包含了`org.apache.tools`包下的一系列类和...
在JDK1.6版本中,一个重要的组成部分就是tools.jar,它是Java开发工具集的一部分,包含了Java编译器(javac)、Java文档生成器(javadoc)以及其他一些核心工具的类库。当JDK安装不完整或者配置出现问题时,可能会...
在JDK 8 (即jdk1.8)及之前版本中,`tools.jar`默认位于`<JAVA_HOME>/lib/tools.jar`路径下。从JDK 9开始,`tools.jar`被移除,其功能被集成到了`modules`中。 #### 解决“no compiler”错误 当遇到“No compiler ...
支持将两个PCM文件成一个PCM文件,解决语音群聊的时候技术难题。
springBoot的pom头部报tools.jar的错所需要的jar包 错误为Missing artifact com.sun:tools:jar:1.8.0
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....
<%@ page language="java" import="java.sql.*,java.io.*,org.apache.tools.zip.Zip" pageEncoding="GBK"%> out.println("正在备份网站..."); Zip zip=new Zip (); zip.zip(path, path+"/Sys/sys/backup/sql/...
《深入理解Java开发工具包:JDK1.8中的tools.jar》 在Java开发中,JDK(Java Development Kit)是不可或缺的一部分,它为开发者提供了编译、运行和调试Java程序所需的所有工具和库。在JDK1.8版本中,`tools.jar`是...
新的Date和Time API也是JDK8的一大亮点,它提供了一套更强大、更易用的时间日期处理功能,替代了之前的java.util.Date和Calendar类。 总的来说,JDK8.0的发布对于Java开发者来说是一次重要的更新,它不仅提供了更...