mirror of
https://gitee.com/willfree/min-dev-java.git
synced 2026-10-04 19:42:01 +08:00
Merge branch 'master' of gitee.com:willfree/min-dev-java
This commit is contained in:
commit
84ae7d1443
18 files changed
+750
-1
No files matched your search
@@ -0,0 +1,192 @@
|
||||
package encoding;
|
||||
|
||||
import util.ByteHelper;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 14:19 2021/3/2
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
|
||||
// TLV 组件容器
|
||||
class ElementContainer{
|
||||
private List<Block> ElementContainer;
|
||||
public ElementContainer(){
|
||||
ElementContainer= new LinkedList<>();
|
||||
}
|
||||
public int length(){
|
||||
return ElementContainer.size();
|
||||
}
|
||||
}
|
||||
|
||||
public class Block {
|
||||
private VlInt tlvType; // TLV-TYPE
|
||||
private VlInt length; // TLV-LENGTH
|
||||
private byte[] value; // TLV-VALUE
|
||||
private ElementContainer elements; // TLV-sub-elements
|
||||
private byte[] raw; // TLV编码后的字节数组
|
||||
|
||||
/**
|
||||
* 从一个包含TLV的字节数组中构造一个 Block 对象
|
||||
* @param buffer
|
||||
* @param verifyLength 是否要验证TLV的长度是否匹配,如果true,
|
||||
* 则会对比解析到的 TLV-LENGTH 与 TLV-VALUE的实际长度是否匹配
|
||||
* @return
|
||||
*/
|
||||
public Block createBlockByBuffer(byte[] buffer,boolean verifyLength){
|
||||
if(buffer.length==0){
|
||||
return null;
|
||||
}
|
||||
|
||||
// 读取type
|
||||
VlInt tlvType=TLV.readType(buffer,new VlInt(0));
|
||||
if(tlvType==null){
|
||||
return null;
|
||||
}
|
||||
|
||||
// 读取length
|
||||
VlInt tlvLength=TLV.readVarNumber(buffer,new VlInt(tlvType.SizeOfVarNumber()));
|
||||
if(tlvLength==null){
|
||||
return null;
|
||||
}
|
||||
|
||||
return createBlockByTypeLengthBuffer(tlvType,tlvLength,
|
||||
ByteHelper.getLenBytes(buffer,new VlInt(tlvType.SizeOfVarNumber()+tlvLength.SizeOfVarNumber()),
|
||||
buffer.length-(tlvType.SizeOfVarNumber()+tlvLength.SizeOfVarNumber())),verifyLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入 T、L、V 构造一个 TLV Block
|
||||
* @param tlvType
|
||||
* @param tlvLength
|
||||
* @param buffer
|
||||
* @param verifyLength
|
||||
* @return
|
||||
*/
|
||||
public Block createBlockByTypeLengthBuffer(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength){
|
||||
return new Block(tlvType,tlvLength,buffer,verifyLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param tlvType
|
||||
* @param tlvLength
|
||||
* @param buffer
|
||||
* @param verifyLength
|
||||
*/
|
||||
public Block(VlInt tlvType,VlInt tlvLength,byte[] buffer,boolean verifyLength){
|
||||
this.tlvType=tlvType;
|
||||
this.length=tlvLength;
|
||||
|
||||
// 检查长度是否正确
|
||||
if(verifyLength && (!this.length.isEqual(buffer.length))){
|
||||
//todo: 抛出异常
|
||||
}
|
||||
|
||||
// todo;设置 Raw
|
||||
|
||||
// todo 设置Value
|
||||
|
||||
}
|
||||
|
||||
public VlInt getTlvType() {
|
||||
return tlvType;
|
||||
}
|
||||
|
||||
public void setTlvType(VlInt tlvType) {
|
||||
this.tlvType = tlvType;
|
||||
}
|
||||
|
||||
public VlInt getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(VlInt length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public byte[] getRaw() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 整个TLV编码后的大小,包含T和L
|
||||
* @return
|
||||
*/
|
||||
public SizeT Size(){
|
||||
if(!this.isValid()){
|
||||
return null;
|
||||
}
|
||||
return new SizeT(this.tlvType.SizeOfVarNumber()+this.length.SizeOfVarNumber()+this.value.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前的 Block 对象是否含有 value
|
||||
* @return
|
||||
*/
|
||||
public boolean hasValue(){
|
||||
return this.value.length!=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前的 Block 对象是否含有 raw数组
|
||||
* @return
|
||||
*/
|
||||
public boolean hasRaw(){
|
||||
return this.raw.length!=0;
|
||||
}
|
||||
|
||||
// ************** Sub-Elements **************
|
||||
|
||||
/**
|
||||
* 判断当前 TLV Block 是否包含子 TLV
|
||||
* 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法,
|
||||
* 才会去解析一级子TLV
|
||||
* @return
|
||||
*/
|
||||
public boolean hasSubElement(){
|
||||
return this.elements.length()!=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的一级子TLV Block
|
||||
* * 1. 每次通过 CreateBlockBy* 系列工厂方法构造出Block之后,需要手动调用 ParseSubElements 方法,
|
||||
* * 才会去解析一级子TLV
|
||||
* @return
|
||||
*/
|
||||
public ElementContainer getSubElements(){
|
||||
return this.elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 value 字节数组中解析出所有的一级子 TLV Block
|
||||
* 1. 这要求这个TLV确实存在嵌套的子TLV,或者为空;
|
||||
* 2. 如果TLV的value不为空,且不存在嵌套的子TLV,则会抛出错误
|
||||
* @return
|
||||
*/
|
||||
// public boolean parseSubElements(){
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* 判断是否有效
|
||||
* @return
|
||||
*/
|
||||
public boolean isValid(){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
package encoding;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static java.lang.Math.pow;
|
||||
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:变长无符号整型,用于表示TLV中的T和L
|
||||
* @Version: 1.0.0
|
||||
* @Date: 18:13 2021/3/1
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class SizeT {
|
||||
// 实际传输的数据
|
||||
private byte[] VlIntBytes;
|
||||
// 变长整数表示的真实数值
|
||||
private BigInteger VlIntValue;
|
||||
|
||||
/**
|
||||
* 测量一个变长整型实际用几个字节表示
|
||||
* @return
|
||||
*/
|
||||
public int SizeOfVarNumber(){
|
||||
return SizeOfVarNumber(this.VlIntValue);
|
||||
}
|
||||
private static int SizeOfVarNumber(BigInteger bigInteger){
|
||||
if(bigInteger.compareTo(BigInteger.valueOf(Long.parseLong("241"))) < 0){
|
||||
return 1;
|
||||
}else if(bigInteger.compareTo(BigInteger.valueOf(
|
||||
new Double(pow(2, 16)).longValue())) < 0){
|
||||
return 3;
|
||||
}else if(bigInteger.compareTo(BigInteger.valueOf(
|
||||
new Double(pow(2, 32)).longValue())) < 0){
|
||||
return 5;
|
||||
}else{ //MIN1.0中,VlInt的size最大为9
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
|
||||
//todo:判断bytes是否是一个合法的变长非负整型
|
||||
|
||||
//todo:判断biginteger是否合法
|
||||
|
||||
public SizeT(byte[] bytes){
|
||||
this.VlIntBytes=bytes;
|
||||
this.VlIntValue=vlintBytes2bigInteger(bytes);
|
||||
}
|
||||
|
||||
public SizeT(BigInteger bigInteger){
|
||||
this.VlIntValue=bigInteger;
|
||||
this.VlIntBytes=bigInteger2vlintBytes(bigInteger);
|
||||
}
|
||||
|
||||
// 传入一个变长无符号字节数组byte[],将它解析成一个VlInt
|
||||
public SizeT createVlInt(byte[] bytes){
|
||||
return new SizeT(bytes);
|
||||
}
|
||||
|
||||
// 传入一个BigInteger,将它解析成一个VlInt
|
||||
public SizeT createVlIntByBigInteger(BigInteger bigInteger){
|
||||
return new SizeT(bigInteger);
|
||||
}
|
||||
|
||||
// todo:传入一个int,将它解析成一个VlInt
|
||||
public SizeT(int i){
|
||||
this.VlIntValue=new BigInteger(String.valueOf(i));
|
||||
this.VlIntBytes=bigInteger2vlintBytes(this.VlIntValue);
|
||||
}
|
||||
|
||||
// todo:传入一个long,将它解析成一个VlInt
|
||||
|
||||
// 将vlint转为一个int输出:需要判断size是不是小于4(1 or 3)
|
||||
public Integer getVlIntValue2Int(){
|
||||
if(this.SizeOfVarNumber()<4){
|
||||
return VlIntValue.intValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 将vlint转为一个long输出:需要判断size是不是小于8(5)
|
||||
public Long getVlIntValue2Long(){
|
||||
if(this.SizeOfVarNumber()<8){
|
||||
return VlIntValue.longValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 将vlint转为一个biginteger输出:需要判断size是不是等于9(9)
|
||||
public BigInteger getVlIntValue(){
|
||||
if(this.SizeOfVarNumber()>=9){
|
||||
return VlIntValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 判断vlint是否与某个int值相等
|
||||
public boolean isEqual(Integer vlint){
|
||||
return isEqual(vlint.intValue());
|
||||
}
|
||||
public boolean isEqual(int i){
|
||||
if(this.VlIntValue.compareTo(new BigInteger(String.valueOf(i)))==0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isEqual(SizeT vlInt){
|
||||
if(this.VlIntValue.compareTo(vlInt.VlIntValue)==0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// todo: 判断vlint是否与某个long值相等
|
||||
|
||||
/**
|
||||
* 判断与另一个VlInt的数值孰大孰小
|
||||
* @param vlInt
|
||||
* @return
|
||||
*/
|
||||
public int compareTo(SizeT vlInt){
|
||||
return this.VlIntValue.compareTo(vlInt.VlIntValue);
|
||||
}
|
||||
public int compareTo(int i){
|
||||
BigInteger bigInteger=new BigInteger(String.valueOf(i));
|
||||
return this.VlIntValue.compareTo(bigInteger);
|
||||
}
|
||||
|
||||
/**
|
||||
* 减去另一个VlInt
|
||||
* todo:暂没考虑两者差值越界int最大值
|
||||
* @param vlInt
|
||||
* @return
|
||||
*/
|
||||
public int subtract(SizeT vlInt){
|
||||
return this.VlIntValue.subtract(vlInt.VlIntValue).intValue();
|
||||
}
|
||||
|
||||
// 将BigInteger转为byte[按照变长无符号整数方式转]
|
||||
private byte[] bigInteger2vlintBytes(BigInteger bigInteger){
|
||||
byte[] vlintbytes;
|
||||
if(SizeOfVarNumber(bigInteger)==1){
|
||||
vlintbytes=new byte[1];
|
||||
//todo
|
||||
}else if(SizeOfVarNumber(bigInteger)==3){
|
||||
vlintbytes=new byte[3];
|
||||
//todo
|
||||
}else if(SizeOfVarNumber(bigInteger)==5){
|
||||
vlintbytes=new byte[5];
|
||||
//todo
|
||||
}else{
|
||||
vlintbytes=new byte[9];
|
||||
//todo
|
||||
}
|
||||
return vlintbytes;
|
||||
}
|
||||
|
||||
// 将变长无符号整数数组转为BigInteger
|
||||
private BigInteger vlintBytes2bigInteger(byte[] vlIntBytes){
|
||||
BigInteger vlintValue=null;
|
||||
if(vlIntBytes.length==1){
|
||||
//todo
|
||||
}else if(vlIntBytes.length==3){
|
||||
//todo
|
||||
}else if(vlIntBytes.length==5){
|
||||
//todo
|
||||
}else if(vlIntBytes.length==9){
|
||||
//todo
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
return vlintValue;
|
||||
}
|
||||
|
||||
// 测试
|
||||
public static void main(String[] args){
|
||||
BigInteger bigInteger=new BigInteger("3");
|
||||
SizeT vlInt=new SizeT(bigInteger);
|
||||
System.out.println(vlInt.isEqual(2));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package encoding;
|
||||
|
||||
import static util.ByteHelper.*;
|
||||
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 17:54 2021/3/1
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class TLV {
|
||||
////// 一级:网络分组级别TLV号分配(0 ~ 49)
|
||||
public static final int TlvInvalid = 0; // 无效包
|
||||
public static final int TlvPacketMINCommon = 5; // 通用MIN包
|
||||
public static final int TlvPacketMINManagement = 6; // MIN管理包
|
||||
public static final int TlvPacketMINIP = 7; // MIN支持IP包
|
||||
|
||||
////// 二级:网络包分区TLV号分配 (50 ~ 99)
|
||||
public static final int TlvIdentifierField = 50; // 目的标识区
|
||||
public static final int TlvSignatureField = 51; // 数字签名区
|
||||
public static final int TlvReadOnlyField = 52; // 只读数据区
|
||||
public static final int TlvMutableField = 53; // 可变数据区
|
||||
public static final int TlvMutableProtectField = 54; // 可变数据区中的保护区
|
||||
public static final int TlvMutableDangerousField = 55; // 可变数据区中的非受保护区
|
||||
|
||||
////// 组件 (100 -> 500)
|
||||
// 标识分配
|
||||
public static final int TlvIdentifierComponent = 100; // 标识名称组件
|
||||
public static final int TlvIdentifier = 101; // 标识
|
||||
public static final int TlvIdentifierCommon = 102; // 身份标识
|
||||
public static final int TlvIdentifierContentInterest = 103; // 内容兴趣标识
|
||||
public static final int TlvIdentifierContentData = 104; // 内容数据标识
|
||||
|
||||
// 数字签名
|
||||
public static final int TlvSignatureValue = 200; // 签名值
|
||||
public static final int TlvSignatureInfo = 201; // 签名参数
|
||||
public static final int TlvSignatureType = 202; // 签名类型
|
||||
public static final int TlvKeyLocator = 203; // 指示证书或公钥的位置
|
||||
|
||||
public static final int TlvPayload = 204; // 网络包负载
|
||||
public static final int TlvCanBePrefix = 205; // 是否可以被较长的数据包前缀匹配
|
||||
public static final int TlvMustBeRefresh = 206; // 是否强制只拉取新鲜的数据
|
||||
public static final int TlvInterestLifeTime = 207; // 兴趣包生存期
|
||||
public static final int TlvNonce = 208; // 随机数
|
||||
public static final int TlvHopLimit = 209; // 跳数限制
|
||||
public static final int TlvFreshnessPeriod = 210; // 数据包新鲜时间
|
||||
public static final int TlvCongestionMark = 211; // 拥塞标记
|
||||
public static final int TlvTTL = 212; // Time to live
|
||||
public static final int TlvNackHeader = 213; // Nack header
|
||||
|
||||
// 管理通信协议
|
||||
public static final int TlvSliceNumber = 211; // 分片数量
|
||||
public static final int TlvSliceSize = 212; // 分片大小
|
||||
public static final int TlvTlvLogicFaceId = 213; // 逻辑接口id
|
||||
public static final int TlvRemoteAddr = 214; // 源端地址
|
||||
public static final int TlvLocalAddr = 215; // 本地地址
|
||||
public static final int TlvMtu = 216; // 最大传输单元
|
||||
public static final int TlvRet = 217; // bool类型,成功或失败
|
||||
public static final int TlvOrigin = 218; //
|
||||
public static final int TlvCost = 219; // 链路开销
|
||||
public static final int TlvExpires = 220; // LogicFace超时时间,-1为不超时(never)
|
||||
|
||||
// 目前已分配的最大的Tlv值,第一轮分配的最大值为500,超过该值则断定为不合法
|
||||
// TODO: 目前TLV值的分配,第一轮分配都在500以内,如果以后分配更高值时,需要修改此处的限制
|
||||
public static final int MaxTlvNum = 500;
|
||||
|
||||
/**
|
||||
* 从字节数组中读出一个变长整型
|
||||
* @param buffer
|
||||
* @param start
|
||||
* @return
|
||||
*/
|
||||
public static VlInt readVarNumber(byte[] buffer,VlInt start){
|
||||
VlInt length=new VlInt(buffer.length);
|
||||
if(start.compareTo(length)>=0){
|
||||
return null;
|
||||
}
|
||||
|
||||
int firstbyte=uint8ToInt(getFirstByte(buffer,start));
|
||||
if(firstbyte<241){
|
||||
return new VlInt(firstbyte);
|
||||
}else if(firstbyte==241){
|
||||
if(length.subtract(start)<3){
|
||||
return null;
|
||||
}
|
||||
return new VlInt(getLenBytes(buffer,start,3));
|
||||
}else if(firstbyte==242){
|
||||
if(length.subtract(start)<5){
|
||||
return null;
|
||||
}
|
||||
return new VlInt(getLenBytes(buffer,start,5));
|
||||
}else if(firstbyte==243){
|
||||
if(length.subtract(start)<9){
|
||||
return null;
|
||||
}
|
||||
return new VlInt(getLenBytes(buffer,start,9));
|
||||
}else{ //MIN1.0中算越界
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从字节数组的指定位置中读取一个变长的整型作为 TLV Type
|
||||
* @param buffer
|
||||
* @param start
|
||||
* @return
|
||||
*/
|
||||
public static VlInt readType(byte[] buffer,VlInt start){
|
||||
VlInt tlvType=readVarNumber(buffer,start);
|
||||
|
||||
if(tlvType==null||tlvType.isEqual(0)||tlvType.compareTo(MaxTlvNum)>0){
|
||||
return null;
|
||||
}
|
||||
|
||||
return tlvType;
|
||||
}
|
||||
|
||||
// todo:从字节数组的指定位置中读取一个非负整型
|
||||
|
||||
/**
|
||||
* 检查某个type值是否是指定的 TLV-TYPE
|
||||
* @param current
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
public static boolean expectType(VlInt current,VlInt target){
|
||||
if(current.isEqual(target)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 TLV 分配规则,判断某个tlvType是否是合规的标识类型
|
||||
* TODO: 目前TLV的分配是500为一轮,如果标识范围扩展了,本方法需要对应修改
|
||||
* @param tlvType
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidIdentifierType(VlInt tlvType){
|
||||
return tlvType.compareTo(102)>=0 && tlvType.compareTo(199)<=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 TLV 分配规则,判断某个tlvType是否是合规的包类型
|
||||
* TODO: 目前TLV的分配是500为一轮,如果标识范围扩展了,本方法需要对应修改
|
||||
* @param tlvType
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidPacketType(VlInt tlvType){
|
||||
return tlvType.compareTo(0)>0 && tlvType.compareTo(50)<0;
|
||||
}
|
||||
|
||||
//todo: 错误处理
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package encoding;
|
||||
|
||||
import util.ByteHelper;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static java.lang.Math.pow;
|
||||
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:变长无符号整型,用于表示TLV中的T和L
|
||||
* @Version: 1.0.0
|
||||
* @Date: 18:13 2021/3/1
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
|
||||
public class VlInt {
|
||||
// 实际传输的数据
|
||||
private byte[] VlIntBytes;
|
||||
// 变长整数表示的真实数值
|
||||
private BigInteger VlIntValue;
|
||||
|
||||
// 一些int常量
|
||||
// @Description:
|
||||
// 1. x < 240 => 1字节表示 => 230
|
||||
// 2. 241 =< x < uint16::Max => 第一个字节为241,后面连着2字节表示实际数值,总共用3个字节表示 => 246
|
||||
// 3. uint16::Max =< x < uint32::Max => 第一个字节为242,后面连着4字节表示实际数值,总共用5个字节表示
|
||||
// 4. int32::Max =< x < int64::Max => 第一个字节为243,后面连着8字节表示实际数值,总共用9个字节表示
|
||||
// 5. 后续还留有12个字节可以进行指数级扩展,目前留空
|
||||
public static final int VlIntExtend2=241;
|
||||
public static final int VlIntExtend4=242;
|
||||
public static final int VlIntExtend8=243;
|
||||
|
||||
/**
|
||||
* 测量一个变长整型实际用几个字节表示
|
||||
* @return
|
||||
*/
|
||||
public int SizeOfVarNumber(){
|
||||
return SizeOfVarNumber(this.VlIntValue);
|
||||
}
|
||||
private static int SizeOfVarNumber(BigInteger bigInteger){
|
||||
if(bigInteger.compareTo(BigInteger.valueOf(Long.parseLong("241"))) < 0){
|
||||
return 1;
|
||||
}else if(bigInteger.compareTo(BigInteger.valueOf(
|
||||
new Double(pow(2, 16)).longValue())) < 0){
|
||||
return 3;
|
||||
}else if(bigInteger.compareTo(BigInteger.valueOf(
|
||||
new Double(pow(2, 32)).longValue())) < 0){
|
||||
return 5;
|
||||
}else{ //MIN1.0中,VlInt的size最大为9
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
|
||||
//todo:判断bytes是否是一个合法的变长非负整型
|
||||
|
||||
//todo:判断biginteger是否合法
|
||||
|
||||
public VlInt(byte[] bytes){
|
||||
this.VlIntBytes=bytes;
|
||||
this.VlIntValue=vlintBytes2bigInteger(bytes);
|
||||
}
|
||||
|
||||
public VlInt(BigInteger bigInteger){
|
||||
this.VlIntValue=bigInteger;
|
||||
this.VlIntBytes=bigInteger2vlintBytes(bigInteger);
|
||||
}
|
||||
|
||||
public VlInt(int i){
|
||||
this.VlIntValue=BigInteger.valueOf(i);
|
||||
this.VlIntBytes=bigInteger2vlintBytes(this.VlIntValue);
|
||||
}
|
||||
|
||||
public VlInt(long l){
|
||||
this.VlIntValue=BigInteger.valueOf(l);
|
||||
this.VlIntBytes=bigInteger2vlintBytes(this.VlIntValue);
|
||||
}
|
||||
|
||||
// 传入一个变长无符号字节数组byte[],将它解析成一个VlInt
|
||||
public VlInt createVlInt(byte[] bytes){
|
||||
return new VlInt(bytes);
|
||||
}
|
||||
|
||||
// 传入一个BigInteger,将它解析成一个VlInt
|
||||
public VlInt createVlIntByBigInteger(BigInteger bigInteger){
|
||||
return new VlInt(bigInteger);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将vlint转为一个int输出:需要判断size是不是小于4(1 or 3)
|
||||
* @return
|
||||
*/
|
||||
public int getVlIntValue2Int(){
|
||||
if(this.SizeOfVarNumber()<4){
|
||||
return VlIntValue.intValue();
|
||||
}
|
||||
return Integer.parseInt(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将vlint转为一个long输出:需要判断size是不是小于8(5)
|
||||
* @return
|
||||
*/
|
||||
public long getVlIntValue2Long(){
|
||||
if(this.SizeOfVarNumber()<8){
|
||||
return VlIntValue.longValue();
|
||||
}
|
||||
return Long.parseLong(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将vlint转为一个biginteger输出:需要判断size是不是等于9(9)
|
||||
* @return
|
||||
*/
|
||||
public BigInteger getVlIntValue(){
|
||||
if(this.SizeOfVarNumber()>=9){
|
||||
return VlIntValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断vlint是否与某个值相等
|
||||
* @param vlInt
|
||||
* @return
|
||||
*/
|
||||
public boolean isEqual(VlInt vlInt){
|
||||
if(this.VlIntValue.compareTo(vlInt.VlIntValue)==0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isEqual(int i){
|
||||
if(this.VlIntValue.compareTo(BigInteger.valueOf(i))==0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isEqual(long l){
|
||||
if(this.VlIntValue.compareTo(BigInteger.valueOf(l))==0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断与另一个VlInt的数值孰大孰小
|
||||
* @param vlInt
|
||||
* @return
|
||||
*/
|
||||
public int compareTo(VlInt vlInt){
|
||||
return this.VlIntValue.compareTo(vlInt.VlIntValue);
|
||||
}
|
||||
public int compareTo(int i){
|
||||
BigInteger bigInteger=BigInteger.valueOf(i);
|
||||
return this.VlIntValue.compareTo(bigInteger);
|
||||
}
|
||||
public int compareTo(long l){
|
||||
BigInteger bigInteger=BigInteger.valueOf(l);
|
||||
return this.VlIntValue.compareTo(bigInteger);
|
||||
}
|
||||
|
||||
/**
|
||||
* 减去另一个VlInt
|
||||
* todo:暂没考虑两者差值越界int最大值
|
||||
* @param vlInt
|
||||
* @return
|
||||
*/
|
||||
public int subtract(VlInt vlInt){
|
||||
return this.VlIntValue.subtract(vlInt.VlIntValue).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将BigInteger转为byte[按照变长无符号整数方式转]
|
||||
* @param bigInteger
|
||||
* @return
|
||||
*/
|
||||
private byte[] bigInteger2vlintBytes(BigInteger bigInteger){
|
||||
byte[] vlintbytes;
|
||||
if(SizeOfVarNumber(bigInteger)==1){
|
||||
vlintbytes=new byte[1];
|
||||
vlintbytes[0]= ByteHelper.uint8ToByte(bigInteger.intValue());
|
||||
}else if(SizeOfVarNumber(bigInteger)==3){
|
||||
vlintbytes=new byte[3];
|
||||
vlintbytes[0]=ByteHelper.uint8ToByte(VlIntExtend2);
|
||||
System.arraycopy(ByteHelper.uint16ToByteArray(bigInteger.intValue()),0,vlintbytes,1,2);
|
||||
}else if(SizeOfVarNumber(bigInteger)==5){
|
||||
vlintbytes=new byte[5];
|
||||
vlintbytes[0]=ByteHelper.uint8ToByte(VlIntExtend4);
|
||||
System.arraycopy(ByteHelper.uint32ToByteArray(bigInteger.longValue()),0,vlintbytes,1,4);
|
||||
}else{
|
||||
vlintbytes=new byte[9];
|
||||
vlintbytes[0]=ByteHelper.uint8ToByte(VlIntExtend8);
|
||||
System.arraycopy(ByteHelper.uint64ToByteArray(bigInteger.longValue()),0,vlintbytes,1,8);
|
||||
}
|
||||
return vlintbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将变长无符号整数数组转为BigInteger
|
||||
* @param vlIntBytes
|
||||
* @return
|
||||
*/
|
||||
private BigInteger vlintBytes2bigInteger(byte[] vlIntBytes){
|
||||
BigInteger vlintValue;
|
||||
if(vlIntBytes.length==1){
|
||||
long value=ByteHelper.uint8ToLong(vlIntBytes[0]);
|
||||
vlintValue=BigInteger.valueOf(value);
|
||||
}else if(vlIntBytes.length==3){
|
||||
byte[] valueByte=new byte[2];
|
||||
System.arraycopy(vlIntBytes,1,valueByte,0,valueByte.length);
|
||||
long value=ByteHelper.uint16ToLong(valueByte);
|
||||
vlintValue=BigInteger.valueOf(value);
|
||||
}else if(vlIntBytes.length==5){
|
||||
byte[] valueByte=new byte[4];
|
||||
System.arraycopy(vlIntBytes,1,valueByte,0,valueByte.length);
|
||||
long value=ByteHelper.uint32ToLong(valueByte);
|
||||
vlintValue=BigInteger.valueOf(value);
|
||||
}else if(vlIntBytes.length==9){
|
||||
byte[] valueByte=new byte[8];
|
||||
System.arraycopy(vlIntBytes,1,valueByte,0,valueByte.length);
|
||||
long value=ByteHelper.uint64ToLong(valueByte);
|
||||
vlintValue=BigInteger.valueOf(value);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
return vlintValue;
|
||||
}
|
||||
|
||||
// 测试
|
||||
public static void main(String[] args){
|
||||
BigInteger bigInteger=new BigInteger("3");
|
||||
VlInt vlInt=new VlInt(bigInteger);
|
||||
System.out.println(vlInt.isEqual(2));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package encoding;
|
||||
|
||||
import static java.lang.Math.pow;
|
||||
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:变长无符号整型,用于表示TLV中的T和L
|
||||
* @Version: 1.0.0
|
||||
* @Date: 22:58 2021/3/1
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class VlInt_V1 {
|
||||
|
||||
// 实际传输的数据
|
||||
private byte[] VlIntByte;
|
||||
// 变长整数表示的真实数值:
|
||||
// MIN1.0最大为(2^64-1),此处用long表示,则可能发生越界
|
||||
private long VlIntValue;
|
||||
|
||||
// 传入一个变长无符号字节数组byte[],将它解析成一个VlInt
|
||||
|
||||
// 传入一个int,将它解析成一个VlInt
|
||||
|
||||
// 将vlint转为一个int输出
|
||||
|
||||
/**
|
||||
* 测量一个变长整型实际用几个字节表示
|
||||
* @return int
|
||||
*/
|
||||
public int SizeOfVarNumber(){
|
||||
if(VlIntValue<241){
|
||||
return 1;
|
||||
}else if(VlIntValue<new Double(pow(2,16))){
|
||||
return 3;
|
||||
}else{
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package minsecurity;
|
||||
|
||||
import org.bouncycastle.crypto.CryptoException;
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description: 所有对称加密方法必须实现的基本方法
|
||||
* @Version: 1.0.0
|
||||
* @Date: 17:28 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public interface PrivateKeyInterface {
|
||||
public byte[] getBytes();
|
||||
public boolean setBytes(byte[] bytes);
|
||||
public byte[] decrypt(byte[] content) throws InvalidCipherTextException;
|
||||
public byte[] sign(byte[] content) throws CryptoException;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package minsecurity;
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description: 所有对称加密方法必须实现的基本方法
|
||||
* @Version: 1.0.0
|
||||
* @Date: 17:06 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
|
||||
public interface PublicKeyInterface {
|
||||
public byte[] getBytes();
|
||||
public boolean setBytes(byte[] bytes);
|
||||
public byte[] encrypt(byte[] content) throws InvalidCipherTextException;
|
||||
public boolean verify(byte[] content, byte[] digest);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package minsecurity.crypto.sm2;
|
||||
|
||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description: SM2推荐曲线参数
|
||||
* @Version: 1.0.0
|
||||
* @Date: 18:48 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Sm2Base {
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Sm2Base.class);
|
||||
public static final SM2P256V1Curve CURVE = new SM2P256V1Curve();
|
||||
public final static BigInteger SM2_ECC_P = CURVE.getQ();
|
||||
public final static BigInteger SM2_ECC_A = CURVE.getA().toBigInteger();
|
||||
public final static BigInteger SM2_ECC_B = CURVE.getB().toBigInteger();
|
||||
public final static BigInteger SM2_ECC_N = CURVE.getOrder();
|
||||
public final static BigInteger SM2_ECC_H = CURVE.getCofactor();
|
||||
public final static BigInteger SM2_ECC_GX = new BigInteger(
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16);
|
||||
public final static BigInteger SM2_ECC_GY = new BigInteger(
|
||||
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16);
|
||||
public static final ECPoint G_POINT = CURVE.createPoint(SM2_ECC_GX, SM2_ECC_GY);
|
||||
public static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G_POINT,
|
||||
SM2_ECC_N, SM2_ECC_H);
|
||||
|
||||
public static AsymmetricCipherKeyPair generateKeyPairParameter(){
|
||||
SecureRandom random = new SecureRandom();
|
||||
ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(DOMAIN_PARAMS,
|
||||
random);
|
||||
ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
|
||||
keyGen.init(keyGenerationParams);
|
||||
AsymmetricCipherKeyPair keyPair = keyGen.generateKeyPair();
|
||||
ECPrivateKeyParameters privateKeyParameters = (ECPrivateKeyParameters) keyPair.getPrivate();
|
||||
logger.debug("priv D: bitlen = {}, d.len = {}",privateKeyParameters.getD().bitLength(),privateKeyParameters.getD().toByteArray().length);
|
||||
return keyPair;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package minsecurity.crypto.sm2;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description: sm2的自定义异常
|
||||
* @Version: 1.0.0
|
||||
* @Date: 19:00 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Sm2Exception extends java.lang.Exception {
|
||||
public Sm2Exception(String msg){
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package minsecurity.crypto.sm2;
|
||||
|
||||
import minsecurity.PrivateKeyInterface;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
import org.bouncycastle.crypto.CryptoException;
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
import org.bouncycastle.crypto.engines.SM2Engine;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ParametersWithID;
|
||||
import org.bouncycastle.crypto.params.ParametersWithRandom;
|
||||
import org.bouncycastle.crypto.signers.SM2Signer;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description: 国密sm2 非对称加密私钥
|
||||
* @Version: 1.0.0
|
||||
* @Date: 19:40 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Sm2PrivateKey implements PrivateKeyInterface {
|
||||
|
||||
Sm2PrivateKey(){}
|
||||
|
||||
Sm2PrivateKey(byte[] d) {
|
||||
if(d.length == 32 || d.length == 33)
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS);
|
||||
else {
|
||||
try {
|
||||
throw new Sm2Exception("SM2私钥中,参数d长度应为32/33");
|
||||
} catch (Sm2Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Sm2PrivateKey(byte[] d, ECDomainParameters parameters){
|
||||
if(d.length == 32 || d.length == 33)
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), parameters);
|
||||
else {
|
||||
try {
|
||||
throw new Sm2Exception("SM2私钥中,参数d长度应为32/33");
|
||||
} catch (Sm2Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
return privateKey.getD().toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBytes(byte[] d) {
|
||||
if(d.length != 32 && d.length != 33)
|
||||
return false;
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException {
|
||||
SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C2C3);
|
||||
engine.init(false, privateKey);
|
||||
return engine.processBlock(cipher, 0, cipher.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] sign(byte[] content) throws CryptoException {
|
||||
SM2Signer signer = new SM2Signer();
|
||||
CipherParameters param = null;
|
||||
ParametersWithRandom pwr = new ParametersWithRandom(privateKey, new SecureRandom());
|
||||
param = pwr;
|
||||
signer.init(true, param);
|
||||
signer.update(content, 0, content.length);
|
||||
return signer.generateSignature();
|
||||
}
|
||||
|
||||
private ECPrivateKeyParameters privateKey;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package minsecurity.crypto.sm2;
|
||||
|
||||
import minsecurity.PublicKeyInterface;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
import org.bouncycastle.crypto.engines.SM2Engine;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ParametersWithRandom;
|
||||
import org.bouncycastle.crypto.signers.SM2Signer;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description: 国密sm2 非对称加密公钥
|
||||
* @Version: 1.0.0
|
||||
* @Date: 17:32 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Sm2PublicKey implements PublicKeyInterface {
|
||||
|
||||
Sm2PublicKey(){}
|
||||
|
||||
public Sm2PublicKey(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){
|
||||
publicKey = createPublicKey(xBytes,yBytes,curve,domainParameters);
|
||||
}
|
||||
|
||||
public Sm2PublicKey(byte[] xBytes, byte[] yBytes){
|
||||
this(xBytes,yBytes, Sm2Base.CURVE, Sm2Base.DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
if(publicKey != null)
|
||||
return publicKey.getQ().getEncoded(false); //不压缩
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBytes(byte[] bytes) {
|
||||
if(bytes.length != 65)
|
||||
return false;
|
||||
ByteBuffer encoded = ByteBuffer.wrap(bytes);
|
||||
byte[] x = new byte[32];
|
||||
byte[] y = new byte[32];
|
||||
encoded.position(1);
|
||||
encoded.get(x,0,32);
|
||||
encoded.get(y,0,32);
|
||||
publicKey = createPublicKey(x,y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encrypt(byte[] content) throws InvalidCipherTextException {
|
||||
SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C2C3);
|
||||
ParametersWithRandom pwr = new ParametersWithRandom(publicKey, new SecureRandom());
|
||||
engine.init(true, pwr);
|
||||
return engine.processBlock(content, 0, content.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(byte[] content, byte[] digest) {
|
||||
SM2Signer signer = new SM2Signer();
|
||||
CipherParameters param = publicKey;
|
||||
signer.init(false, param);
|
||||
signer.update(content, 0, content.length);
|
||||
return signer.verifySignature(digest);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////// private start //////////////////////////////////////////////
|
||||
private static ECPublicKeyParameters createPublicKey(
|
||||
byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){
|
||||
final byte uncompressedFlag = 0x04;
|
||||
int curveLength = getCurveLength(domainParameters);
|
||||
xBytes = fixToCurveLengthBytes(curveLength, xBytes);
|
||||
yBytes = fixToCurveLengthBytes(curveLength, yBytes);
|
||||
byte[] encodedPubKey = new byte[1 + xBytes.length + yBytes.length];
|
||||
encodedPubKey[0] = uncompressedFlag;
|
||||
System.arraycopy(xBytes, 0, encodedPubKey, 1, xBytes.length);
|
||||
System.arraycopy(yBytes, 0, encodedPubKey, 1 + xBytes.length, yBytes.length);
|
||||
return new ECPublicKeyParameters(curve.decodePoint(encodedPubKey), domainParameters);
|
||||
}
|
||||
|
||||
private static ECPublicKeyParameters createPublicKey(byte[] xBytes, byte[] yBytes){
|
||||
return createPublicKey(xBytes,yBytes,Sm2Base.CURVE,Sm2Base.DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
private static int getCurveLength(ECDomainParameters domainParams) {
|
||||
return (domainParams.getCurve().getFieldSize() + 7) / 8;
|
||||
}
|
||||
|
||||
private static byte[] fixToCurveLengthBytes(int curveLength, byte[] src) {
|
||||
if (src.length == curveLength) {
|
||||
return src;
|
||||
}
|
||||
|
||||
byte[] result = new byte[curveLength];
|
||||
if (src.length > curveLength) {
|
||||
System.arraycopy(src, src.length - result.length, result, 0, result.length);
|
||||
} else {
|
||||
System.arraycopy(src, 0, result, result.length - src.length, src.length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
////////////////////////////////////////////// private end //////////////////////////////////////////////
|
||||
|
||||
ECPublicKeyParameters publicKey;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
package util;
|
||||
|
||||
import encoding.VlInt;
|
||||
|
||||
/*
|
||||
* @Author: Wang Feng
|
||||
* @Description:常用的数据类型转换。转无符号byte是重点
|
||||
* @Version: 1.0.0
|
||||
* @Date: 15:40 2021/3/2
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class ByteHelper {
|
||||
|
||||
/**
|
||||
* 从byte[]数组指定开始位置获取第一个字节
|
||||
* todo: start位置可能是大于int类型的数值
|
||||
* @param buffer
|
||||
* @param start
|
||||
* @return
|
||||
*/
|
||||
public static byte getFirstByte(byte[] buffer, VlInt start){
|
||||
int startInt=start.getVlIntValue2Int();
|
||||
byte[] firstbyte=new byte[1];
|
||||
System.arraycopy(buffer,startInt,firstbyte,0,firstbyte.length);
|
||||
return firstbyte[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 从byte[]数组指定开始位置获取长度为len的字节数组
|
||||
* todo: start位置可能是大于int类型的数值
|
||||
* @param buffer
|
||||
* @param start
|
||||
* @return
|
||||
*/
|
||||
public static byte[] getLenBytes(byte[] buffer, VlInt start,VlInt len){
|
||||
int startInt=start.getVlIntValue2Int();
|
||||
int lenInt=len.getVlIntValue2Int();
|
||||
byte[] lenbytes=new byte[1];
|
||||
System.arraycopy(buffer,startInt,lenbytes,0,lenInt);
|
||||
return lenbytes;
|
||||
}
|
||||
public static byte[] getLenBytes(byte[] buffer, VlInt start,int len){
|
||||
int startInt=start.getVlIntValue2Int();
|
||||
byte[] lenbytes=new byte[1];
|
||||
System.arraycopy(buffer,startInt,lenbytes,0,len);
|
||||
return lenbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无符号int转byte[]
|
||||
* @param i_int
|
||||
* @return
|
||||
*/
|
||||
private static byte[] intToByteArray(int i_int) {
|
||||
byte[] result = new byte[4];
|
||||
//由高位到低位
|
||||
for(int i=0;i<4;i++) {
|
||||
int offset=(result.length-i-1)*8;
|
||||
result[i] = (byte) ((i_int >>>offset) & 0xff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无符号byte[]转int
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
private static int byteArrayToInt(byte[] bytes) {
|
||||
if(bytes.length!=4){
|
||||
return Integer.parseInt(null);
|
||||
}
|
||||
int value= 0;
|
||||
//由高位到低位
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int offset= (bytes.length - 1 - i) * 8;
|
||||
value +=(bytes[i] & 0x000000ff) << offset; //往高位游
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无符号long转byte[]
|
||||
* @param l_long
|
||||
* @return
|
||||
*/
|
||||
private static byte[] longToByteArray(long l_long) {
|
||||
byte[] result = new byte[8];
|
||||
for (int i = 0; i<8; i++) {
|
||||
int offset = (result.length - 1 - i) * 8;
|
||||
result[i] = (byte) ((l_long >>> offset) & 0xff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无符号byte[]转long
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
private static long byteArrayToLong(byte[] bytes) {
|
||||
if(bytes.length!=8){
|
||||
return Integer.parseInt(null);
|
||||
}
|
||||
int value= 0;
|
||||
//由高位到低位
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int offset= (bytes.length - 1 - i) * 8;
|
||||
value +=(bytes[i] & 0x000000000000ff) << offset; //往高位游
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无符号字节转int
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
// private static int unsignedbyte2int(byte b){
|
||||
// return (int) b&0xff;
|
||||
// }
|
||||
|
||||
/**
|
||||
* uint8转int
|
||||
* @param uint8
|
||||
* @return
|
||||
*/
|
||||
public static int uint8ToInt(byte uint8){
|
||||
return uint8 & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个uint8转为的int,通过本函数再次转为byte
|
||||
* @param uint8
|
||||
* @return
|
||||
*/
|
||||
public static byte uint8ToByte(int uint8){
|
||||
return (byte)(uint8 & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* uint8转long
|
||||
* @param uint8
|
||||
* @return
|
||||
*/
|
||||
public static long uint8ToLong(byte uint8){
|
||||
return uint8ToInt(uint8);
|
||||
}
|
||||
|
||||
/**
|
||||
* uint16转int
|
||||
* @param uint16
|
||||
* @return
|
||||
*/
|
||||
public static int uint16ToInt(byte[] uint16){
|
||||
if(uint16.length!=2){
|
||||
return Integer.parseInt(null);
|
||||
}
|
||||
byte[] bytes=new byte[4];
|
||||
for(int i=0;i<2;i++) {
|
||||
bytes[i] = 0x00;
|
||||
}
|
||||
System.arraycopy(uint16,0,bytes,2,uint16.length);
|
||||
return byteArrayToInt(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个uint16转为的int,通过本函数再次转为byte[]
|
||||
* @param uint16
|
||||
* @return
|
||||
*/
|
||||
public static byte[] uint16ToByteArray(int uint16){
|
||||
byte[] result = new byte[2];
|
||||
for (int i = 0; i<2; i++) {
|
||||
int offset = (result.length - 1 - i) * 8;
|
||||
result[i] = (byte) ((uint16 >>> offset) & 0xff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* uint16转long
|
||||
* @param uint16
|
||||
* @return
|
||||
*/
|
||||
public static long uint16ToLong(byte[] uint16){
|
||||
return uint16ToInt(uint16);
|
||||
}
|
||||
|
||||
/**
|
||||
* uint32转long
|
||||
* @param uint32
|
||||
* @return
|
||||
*/
|
||||
public static long uint32ToLong(byte[] uint32){
|
||||
if(uint32.length!=4){
|
||||
return Long.parseLong(null);
|
||||
}
|
||||
byte[] bytes=new byte[64];
|
||||
for(int i=0;i<4;i++) {
|
||||
bytes[i] = 0x00;
|
||||
}
|
||||
System.arraycopy(uint32,0,bytes,4,uint32.length);
|
||||
return byteArrayToLong(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个uint32转为的long,通过本函数再次转为byte[]
|
||||
* @param uint32
|
||||
* @return
|
||||
*/
|
||||
public static byte[] uint32ToByteArray(long uint32){
|
||||
byte[] result = new byte[4];
|
||||
for (int i = 0; i<4; i++) {
|
||||
int offset = (result.length - 1 - i) * 8;
|
||||
result[i] = (byte) ((uint32 >>> offset) & 0xff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* uint64转long
|
||||
* todo: 理论上可能发生越界
|
||||
* @param uint64
|
||||
* @return
|
||||
*/
|
||||
public static long uint64ToLong(byte[] uint64){
|
||||
if(uint64.length!=8){
|
||||
return Long.parseLong(null);
|
||||
}
|
||||
return byteArrayToLong(uint64);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一个uint64转为的long,通过本函数再次转为byte[]
|
||||
* todo: 理论上可能发生越界
|
||||
* @param uint64
|
||||
* @return
|
||||
*/
|
||||
public static byte[] uint64ToByteArray(long uint64){
|
||||
byte[] result = new byte[8];
|
||||
for (int i = 0; i<8; i++) {
|
||||
int offset = (result.length - 1 - i) * 8;
|
||||
result[i] = (byte) ((uint64 >>> offset) & 0xff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// short整型转为byte类型的数组
|
||||
// private static byte[] unsigned_short_2byte(int length) {
|
||||
// byte[] targets = new byte[2];
|
||||
// for (int i = 0; i < 2; i++) {
|
||||
// int offset = (targets.length - 1 - i) * 8;
|
||||
// targets[i] = (byte) ((length >>> offset) & 0xff);
|
||||
// }
|
||||
// return targets;
|
||||
// }
|
||||
|
||||
//测试:对于uint8,应当测试1 127 128
|
||||
public static void main(String[] args){
|
||||
|
||||
// byte[] testBytes={0x01,0x02};
|
||||
// for(int i=0;i<2;i++) {
|
||||
// System.out.println(testBytes[i]&0xFF);
|
||||
//// System.out.println(Integer.toHexString(testBytes[i]&0xFF));
|
||||
// }
|
||||
byte b=-1;
|
||||
System.out.println(b&0xff);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user