| HELP.md | |||||
| target/ | |||||
| !.mvn/wrapper/maven-wrapper.jar | |||||
| !**/src/main/**/target/ | |||||
| !**/src/test/**/target/ | |||||
| ### STS ### | |||||
| .apt_generated | |||||
| .classpath | |||||
| .factorypath | |||||
| .project | |||||
| .settings | |||||
| .springBeans | |||||
| .sts4-cache | |||||
| ### IntelliJ IDEA ### | |||||
| .idea | |||||
| *.iws | |||||
| *.iml | |||||
| *.ipr | |||||
| ### NetBeans ### | |||||
| /nbproject/private/ | |||||
| /nbbuild/ | |||||
| /dist/ | |||||
| /nbdist/ | |||||
| /.nb-gradle/ | |||||
| build/ | |||||
| !**/src/main/**/build/ | |||||
| !**/src/test/**/build/ | |||||
| ### VS Code ### | |||||
| .vscode/ | |||||
| .DS_Store | |||||
| logs/ | |||||
| html/ | |||||
| .libs/ | |||||
| upload/ | |||||
| *.sh | |||||
| *.bat | |||||
| .lib/ |
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
| <modelVersion>4.0.0</modelVersion> | |||||
| <artifactId>utils-test</artifactId> | |||||
| <groupId>com.inet</groupId> | |||||
| <version>1.0</version> | |||||
| <packaging>jar</packaging> | |||||
| <name>utils-test</name> | |||||
| <url>http://maven.apache.org</url> | |||||
| <properties> | |||||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||||
| <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||||
| </properties> | |||||
| <dependencies> | |||||
| <dependency> | |||||
| <groupId>commons-lang</groupId> | |||||
| <artifactId>commons-lang</artifactId> | |||||
| <version>2.5</version> | |||||
| </dependency> | |||||
| </dependencies> | |||||
| <build> | |||||
| <plugins> | |||||
| <!-- compiler插件, 设定JDK版本 --> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>2.5.1</version> | |||||
| <configuration> | |||||
| <source>${jdk.version}</source> | |||||
| <target>${jdk.version}</target> | |||||
| <showWarnings>true</showWarnings> | |||||
| </configuration> | |||||
| </plugin> | |||||
| <plugin> | |||||
| <groupId>org.eclipse.m2e</groupId> | |||||
| <artifactId>lifecycle-mapping</artifactId> | |||||
| <version>1.0.0</version> | |||||
| <configuration> | |||||
| <lifecycleMappingMetadata> | |||||
| <pluginExecutions> | |||||
| <pluginExecution> | |||||
| <pluginExecutionFilter> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-enforcer-plugin</artifactId> | |||||
| <versionRange>[1.0.0,)</versionRange> | |||||
| <goals> | |||||
| <goal>enforce</goal> | |||||
| </goals> | |||||
| </pluginExecutionFilter> | |||||
| <action> | |||||
| <ignore /> | |||||
| </action> | |||||
| </pluginExecution> | |||||
| </pluginExecutions> | |||||
| </lifecycleMappingMetadata> | |||||
| </configuration> | |||||
| </plugin> | |||||
| <!-- enforcer插件, 设定环境与依赖的规则 --> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-enforcer-plugin</artifactId> | |||||
| <version>1.1.1</version> | |||||
| <executions> | |||||
| <execution> | |||||
| <id>enforce-banned-dependencies</id> | |||||
| <goals> | |||||
| <goal>enforce</goal> | |||||
| </goals> | |||||
| <configuration> | |||||
| <rules> | |||||
| <bannedDependencies> | |||||
| <searchTransitive>true</searchTransitive> | |||||
| <!-- 避免引入过期的jar包 --> | |||||
| <excludes> | |||||
| <!-- <exclude>commons-logging</exclude> --> | |||||
| <exclude>aspectj:aspectj*</exclude> | |||||
| <exclude>org.springframework:2.*</exclude> | |||||
| <exclude>org.springframework:3.0.*</exclude> | |||||
| </excludes> | |||||
| </bannedDependencies> | |||||
| </rules> | |||||
| <fail>true</fail> | |||||
| </configuration> | |||||
| </execution> | |||||
| </executions> | |||||
| </plugin> | |||||
| <!-- resource插件 --> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-resources-plugin</artifactId> | |||||
| <version>2.5</version> | |||||
| <configuration> | |||||
| <encoding>UTF-8</encoding> | |||||
| </configuration> | |||||
| </plugin> | |||||
| <!-- clean插件 --> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-clean-plugin</artifactId> | |||||
| <version>2.5</version> | |||||
| </plugin> | |||||
| <!-- ant插件 --> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-antrun-plugin</artifactId> | |||||
| <version>1.7</version> | |||||
| </plugin> | |||||
| <plugin> | |||||
| <groupId>org.codehaus.mojo</groupId> | |||||
| <artifactId>sonar-maven-plugin</artifactId> | |||||
| <version>2.0</version> | |||||
| </plugin> | |||||
| <!-- dependency插件 --> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-dependency-plugin</artifactId> | |||||
| <version>2.4</version> | |||||
| </plugin> | |||||
| <!-- 增加functional test的Source目录 --> | |||||
| <plugin> | |||||
| <groupId>org.codehaus.mojo</groupId> | |||||
| <artifactId>build-helper-maven-plugin</artifactId> | |||||
| <version>1.7</version> | |||||
| <executions> | |||||
| <execution> | |||||
| <id>add-functional-source</id> | |||||
| <phase>generate-sources</phase> | |||||
| <goals> | |||||
| <goal>add-test-source</goal> | |||||
| </goals> | |||||
| <configuration> | |||||
| <sources> | |||||
| <source>src/test/functional</source> | |||||
| </sources> | |||||
| </configuration> | |||||
| </execution> | |||||
| </executions> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </project> |
| package com.elinkthings.elink; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import com.elinkthings.elink.utils.Base64Util; | |||||
| import com.elinkthings.elink.utils.TeaUtils; | |||||
| public class Test { | |||||
| public static void main(String args[]) throws UnsupportedEncodingException | |||||
| { | |||||
| //设备注册数据 | |||||
| byte[] old =new byte[]{ | |||||
| (byte)0x0f,//imei长度 | |||||
| (byte)0x38,(byte)0x36,(byte)0x31,(byte)0x31,(byte)0x39 ,(byte)0x33 ,(byte)0x30 ,(byte)0x34 ,(byte)0x30 ,(byte)0x34 ,(byte)0x38 ,(byte)0x39 ,(byte)0x31 ,(byte)0x31 ,(byte)0x35, //IMEI | |||||
| (byte)0x0f, //IMSI长度 | |||||
| (byte)0x34,(byte)0x36 ,(byte)0x30 ,(byte)0x30 ,(byte)0x34 ,(byte)0x34 ,(byte)0x36 ,(byte)0x30 ,(byte)0x36 ,(byte)0x36 ,(byte)0x30 ,(byte)0x34 ,(byte)0x35 ,(byte)0x34 ,(byte)0x38, //IMSI长度 | |||||
| (byte)0x14, //ICCID长度 | |||||
| (byte)0x38,(byte)0x39 ,(byte)0x38 ,(byte)0x36 ,(byte)0x30 ,(byte)0x34 ,(byte)0x32 ,(byte)0x36 ,(byte)0x31 ,(byte)0x30 ,(byte)0x31 ,(byte)0x39 ,(byte)0x39 ,(byte)0x30 ,(byte)0x30 ,(byte)0x32 ,(byte)0x34 ,(byte)0x35 ,(byte)0x34 ,(byte)0x38, //ICCID | |||||
| (byte)0x13,//版本长度 | |||||
| (byte)0x4c ,(byte)0x4d ,(byte)0x30 ,(byte)0x31 ,(byte)0x48 ,(byte)0x31 ,(byte)0x53 ,(byte)0x31 ,(byte)0x2e ,(byte)0x30 ,(byte)0x5f ,(byte)0x32 ,(byte)0x30 ,(byte)0x32 ,(byte)0x30 ,(byte)0x30 ,(byte)0x36 ,(byte)0x33 ,(byte)0x30, //固件版本 | |||||
| (byte)0x00,(byte)0x00 ,(byte)0x00 ,(byte)0x00 ,(byte)0x00 ,(byte)0x00 ,(byte)0x00 | |||||
| }; | |||||
| //体脂数据 | |||||
| old =new byte[]{ | |||||
| (byte)0x00,(byte)0x00 ,(byte)0x0f,(byte)0x62 //设备ID | |||||
| ,(byte)0x13 //年 | |||||
| ,(byte)0x0c //月 | |||||
| ,(byte)0x12 //日 | |||||
| ,(byte)0x13 //时 | |||||
| ,(byte)0x0c //分 | |||||
| ,(byte)0x12 //秒 | |||||
| ,(byte)0x01 //是否离线记录 | |||||
| ,(byte)0x00 //体重数据高 | |||||
| ,(byte)0x00 //体重数据中 | |||||
| ,(byte)0x3C //体重数据低 | |||||
| ,(byte)0x00 //体重单位 | |||||
| ,(byte)0x00 //体重精度 | |||||
| ,(byte)0x01 //阻抗高 | |||||
| ,(byte)0xff //阻抗低 | |||||
| ,(byte)0x5f //心率 | |||||
| ,(byte)0x01 //算法 | |||||
| ,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00 //备用 | |||||
| }; | |||||
| //原始数据 | |||||
| System.out.println( "原始数据:"); | |||||
| for(byte i : old) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| //tea加密 | |||||
| byte[] teaDscrypt =TeaUtils.encrypt(old,null); | |||||
| System.out.println( "tea加密:"); | |||||
| for(byte i : teaDscrypt) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| //base编码 | |||||
| String base64Text = Base64Util.encoderString(teaDscrypt); | |||||
| System.out.println("base64编码后的数据长度:"+Base64Util.getLength(base64Text)+":"+base64Text); | |||||
| //base解码 | |||||
| String base64TextEn= Base64Util.decoderString(base64Text); | |||||
| System.out.println("base64解码后的数据长度:"+Base64Util.getLength(base64TextEn)+":"+base64TextEn); | |||||
| //解码数据转换为byte数组 | |||||
| byte[] base64TeaByteOld = Base64Util.hexStrToByteArray(base64TextEn); | |||||
| System.out.println( "解码后得到的tea加密的byte数组:"); | |||||
| for(byte i : base64TeaByteOld) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| byte[] base64TeaByte =TeaUtils.decrypt(base64TeaByteOld,null); | |||||
| System.out.println( "tea解密完成:"); | |||||
| for(byte i : base64TeaByte) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| } | |||||
| } |
| package com.elinkthings.elink.common; | |||||
| public class Common { | |||||
| /** | |||||
| * tea加密的密钥 | |||||
| */ | |||||
| public final static byte[] TEA_KEY = new byte[] { | |||||
| 0x00, 0x00, 0x00, 0x05, | |||||
| 0x00, 0x00, 0x00, 0x03, | |||||
| 0x00, 0x00, 0x00, 0x07, | |||||
| 0x00, 0x00, 0x00, 0x08 | |||||
| }; | |||||
| } |
| package com.elinkthings.elink.utils; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| public class Base64TeaUitls { | |||||
| //加密 | |||||
| public static String encryptForStr(String dataValue){ | |||||
| byte[] old = dataValue.getBytes(); | |||||
| String result = ""; | |||||
| try { | |||||
| //tea加密 | |||||
| byte[] teaDscrypt =TeaUtils.encrypt(old,null); | |||||
| //base编码 | |||||
| result= Base64Util.encoderString(teaDscrypt); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| return result; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| //加密 | |||||
| public static String encrypt(String dataValue){ | |||||
| byte[] old = BytesUtils.getBytes(Integer.parseInt(dataValue)); | |||||
| String result = ""; | |||||
| try { | |||||
| //tea加密 | |||||
| byte[] teaDscrypt =TeaUtils.encrypt(old,null); | |||||
| //base编码 | |||||
| result= Base64Util.encoderString(teaDscrypt); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| return result; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| //解密 | |||||
| public static byte[] decrypt(String base64Text){ | |||||
| //base解码 | |||||
| String base64TextEn; | |||||
| try { | |||||
| base64TextEn = Base64Util.decoderString(base64Text); | |||||
| //解码数据转换为byte数组 | |||||
| byte[] base64TeaByteOld = Base64Util.hexStrToByteArray(base64TextEn); | |||||
| //tea解密byte数组 | |||||
| byte[] base64TeaByte =TeaUtils.decrypt(base64TeaByteOld,null); | |||||
| //将负数转换为整数 | |||||
| /*if(base64TeaByte != null){ | |||||
| for(int i=0;i<base64TeaByte.length;i++){ | |||||
| if(base64TeaByte[i]<0){ | |||||
| base64TeaByte[i] = (byte) (256 + base64TeaByte[i]); | |||||
| } | |||||
| } | |||||
| }*/ | |||||
| return base64TeaByte; | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 十进制转16进制 | |||||
| * @param n | |||||
| * @return | |||||
| */ | |||||
| private static String intToHex(int n) { | |||||
| StringBuilder sb = new StringBuilder(8); | |||||
| String a; | |||||
| char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; | |||||
| if(n==0){ | |||||
| return 0+""; | |||||
| } | |||||
| while(n != 0){ | |||||
| if(n<0){ | |||||
| n= 256 +n; | |||||
| } | |||||
| sb = sb.append(b[n%16]); | |||||
| n = n/16; | |||||
| } | |||||
| a = sb.reverse().toString(); | |||||
| /*if(a.length() == 1){ | |||||
| a= "0"+a; | |||||
| }*/ | |||||
| return a; | |||||
| } | |||||
| /** | |||||
| * 获取开始下标到结束下标的16进制的值 | |||||
| * @param start | |||||
| * @param end | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String getStartToEndForHex(int start,int end,byte[] params){ | |||||
| String result = ""; | |||||
| for(int i=start;i<=end;i++){ | |||||
| if(i==end){ | |||||
| result = result+intToHex(params[i]); | |||||
| }else{ | |||||
| result = result+intToHex(params[i])+":"; | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 获取开始下标到结束下标的ASIII对应的值 | |||||
| * @param start | |||||
| * @param end | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String getStartToEndForASIII(int start,int end,byte[] params){ | |||||
| String result = ""; | |||||
| for(int i=start;i<=end;i++){ | |||||
| if(i==end){ | |||||
| result = result+asciiToString(params[i]+""); | |||||
| }else{ | |||||
| result = result+asciiToString(params[i]+"")+":"; | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * ASCII转字符 | |||||
| * @param value | |||||
| * @return | |||||
| */ | |||||
| public static String asciiToString(String value) | |||||
| { | |||||
| value = value.replaceAll(":", ""); | |||||
| char c= (char) Integer.parseInt(value); | |||||
| //System.out.println(value+":"+c); | |||||
| return c+""; | |||||
| } | |||||
| /** | |||||
| * 获取开始下标到结束下标的10进制的值 | |||||
| * @param start | |||||
| * @param end | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String getStartToEndForInt(int start,int end,byte[] params){ | |||||
| String result = ""; | |||||
| for(int i=start;i<=end;i++){ | |||||
| int temp = params[i]; | |||||
| if(temp < 0){ | |||||
| temp = 256 + temp; | |||||
| } | |||||
| if(i==end){ | |||||
| result = result+temp; | |||||
| }else{ | |||||
| result = result+temp+":"; | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 获取低位到高位的移位+或运算的值 | |||||
| * @param indexLow | |||||
| * @param indexHigh | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| public static String getLowConactHighEndForInt(int indexLow,int indexHigh,byte[] params){ | |||||
| String result = ""; | |||||
| int tempResult = 0; | |||||
| for(int i = indexLow;i<=indexHigh;i++){ | |||||
| int temp = (params[i] < 0 ? 256 + params[i] : params[i]); | |||||
| int tempmov = (indexHigh-i)+2; | |||||
| tempmov = (i == indexHigh ? 0 : (int) Math.pow(2, tempmov)); | |||||
| tempResult = (temp << tempmov) | tempResult; | |||||
| } | |||||
| return result+tempResult; | |||||
| } | |||||
| } |
| package com.elinkthings.elink.utils; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.util.Base64; | |||||
| public class Base64Util | |||||
| { | |||||
| final static Base64.Decoder decoder = Base64.getDecoder(); | |||||
| final static Base64.Encoder encoder = Base64.getEncoder(); | |||||
| public Base64Util(){} | |||||
| /** | |||||
| * 解码 | |||||
| * @param encoderStr | |||||
| * @return | |||||
| * @throws UnsupportedEncodingException | |||||
| */ | |||||
| public static String decoderString(String base64Text) throws UnsupportedEncodingException{ | |||||
| String result = ""; | |||||
| if(base64Text != null && !base64Text.isEmpty() && !base64Text.equals("")){ | |||||
| byte[] textByte = decoder.decode(base64Text); | |||||
| result = bytes_String16(textByte); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * byte[]转16进制字符串 | |||||
| * @param b | |||||
| * @return | |||||
| */ | |||||
| public static String bytes_String16(byte[] b) { | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| for(int i=0;i<b.length;i++) { | |||||
| sb.append(String.format("%02x", b[i])); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| /** | |||||
| * 编码 | |||||
| * @param encoderStr | |||||
| * @return | |||||
| * @throws UnsupportedEncodingException | |||||
| */ | |||||
| public static String encoderString(String base64Text) throws UnsupportedEncodingException{ | |||||
| String result = ""; | |||||
| if(base64Text != null && !base64Text.isEmpty() && !base64Text.equals("")){ | |||||
| byte[] textByte = base64Text.getBytes("UTF-8"); | |||||
| result = encoder.encodeToString(textByte); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 编码 | |||||
| * @param encoderStr | |||||
| * @return | |||||
| * @throws UnsupportedEncodingException | |||||
| */ | |||||
| public static String encoderString(byte[] textByte) throws UnsupportedEncodingException{ | |||||
| return encoder.encodeToString(textByte); | |||||
| } | |||||
| public static int getLength(String s) { | |||||
| int length = 0; | |||||
| for (int i = 0; i < s.length(); i++) { | |||||
| int ascii = Character.codePointAt(s, i); | |||||
| if (ascii >= 0 && ascii <= 255) { | |||||
| length++; | |||||
| } else { | |||||
| length += 2; | |||||
| } | |||||
| } | |||||
| return length; | |||||
| } | |||||
| private static String intToHex(int n) { | |||||
| StringBuffer s = new StringBuffer(); | |||||
| String a; | |||||
| char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; | |||||
| while(n != 0){ | |||||
| s = s.append(b[n%16]); | |||||
| n = n/16; | |||||
| } | |||||
| a = s.reverse().toString(); | |||||
| return a; | |||||
| } | |||||
| public static byte[] hexStrToByteArray(String str) | |||||
| { | |||||
| if (str == null) { | |||||
| return null; | |||||
| } | |||||
| if (str.length() == 0) { | |||||
| return new byte[0]; | |||||
| } | |||||
| byte[] byteArray = new byte[str.length() / 2]; | |||||
| for (int i = 0; i < byteArray.length; i++){ | |||||
| String subStr = str.substring(2 * i, 2 * i + 2); | |||||
| byteArray[i] = ((byte)Integer.parseInt(subStr, 16)); | |||||
| } | |||||
| return byteArray; | |||||
| } | |||||
| public static void main(String args[]) throws UnsupportedEncodingException | |||||
| { | |||||
| //01 01 16 b7 28 32 18 4a 88 00 0e 00 00 00 00 42 4d 10 01 0a 00 13 05 07 e9 | |||||
| byte[] old =new byte[]{(byte)0x01 | |||||
| ,(byte)0x01 ,(byte)0x16 ,(byte)0xb7 ,(byte)0x28 | |||||
| ,(byte)0x32 ,(byte)0x18 ,(byte)0x4a ,(byte)0x88 | |||||
| ,(byte)0x00 ,(byte)0x0e ,(byte)0x00 ,(byte)0x00 | |||||
| ,(byte)0x00 ,(byte)0x00 ,(byte)0x42 ,(byte)0x4d | |||||
| ,(byte)0x10 ,(byte)0x01 ,(byte)0x0a ,(byte)0x00 | |||||
| ,(byte)0x13 ,(byte)0x05 ,(byte)0x07 ,(byte)0xe9}; | |||||
| //原始数据 | |||||
| System.out.println( "原始数据:"); | |||||
| for(byte i : old) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| //tea加密 | |||||
| byte[] teaDscrypt =TeaUtils.encrypt(old,null); | |||||
| System.out.println( "tea加密:"); | |||||
| for(byte i : teaDscrypt) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| //base编码 | |||||
| String base64Text = encoderString(teaDscrypt); | |||||
| System.out.println("base64编码后的数据长度:"+getLength(base64Text)+":"+base64Text); | |||||
| //base解码 | |||||
| String base64TextEn= decoderString(base64Text); | |||||
| System.out.println("base64解码后的数据长度:"+getLength(base64TextEn)+":"+base64TextEn); | |||||
| /*//转称byte数组(每两位一个16进制byte) | |||||
| List<String> base64TeaByteOldList = new ArrayList<String>(); | |||||
| for(int i=0;i<base64TextEn.length();i++){ | |||||
| if(i%2 == 0){ | |||||
| base64TeaByteOldList.add("0x"+base64TextEn.charAt(i)+base64TextEn.charAt(i+1)); | |||||
| } | |||||
| } | |||||
| //解码后转换得到的list | |||||
| System.out.println("解码后转换得到的list:"); | |||||
| for(String byte16:base64TeaByteOldList){ | |||||
| System.out.print(byte16+" "); | |||||
| } | |||||
| System.out.println();*/ | |||||
| //解码数据转换为byte数组 | |||||
| byte[] base64TeaByteOld = hexStrToByteArray(base64TextEn); | |||||
| System.out.println( "解码后得到的tea加密的byte数组:"); | |||||
| for(byte i : base64TeaByteOld) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| byte[] base64TeaByte =TeaUtils.decrypt(base64TeaByteOld,null); | |||||
| System.out.println( "tea解密:"); | |||||
| for(byte i : base64TeaByte) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| } | |||||
| } |
| package com.elinkthings.elink.utils; | |||||
| import java.nio.charset.Charset; | |||||
| import org.apache.commons.lang.ArrayUtils; | |||||
| /** | |||||
| * | |||||
| * @Description: 字节数组转换工具类 | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public class BytesUtils { | |||||
| public static final String GBK = "GBK"; | |||||
| public static final String UTF8 = "utf-8"; | |||||
| public static final char[] ascii = "0123456789ABCDEF".toCharArray(); | |||||
| private static char[] HEX_VOCABLE = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | |||||
| /** | |||||
| * 将short整型数值转换为字节数组 | |||||
| * | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static byte[] getBytes(short data) { | |||||
| byte[] bytes = new byte[2]; | |||||
| bytes[0] = (byte) ((data & 0xff00) >> 8); | |||||
| bytes[1] = (byte) (data & 0xff); | |||||
| return bytes; | |||||
| } | |||||
| /** | |||||
| * 将字符转换为字节数组 | |||||
| * | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static byte[] getBytes(char data) { | |||||
| byte[] bytes = new byte[2]; | |||||
| bytes[0] = (byte) (data >> 8); | |||||
| bytes[1] = (byte) (data); | |||||
| return bytes; | |||||
| } | |||||
| /** | |||||
| * 将布尔值转换为字节数组 | |||||
| * | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static byte[] getBytes(boolean data) { | |||||
| byte[] bytes = new byte[1]; | |||||
| bytes[0] = (byte) (data ? 1 : 0); | |||||
| return bytes; | |||||
| } | |||||
| /** | |||||
| * 将整型数值转换为字节数组 | |||||
| * | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static byte[] getBytes(int data) { | |||||
| byte[] bytes = new byte[4]; | |||||
| bytes[0] = (byte) ((data & 0xff000000) >> 24); | |||||
| bytes[1] = (byte) ((data & 0xff0000) >> 16); | |||||
| bytes[2] = (byte) ((data & 0xff00) >> 8); | |||||
| bytes[3] = (byte) (data & 0xff); | |||||
| return bytes; | |||||
| } | |||||
| /** | |||||
| * 将long整型数值转换为字节数组 | |||||
| * | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static byte[] getBytes(long data) { | |||||
| byte[] bytes = new byte[8]; | |||||
| bytes[0] = (byte) ((data >> 56) & 0xff); | |||||
| bytes[1] = (byte) ((data >> 48) & 0xff); | |||||
| bytes[2] = (byte) ((data >> 40) & 0xff); | |||||
| bytes[3] = (byte) ((data >> 32) & 0xff); | |||||
| bytes[4] = (byte) ((data >> 24) & 0xff); | |||||
| bytes[5] = (byte) ((data >> 16) & 0xff); | |||||
| bytes[6] = (byte) ((data >> 8) & 0xff); | |||||
| bytes[7] = (byte) (data & 0xff); | |||||
| return bytes; | |||||
| } | |||||
| /** | |||||
| * 将float型数值转换为字节数组 | |||||
| * | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static byte[] getBytes(float data) { | |||||
| int intBits = Float.floatToIntBits(data); | |||||
| return getBytes(intBits); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getBytes | |||||
| * @Description: 将double型数值转换为字节数组 | |||||
| * @return byte[] | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static byte[] getBytes(double data) { | |||||
| long intBits = Double.doubleToLongBits(data); | |||||
| return getBytes(intBits); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getBytes | |||||
| * @Description: 将字符串按照charsetName编码格式的字节数组 | |||||
| * @return byte[] | |||||
| * @param data 字符串 | |||||
| * @param charsetName | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static byte[] getBytes(String data, String charsetName) { | |||||
| Charset charset = Charset.forName(charsetName); | |||||
| return data.getBytes(charset); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getBytes | |||||
| * @Description: 将字符串按照GBK编码格式的字节数组 | |||||
| * @return byte[] | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static byte[] getBytes(String data) { | |||||
| return getBytes(data, GBK); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getBoolean | |||||
| * @Description: 将字节数组第0字节转换为布尔值 | |||||
| * @return boolean | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static boolean getBoolean(byte[] bytes) { | |||||
| return bytes[0] == 1; | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getBoolean | |||||
| * @Description: 将字节数组的第index字节转换为布尔值 | |||||
| * @return boolean | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static boolean getBoolean(byte[] bytes, int index) { | |||||
| return bytes[index] == 1; | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getShort | |||||
| * @Description: 将字节数组前2字节转换为short整型数值 | |||||
| * @return short | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static short getShort(byte[] bytes) { | |||||
| return (short) ((0xff00 & (bytes[0] << 8)) | (0xff & bytes[1])); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getShort | |||||
| * @Description: 将字节数组从startIndex开始的2个字节转换为short整型数值 | |||||
| * @return short | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static short getShort(byte[] bytes, int startIndex) { | |||||
| return (short) ((0xff00 & (bytes[startIndex] << 8)) | (0xff & bytes[startIndex + 1])); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getChar | |||||
| * @Description: 将字节数组前2字节转换为字符 | |||||
| * @return char | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static char getChar(byte[] bytes) { | |||||
| return (char) ((0xff00 & (bytes[0] << 8)) | (0xff & bytes[1])); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getChar | |||||
| * @Description: 将字节数组从startIndex开始的2个字节转换为字符 | |||||
| * @return char | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static char getChar(byte[] bytes, int startIndex) { | |||||
| return (char) ((0xff00 & (bytes[startIndex] << 8)) | (0xff & bytes[startIndex + 1])); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getInt | |||||
| * @Description: 将字节数组前4字节转换为整型数值 | |||||
| * @return int | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static int getInt(byte[] bytes) { | |||||
| return (0xff000000 & (bytes[0] << 24) | (0xff0000 & (bytes[1] << 16)) | (0xff00 & (bytes[2] << 8)) | |||||
| | (0xff & bytes[3])); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: getInt | |||||
| * @Description: 将字节数组从startIndex开始的4个字节转换为整型数值 | |||||
| * @return int | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static int getInt(byte[] bytes, int startIndex) { | |||||
| return (0xff000000 & (bytes[startIndex] << 24) | (0xff0000 & (bytes[startIndex + 1] << 16)) | |||||
| | (0xff00 & (bytes[startIndex + 2] << 8)) | (0xff & bytes[startIndex + 3])); | |||||
| } | |||||
| /** | |||||
| * 将字节数组前8字节转换为long整型数值 | |||||
| * | |||||
| * @param bytes | |||||
| * @return | |||||
| */ | |||||
| public static long getLong(byte[] bytes) { | |||||
| return (0xff00000000000000L & ((long) bytes[0] << 56) | (0xff000000000000L & ((long) bytes[1] << 48)) | |||||
| | (0xff0000000000L & ((long) bytes[2] << 40)) | (0xff00000000L & ((long) bytes[3] << 32)) | |||||
| | (0xff000000L & ((long) bytes[4] << 24)) | (0xff0000L & ((long) bytes[5] << 16)) | |||||
| | (0xff00L & ((long) bytes[6] << 8)) | (0xffL & (long) bytes[7])); | |||||
| } | |||||
| /** | |||||
| * 将字节数组从startIndex开始的8个字节转换为long整型数值 | |||||
| * | |||||
| * @param bytes | |||||
| * @param startIndex | |||||
| * @return | |||||
| */ | |||||
| public static long getLong(byte[] bytes, int startIndex) { | |||||
| return (0xff00000000000000L & ((long) bytes[startIndex] << 56) | |||||
| | (0xff000000000000L & ((long) bytes[startIndex + 1] << 48)) | |||||
| | (0xff0000000000L & ((long) bytes[startIndex + 2] << 40)) | |||||
| | (0xff00000000L & ((long) bytes[startIndex + 3] << 32)) | |||||
| | (0xff000000L & ((long) bytes[startIndex + 4] << 24)) | |||||
| | (0xff0000L & ((long) bytes[startIndex + 5] << 16)) | (0xff00L & ((long) bytes[startIndex + 6] << 8)) | |||||
| | (0xffL & (long) bytes[startIndex + 7])); | |||||
| } | |||||
| /** | |||||
| * 将字节数组前4字节转换为float型数值 | |||||
| * | |||||
| * @param bytes | |||||
| * @return | |||||
| */ | |||||
| public static float getFloat(byte[] bytes) { | |||||
| return Float.intBitsToFloat(getInt(bytes)); | |||||
| } | |||||
| /** | |||||
| * 将字节数组从startIndex开始的4个字节转换为float型数值 | |||||
| * | |||||
| * @param bytes | |||||
| * @param startIndex | |||||
| * @return | |||||
| */ | |||||
| public static float getFloat(byte[] bytes, int startIndex) { | |||||
| byte[] result = new byte[4]; | |||||
| System.arraycopy(bytes, startIndex, result, 0, 4); | |||||
| return Float.intBitsToFloat(getInt(result)); | |||||
| } | |||||
| /** | |||||
| * 将字节数组前8字节转换为double型数值 | |||||
| * | |||||
| * @param bytes | |||||
| * @return | |||||
| */ | |||||
| public static double getDouble(byte[] bytes) { | |||||
| long l = getLong(bytes); | |||||
| return Double.longBitsToDouble(l); | |||||
| } | |||||
| /** | |||||
| * 将字节数组从startIndex开始的8个字节转换为double型数值 | |||||
| * | |||||
| * @param bytes | |||||
| * @param startIndex | |||||
| * @return | |||||
| */ | |||||
| public static double getDouble(byte[] bytes, int startIndex) { | |||||
| byte[] result = new byte[8]; | |||||
| System.arraycopy(bytes, startIndex, result, 0, 8); | |||||
| long l = getLong(result); | |||||
| return Double.longBitsToDouble(l); | |||||
| } | |||||
| /** | |||||
| * 将charsetName编码格式的字节数组转换为字符串 | |||||
| * | |||||
| * @param bytes | |||||
| * @param charsetName | |||||
| * @return | |||||
| */ | |||||
| public static String getString(byte[] bytes, String charsetName) { | |||||
| return new String(bytes, Charset.forName(charsetName)); | |||||
| } | |||||
| /** | |||||
| * 将GBK编码格式的字节数组转换为字符串 | |||||
| * | |||||
| * @param bytes | |||||
| * @return | |||||
| */ | |||||
| public static String getString(byte[] bytes) { | |||||
| return getString(bytes, GBK); | |||||
| } | |||||
| /** | |||||
| * 将16进制字符串转换为字节数组 | |||||
| * | |||||
| * @param hex | |||||
| * @return | |||||
| */ | |||||
| public static byte[] hexStringToBytes(String hex) { | |||||
| if (hex == null || "".equals(hex)) { | |||||
| return null; | |||||
| } | |||||
| int len = hex.length() / 2; | |||||
| byte[] result = new byte[len]; | |||||
| char[] chArr = hex.toCharArray(); | |||||
| for (int i = 0; i < len; i++) { | |||||
| int pos = i * 2; | |||||
| result[i] = (byte) (toByte(chArr[pos]) << 4 | toByte(chArr[pos + 1])); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 将16进制字符串转换为字节数组 | |||||
| * | |||||
| * @param hex | |||||
| * @return | |||||
| */ | |||||
| public static byte[] hexToBytes(String hex) { | |||||
| if (hex.length() % 2 != 0) | |||||
| throw new IllegalArgumentException("input string should be any multiple of 2!"); | |||||
| hex.toUpperCase(); | |||||
| byte[] byteBuffer = new byte[hex.length() / 2]; | |||||
| byte padding = 0x00; | |||||
| boolean paddingTurning = false; | |||||
| for (int i = 0; i < hex.length(); i++) { | |||||
| if (paddingTurning) { | |||||
| char c = hex.charAt(i); | |||||
| int index = indexOf(hex, c); | |||||
| padding = (byte) ((padding << 4) | index); | |||||
| byteBuffer[i / 2] = padding; | |||||
| padding = 0x00; | |||||
| paddingTurning = false; | |||||
| } else { | |||||
| char c = hex.charAt(i); | |||||
| int index = indexOf(hex, c); | |||||
| padding = (byte) (padding | index); | |||||
| paddingTurning = true; | |||||
| } | |||||
| } | |||||
| return byteBuffer; | |||||
| } | |||||
| private static int indexOf(String input, char c) { | |||||
| int index = ArrayUtils.indexOf(HEX_VOCABLE, c); | |||||
| if (index < 0) { | |||||
| throw new IllegalArgumentException("err input:" + input); | |||||
| } | |||||
| return index; | |||||
| } | |||||
| /** | |||||
| * 将BCD编码的字节数组转换为字符串 | |||||
| * | |||||
| * @param bcds | |||||
| * @return | |||||
| */ | |||||
| public static String bcdToString(byte[] bcds) { | |||||
| if (bcds == null || bcds.length == 0) { | |||||
| return null; | |||||
| } | |||||
| byte[] temp = new byte[2 * bcds.length]; | |||||
| for (int i = 0; i < bcds.length; i++) { | |||||
| temp[i * 2] = (byte) ((bcds[i] >> 4) & 0x0f); | |||||
| temp[i * 2 + 1] = (byte) (bcds[i] & 0x0f); | |||||
| } | |||||
| StringBuffer res = new StringBuffer(); | |||||
| for (int i = 0; i < temp.length; i++) { | |||||
| res.append(ascii[temp[i]]); | |||||
| } | |||||
| return res.toString(); | |||||
| } | |||||
| /** | |||||
| * 字节转整形 | |||||
| * | |||||
| * @param value | |||||
| * @return | |||||
| */ | |||||
| public static int bcdToInt(byte value) { | |||||
| return ((value >> 4) * 10) + (value & 0x0F); | |||||
| } | |||||
| /** | |||||
| * 字节数组转16进制字符串 | |||||
| * | |||||
| * @param bs | |||||
| * @return | |||||
| */ | |||||
| public static String bytesToHex(byte[] bs) { | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| for (byte b : bs) { | |||||
| int high = (b >> 4) & 0x0f; | |||||
| int low = b & 0x0f; | |||||
| sb.append(HEX_VOCABLE[high]); | |||||
| sb.append(HEX_VOCABLE[low]); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| /** | |||||
| * 字节数组取前len个字节转16进制字符串 | |||||
| * | |||||
| * @param bs | |||||
| * @param len | |||||
| * @return | |||||
| */ | |||||
| public static String bytesToHex(byte[] bs, int len) { | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| for (int i = 0; i < len; i++) { | |||||
| byte b = bs[i]; | |||||
| int high = (b >> 4) & 0x0f; | |||||
| int low = b & 0x0f; | |||||
| sb.append(HEX_VOCABLE[high]); | |||||
| sb.append(HEX_VOCABLE[low]); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| /** | |||||
| * 字节数组偏移offset长度之后的取len个字节转16进制字符串 | |||||
| * | |||||
| * @param bs | |||||
| * @param offset | |||||
| * @param len | |||||
| * @return | |||||
| */ | |||||
| public static String bytesToHex(byte[] bs, int offset, int len) { | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| for (int i = 0; i < len; i++) { | |||||
| byte b = bs[offset + i]; | |||||
| int high = (b >> 4) & 0x0f; | |||||
| int low = b & 0x0f; | |||||
| sb.append(HEX_VOCABLE[high]); | |||||
| sb.append(HEX_VOCABLE[low]); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| /** | |||||
| * 字节转16进制字符串 | |||||
| * | |||||
| * @param bs | |||||
| * @return | |||||
| */ | |||||
| public static String byteToHex(byte b) { | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| int high = (b >> 4) & 0x0f; | |||||
| int low = b & 0x0f; | |||||
| sb.append(HEX_VOCABLE[high]); | |||||
| sb.append(HEX_VOCABLE[low]); | |||||
| String s = sb.toString(); | |||||
| if ("".equals(s.substring(0, 1))) { | |||||
| return s.substring(1); | |||||
| } else { | |||||
| return s; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 将字节数组取反 | |||||
| * | |||||
| * @param src | |||||
| * @return | |||||
| */ | |||||
| public static String negate(byte[] src) { | |||||
| if (src == null || src.length == 0) { | |||||
| return null; | |||||
| } | |||||
| byte[] temp = new byte[2 * src.length]; | |||||
| for (int i = 0; i < src.length; i++) { | |||||
| byte tmp = (byte) (0xFF ^ src[i]); | |||||
| temp[i * 2] = (byte) ((tmp >> 4) & 0x0f); | |||||
| temp[i * 2 + 1] = (byte) (tmp & 0x0f); | |||||
| } | |||||
| StringBuffer res = new StringBuffer(); | |||||
| for (int i = 0; i < temp.length; i++) { | |||||
| res.append(ascii[temp[i]]); | |||||
| } | |||||
| return res.toString(); | |||||
| } | |||||
| /** | |||||
| * 比较字节数组是否相同 | |||||
| * | |||||
| * @param a | |||||
| * @param b | |||||
| * @return | |||||
| */ | |||||
| public static boolean compareBytes(byte[] a, byte[] b) { | |||||
| if (a == null || a.length == 0 || b == null || b.length == 0 || a.length != b.length) { | |||||
| return false; | |||||
| } | |||||
| if (a.length == b.length) { | |||||
| for (int i = 0; i < a.length; i++) { | |||||
| if (a[i] != b[i]) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } else { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * 只比对指定长度byte | |||||
| * | |||||
| * @param a | |||||
| * @param b | |||||
| * @param len | |||||
| * @return | |||||
| */ | |||||
| public static boolean compareBytes(byte[] a, byte[] b, int len) { | |||||
| if (a == null || a.length == 0 || b == null || b.length == 0 || a.length < len || b.length < len) { | |||||
| return false; | |||||
| } | |||||
| for (int i = 0; i < len; i++) { | |||||
| if (a[i] != b[i]) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * 将字节数组转换为二进制字符串 | |||||
| * | |||||
| * @param items | |||||
| * @return | |||||
| */ | |||||
| public static String bytesToBinaryString(byte[] items) { | |||||
| if (items == null || items.length == 0) { | |||||
| return null; | |||||
| } | |||||
| StringBuffer buf = new StringBuffer(); | |||||
| for (byte item : items) { | |||||
| buf.append(byteToBinaryString(item)); | |||||
| } | |||||
| return buf.toString(); | |||||
| } | |||||
| /** | |||||
| * 将字节转换为二进制字符串 | |||||
| * | |||||
| * @param items | |||||
| * @return | |||||
| */ | |||||
| public static String byteToBinaryString(byte item) { | |||||
| byte a = item; | |||||
| StringBuffer buf = new StringBuffer(); | |||||
| for (int i = 0; i < 8; i++) { | |||||
| buf.insert(0, a % 2); | |||||
| a = (byte) (a >> 1); | |||||
| } | |||||
| return buf.toString(); | |||||
| } | |||||
| /** | |||||
| * 对数组a,b进行异或运算 | |||||
| * | |||||
| * @param a | |||||
| * @param b | |||||
| * @return | |||||
| */ | |||||
| public static byte[] xor(byte[] a, byte[] b) { | |||||
| if (a == null || a.length == 0 || b == null || b.length == 0 || a.length != b.length) { | |||||
| return null; | |||||
| } | |||||
| byte[] result = new byte[a.length]; | |||||
| for (int i = 0; i < a.length; i++) { | |||||
| result[i] = (byte) (a[i] ^ b[i]); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 对数组a,b进行异或运算 运算长度len | |||||
| * | |||||
| * @param a | |||||
| * @param b | |||||
| * @param len | |||||
| * @return | |||||
| */ | |||||
| public static byte[] xor(byte[] a, byte[] b, int len) { | |||||
| if (a == null || a.length == 0 || b == null || b.length == 0) { | |||||
| return null; | |||||
| } | |||||
| if (a.length < len || b.length < len) { | |||||
| return null; | |||||
| } | |||||
| byte[] result = new byte[len]; | |||||
| for (int i = 0; i < len; i++) { | |||||
| result[i] = (byte) (a[i] ^ b[i]); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 将short整型数值转换为字节数组 | |||||
| * | |||||
| * @param num | |||||
| * @return | |||||
| */ | |||||
| public static byte[] shortToBytes(int num) { | |||||
| byte[] temp = new byte[2]; | |||||
| for (int i = 0; i < 2; i++) { | |||||
| temp[i] = (byte) ((num >>> (8 - i * 8)) & 0xFF); | |||||
| } | |||||
| return temp; | |||||
| } | |||||
| /** | |||||
| * 将字节数组转为整型 | |||||
| * | |||||
| * @param num | |||||
| * @return | |||||
| */ | |||||
| public static int bytesToShort(byte[] arr) { | |||||
| int mask = 0xFF; | |||||
| int temp = 0; | |||||
| int result = 0; | |||||
| for (int i = 0; i < 2; i++) { | |||||
| result <<= 8; | |||||
| temp = arr[i] & mask; | |||||
| result |= temp; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 将整型数值转换为指定长度的字节数组 | |||||
| * | |||||
| * @param num | |||||
| * @return | |||||
| */ | |||||
| public static byte[] intToBytes(int num) { | |||||
| byte[] temp = new byte[4]; | |||||
| for (int i = 0; i < 4; i++) { | |||||
| temp[i] = (byte) ((num >>> (24 - i * 8)) & 0xFF); | |||||
| } | |||||
| return temp; | |||||
| } | |||||
| /** | |||||
| * 将整型数值转换为指定长度的字节数组 | |||||
| * | |||||
| * @param src | |||||
| * @param len | |||||
| * @return | |||||
| */ | |||||
| public static byte[] intToBytes(int src, int len) { | |||||
| if (len < 1 || len > 4) { | |||||
| return null; | |||||
| } | |||||
| byte[] temp = new byte[len]; | |||||
| for (int i = 0; i < len; i++) { | |||||
| temp[len - 1 - i] = (byte) ((src >>> (8 * i)) & 0xFF); | |||||
| } | |||||
| return temp; | |||||
| } | |||||
| /** | |||||
| * 将字节数组转换为整型数值 | |||||
| * | |||||
| * @param arr | |||||
| * @return | |||||
| */ | |||||
| public static int bytesToInt(byte[] arr) { | |||||
| int mask = 0xFF; | |||||
| int temp = 0; | |||||
| int result = 0; | |||||
| for (int i = 0; i < 4; i++) { | |||||
| result <<= 8; | |||||
| temp = arr[i] & mask; | |||||
| result |= temp; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 将long整型数值转换为字节数组 | |||||
| * | |||||
| * @param num | |||||
| * @return | |||||
| */ | |||||
| public static byte[] longToBytes(long num) { | |||||
| byte[] temp = new byte[8]; | |||||
| for (int i = 0; i < 8; i++) { | |||||
| temp[i] = (byte) ((num >>> (56 - i * 8)) & 0xFF); | |||||
| } | |||||
| return temp; | |||||
| } | |||||
| /** | |||||
| * 将字节数组转换为long整型数值 | |||||
| * | |||||
| * @param arr | |||||
| * @return | |||||
| */ | |||||
| public static long bytesToLong(byte[] arr) { | |||||
| int mask = 0xFF; | |||||
| int temp = 0; | |||||
| long result = 0; | |||||
| int len = Math.min(8, arr.length); | |||||
| for (int i = 0; i < len; i++) { | |||||
| result <<= 8; | |||||
| temp = arr[i] & mask; | |||||
| result |= temp; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 将16进制字符转换为字节 | |||||
| * | |||||
| * @param c | |||||
| * @return | |||||
| */ | |||||
| public static byte toByte(char c) { | |||||
| byte b = (byte) "0123456789ABCDEF".indexOf(c); | |||||
| return b; | |||||
| } | |||||
| /** | |||||
| * 功能描述:把两个字节的字节数组转化为整型数据,高位补零,例如:<br/> | |||||
| * 有字节数组byte[] data = new byte[]{1,2};转换后int数据的字节分布如下:<br/> | |||||
| * 00000000 00000000 00000001 00000010,函数返回258 | |||||
| * | |||||
| * @param lenData | |||||
| * 需要进行转换的字节数组 | |||||
| * @return 字节数组所表示整型值的大小 | |||||
| */ | |||||
| public static int bytesToIntWhereByteLengthEquals2(byte lenData[]) { | |||||
| if (lenData.length != 2) { | |||||
| return -1; | |||||
| } | |||||
| byte fill[] = new byte[] { 0, 0 }; | |||||
| byte real[] = new byte[4]; | |||||
| System.arraycopy(fill, 0, real, 0, 2); | |||||
| System.arraycopy(lenData, 0, real, 2, 2); | |||||
| int len = byteToInt(real); | |||||
| return len; | |||||
| } | |||||
| /** | |||||
| * 功能描述:将byte数组转化为int类型的数据 | |||||
| * | |||||
| * @param byteVal | |||||
| * 需要转化的字节数组 | |||||
| * @return 字节数组所表示的整型数据 | |||||
| */ | |||||
| public static int byteToInt(byte[] byteVal) { | |||||
| int result = 0; | |||||
| for (int i = 0; i < byteVal.length; i++) { | |||||
| int tmpVal = (byteVal[i] << (8 * (3 - i))); | |||||
| switch (i) { | |||||
| case 0: | |||||
| tmpVal = tmpVal & 0xFF000000; | |||||
| break; | |||||
| case 1: | |||||
| tmpVal = tmpVal & 0x00FF0000; | |||||
| break; | |||||
| case 2: | |||||
| tmpVal = tmpVal & 0x0000FF00; | |||||
| break; | |||||
| case 3: | |||||
| tmpVal = tmpVal & 0x000000FF; | |||||
| break; | |||||
| } | |||||
| result = result | tmpVal; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| public static byte CheckXORSum(byte[] bData) { | |||||
| byte sum = 0x00; | |||||
| for (int i = 0; i < bData.length; i++) { | |||||
| sum ^= bData[i]; | |||||
| } | |||||
| return sum; | |||||
| } | |||||
| /** | |||||
| * 从offset开始 将后续长度为len的byte字节转为int | |||||
| * | |||||
| * @param data | |||||
| * @param offset | |||||
| * @param len | |||||
| * @return | |||||
| */ | |||||
| public static int bytesToInt(byte[] data, int offset, int len) { | |||||
| int mask = 0xFF; | |||||
| int temp = 0; | |||||
| int result = 0; | |||||
| len = Math.min(len, 4); | |||||
| for (int i = 0; i < len; i++) { | |||||
| result <<= 8; | |||||
| temp = data[offset + i] & mask; | |||||
| result |= temp; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * byte字节数组中的字符串的长度 | |||||
| * | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static int getBytesStringLen(byte[] data) { | |||||
| int count = 0; | |||||
| for (byte b : data) { | |||||
| if (b == 0x00) | |||||
| break; | |||||
| count++; | |||||
| } | |||||
| return count; | |||||
| } | |||||
| /** | |||||
| * | |||||
| * @Title: hexString2binaryString | |||||
| * @Description: 十六进制字符串转二进制字符串 | |||||
| * @return String | |||||
| * @author fun | |||||
| * @date 2019年3月27日 | |||||
| */ | |||||
| public static String hexString2binaryString(String hexString) { | |||||
| if (hexString == null || hexString.length() % 2 != 0) | |||||
| return null; | |||||
| String bString = "", tmp; | |||||
| for (int i = 0; i < hexString.length(); i++) { | |||||
| tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16)); | |||||
| bString += tmp.substring(tmp.length() - 4); | |||||
| } | |||||
| return bString; | |||||
| } | |||||
| } |
| package com.elinkthings.elink.utils; | |||||
| import java.io.UnsupportedEncodingException; | |||||
| import com.elinkthings.elink.common.Common; | |||||
| public class TeaUtils { | |||||
| public static byte[] encrypt(byte[] data, byte[] key) { | |||||
| int data_len = data.length; // 数据的长度 | |||||
| if (data_len == 0) { | |||||
| return new byte[] {}; | |||||
| } | |||||
| TeaUtils t = new TeaUtils(); | |||||
| if (!t.setKey(key)) { | |||||
| return new byte[] {}; | |||||
| } | |||||
| int group_len = 8; | |||||
| int residues = data_len % group_len; // 余数 | |||||
| int dlen = data_len - residues; | |||||
| // 用于储存加密的密文,第一字节为余数的大小 | |||||
| //int result_len = data_len + 1; | |||||
| int result_len = data_len; | |||||
| if (residues > 0) { | |||||
| result_len += group_len - residues; | |||||
| } | |||||
| byte[] result = new byte[result_len]; | |||||
| //result[0] = (byte)residues; | |||||
| byte[] plain = new byte[group_len]; | |||||
| byte[] enc = new byte[group_len]; | |||||
| for (int i = 0; i < dlen; i += group_len) { | |||||
| for (int j = 0; j < group_len; j++) { | |||||
| plain[j] = data[i + j]; | |||||
| } | |||||
| enc = t.encrypt_group(plain); | |||||
| for (int k = 0; k < group_len; k++) { | |||||
| //result[i + k + 1] = enc[k]; | |||||
| result[i + k ] = enc[k]; | |||||
| } | |||||
| } | |||||
| if (residues > 0) { | |||||
| for (int j = 0; j < residues; j++) { | |||||
| plain[j] = data[dlen + j]; | |||||
| } | |||||
| int padding = group_len - residues; | |||||
| for (int j = 0; j < padding; j++) { | |||||
| plain[residues + j] = (byte)0x00; | |||||
| } | |||||
| enc = t.encrypt_group(plain); | |||||
| for (int k = 0; k < group_len; k++) { | |||||
| //result[dlen + k + 1] = enc[k]; | |||||
| result[dlen + k] = enc[k]; | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| public static byte[] decrypt(byte[] data, byte[] key) { | |||||
| int group_len = 8; | |||||
| // if (data.length % group_len != 1) { | |||||
| // return new byte[] {}; | |||||
| // } | |||||
| TeaUtils t = new TeaUtils(); | |||||
| if (!t.setKey(key)) { | |||||
| return new byte[] {}; | |||||
| } | |||||
| //int data_len = data.length - 1, dlen; // 数据的长度 | |||||
| int data_len = data.length, dlen; // 数据的长度 | |||||
| dlen = data_len; | |||||
| //int residues = (int)(data[0]); // 余数 | |||||
| // if (residues > 0) { | |||||
| // dlen = data_len - group_len; | |||||
| // } else { | |||||
| // dlen = data_len; | |||||
| // } | |||||
| //byte[] result = new byte[dlen + residues]; | |||||
| byte[] result = new byte[dlen]; | |||||
| byte[] dec = new byte[group_len]; | |||||
| byte[] enc = new byte[group_len]; | |||||
| for (int i = 0; i < dlen; i += group_len) { | |||||
| for (int j = 0; j < group_len; j++) { | |||||
| //enc[j] = data[i + j + 1]; | |||||
| enc[j] = data[i + j]; | |||||
| } | |||||
| dec = t.decrypt_group(enc); | |||||
| for (int k = 0; k < group_len; k++) { | |||||
| result[i + k] = dec[k]; | |||||
| } | |||||
| } | |||||
| // if (residues > 0) { | |||||
| // for (int j = 0; j < group_len; j++) { | |||||
| // enc[j] = data[dlen + j + 1]; | |||||
| // } | |||||
| // dec = t.decrypt_group(enc); | |||||
| // for (int k = 0; k < residues; k++) { | |||||
| // result[dlen + k] = dec[k]; | |||||
| // } | |||||
| // } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 设置密钥 | |||||
| * @param k 密钥 | |||||
| * @return 密钥长度为16个byte时, 设置密钥并返回true,否则返回false | |||||
| */ | |||||
| public boolean setKey(byte[] k) { | |||||
| if(k==null){ | |||||
| k = Common.TEA_KEY; | |||||
| } | |||||
| if (k.length != 16) { | |||||
| return false; | |||||
| } | |||||
| k0 = bytes_to_uint32(new byte[] {k[0], k[1], k[2], k[3]}); | |||||
| k1 = bytes_to_uint32(new byte[] {k[4], k[5], k[6], k[7]}); | |||||
| k2 = bytes_to_uint32(new byte[] {k[8], k[9], k[10], k[11]}); | |||||
| k3 = bytes_to_uint32(new byte[] {k[12], k[13], k[14], k[15]}); | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * 设置加密的轮数,默认为32轮 | |||||
| * @param loops 加密轮数 | |||||
| * @return 轮数为16、32、64时,返回true,否则返回false | |||||
| */ | |||||
| public boolean setLoops(int loops) { | |||||
| switch (loops) { | |||||
| case 16: | |||||
| case 32: | |||||
| case 64: | |||||
| this.loops = loops; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| private static long UINT32_MAX = 0xFFFFFFFFL; | |||||
| private static long BYTE_1 = 0xFFL; | |||||
| private static long BYTE_2 = 0xFF00L; | |||||
| private static long BYTE_3 = 0xFF0000L; | |||||
| private static long BYTE_4 = 0xFF000000L; | |||||
| private static long delta = 0x9E3779B9L; | |||||
| private static long k0; | |||||
| private static long k1; | |||||
| private static long k2; | |||||
| private static long k3; | |||||
| private static int loops = 32; | |||||
| /** | |||||
| * 加密一组明文 | |||||
| * @param v 需要加密的明文 | |||||
| * @return 返回密文 | |||||
| */ | |||||
| public static byte[] encrypt_group(byte[] v) { | |||||
| long v0 = bytes_to_uint32(new byte[] {v[0], v[1], v[2], v[3]}); | |||||
| long v1 = bytes_to_uint32(new byte[] {v[4], v[5], v[6], v[7]}); | |||||
| long sum = 0L; | |||||
| long v0_xor_1 = 0L, v0_xor_2 = 0L, v0_xor_3 = 0L; | |||||
| long v1_xor_1 = 0L, v1_xor_2 = 0L, v1_xor_3 = 0L; | |||||
| for (int i = 0; i < loops; i++) { | |||||
| sum = toUInt32(sum + delta); | |||||
| v0_xor_1 = toUInt32(toUInt32(v1 << 4) + k0); | |||||
| v0_xor_2 = toUInt32(v1 + sum); | |||||
| v0_xor_3 = toUInt32((v1 >> 5) + k1); | |||||
| v0 = toUInt32( v0 + toUInt32(v0_xor_1 ^ v0_xor_2 ^ v0_xor_3) ); | |||||
| v1_xor_1 = toUInt32(toUInt32(v0 << 4) + k2); | |||||
| v1_xor_2 = toUInt32(v0 + sum); | |||||
| v1_xor_3 = toUInt32((v0 >> 5) + k3); | |||||
| //System.out.printf("%08X\t%08X\t%08X\t%08X\n", i, v0, v0 >> 5, k3); | |||||
| v1 = toUInt32( v1 + toUInt32(v1_xor_1 ^ v1_xor_2 ^ v1_xor_3) ); | |||||
| } | |||||
| byte[] b0 = long_to_bytes(v0, 4); | |||||
| byte[] b1 = long_to_bytes(v1, 4); | |||||
| return new byte[] {b0[0], b0[1], b0[2], b0[3], b1[0], b1[1], b1[2], b1[3]}; | |||||
| } | |||||
| /** | |||||
| * 解密一组密文 | |||||
| * @param v 要解密的密文 | |||||
| * @return 返回明文 | |||||
| */ | |||||
| public static byte[] decrypt_group(byte[] v) { | |||||
| long v0 = bytes_to_uint32(new byte[] {v[0], v[1], v[2], v[3]}); | |||||
| long v1 = bytes_to_uint32(new byte[] {v[4], v[5], v[6], v[7]}); | |||||
| long sum = 0xC6EF3720L, tmp = 0L; | |||||
| for (int i = 0; i < loops; i++) { | |||||
| tmp = toUInt32(toUInt32(v0 << 4) + k2); | |||||
| v1 = toUInt32( v1 - toUInt32(tmp ^ toUInt32(v0 + sum) ^ toUInt32((v0 >> 5) + k3)) ); | |||||
| tmp = toUInt32(toUInt32(v1 << 4) + k0); | |||||
| v0 = toUInt32( v0 - toUInt32(tmp ^ toUInt32(v1 + sum) ^ toUInt32((v1 >> 5) + k1)) ); | |||||
| sum = toUInt32(sum - delta); | |||||
| } | |||||
| byte[] b0 = long_to_bytes(v0, 4); | |||||
| byte[] b1 = long_to_bytes(v1, 4); | |||||
| return new byte[] {b0[0], b0[1], b0[2], b0[3], b1[0], b1[1], b1[2], b1[3]}; | |||||
| } | |||||
| /** | |||||
| * 将 long 类型的 n 转为 byte 数组,如果 len 为 4,则只返回低32位的4个byte | |||||
| * @param n 需要转换的long | |||||
| * @param len 若为4,则只返回低32位的4个byte,否则返回8个byte | |||||
| * @return 转换后byte数组 | |||||
| */ | |||||
| private static byte[] long_to_bytes(long n, int len) { | |||||
| byte a = (byte)((n & BYTE_4) >> 24); | |||||
| byte b = (byte)((n & BYTE_3) >> 16); | |||||
| byte c = (byte)((n & BYTE_2) >> 8); | |||||
| byte d = (byte)(n & BYTE_1); | |||||
| if (len == 4) { | |||||
| return new byte[] {a, b, c, d}; | |||||
| } | |||||
| byte ha = (byte)(n >> 56); | |||||
| byte hb = (byte)((n >> 48) & BYTE_1); | |||||
| byte hc = (byte)((n >> 40) & BYTE_1); | |||||
| byte hd = (byte)((n >> 32) & BYTE_1); | |||||
| return new byte[] {ha, hb, hc, hd, a, b, c, d}; | |||||
| } | |||||
| /** | |||||
| * 将4个byte转为 Unsigned Integer 32,以 long 形式返回 | |||||
| * @param bs 需要转换的字节 | |||||
| * @return 返回 long,高32位为0,低32位视为Unsigned Integer | |||||
| */ | |||||
| private static long bytes_to_uint32(byte[] bs) { | |||||
| return ((bs[0]<<24) & BYTE_4) + | |||||
| ((bs[1]<<16) & BYTE_3) + | |||||
| ((bs[2]<<8) & BYTE_2) + | |||||
| (bs[3] & BYTE_1); | |||||
| } | |||||
| /** | |||||
| * 将long的高32位清除,只保留低32位,低32位视为Unsigned Integer | |||||
| * @param n 需要清除的long | |||||
| * @return 返回高32位全为0的long | |||||
| */ | |||||
| private static long toUInt32(long n) { | |||||
| return n & UINT32_MAX; | |||||
| } | |||||
| public static void main(String args[]) throws UnsupportedEncodingException | |||||
| { | |||||
| TeaUtils t = new TeaUtils(); | |||||
| t.setKey(Common.TEA_KEY); | |||||
| byte[] old = new byte[]{(byte)0x01,(byte)0x16,(byte)0xA4,(byte)0x28, | |||||
| (byte)0x32,(byte)0x18,(byte)0x4A,(byte)0x88, | |||||
| (byte)0x00,(byte)0x00 ,(byte)0x00 ,(byte)0x00, | |||||
| (byte)0x00 ,(byte)0x00 ,(byte)0x42 ,(byte)0x4D, | |||||
| (byte)0x10 ,(byte)0x01,(byte)0x0A ,(byte)0x00, | |||||
| (byte)0x13 ,(byte)0x05 ,(byte)0x07 ,(byte)0xC8}; | |||||
| /*byte[] old = new byte[] { | |||||
| 0x00, 0x00, 0x00, 0x20, | |||||
| 0x00, 0x00, 0x00, 0x10 | |||||
| };*/ | |||||
| byte[] enc = t.encrypt(old,Common.TEA_KEY); | |||||
| System.out.println( "tea加密:"); | |||||
| for(byte i : enc) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| byte[] dec = t.decrypt(enc,Common.TEA_KEY); | |||||
| System.out.println( "tea解密:"); | |||||
| for(byte i : dec) | |||||
| System.out.print(i + " "); | |||||
| System.out.println(); | |||||
| } | |||||
| } |