diff --git a/pom.xml b/pom.xml index 8fa4433..115f598 100644 --- a/pom.xml +++ b/pom.xml @@ -76,6 +76,14 @@ + + + + org.mapdb + mapdb + 3.0.8 + + \ No newline at end of file diff --git a/src/main/java/component/CanBePrefix.java b/src/main/java/component/CanBePrefix.java new file mode 100644 index 0000000..8cdae09 --- /dev/null +++ b/src/main/java/component/CanBePrefix.java @@ -0,0 +1,87 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示内容兴趣包中的组件 CanBePrefix + * @Version: 1.0.0 + * @Date: 11:33 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class CanBePrefix implements TlvComponentBase,InitialAble, IEncodingAble { + // 成员变量 + private boolean canBePrefix; + + // 函数 + public void setCanBePrefix(boolean canBePrefix){ + this.canBePrefix=canBePrefix; + this.doInitial(); + } + + public boolean getCanBePrefix(){ + return this.canBePrefix; + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 CanBePrefix 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + // 这是一个存在性组件,所以如果值为false,则无需编码 + if(!this.canBePrefix){ + return 0; + } + + int totalLength=0; + + // 编码 TLV-LENGTH + int tmplen=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen=encoder.prependVarNumber(new VlInt(TLV.TlvCanBePrefix)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码一个 CanBePrefix + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvCanBePrefix))){ + return false; + } + + // 这是一个存在性组件,所以存在则为 true + this.canBePrefix=true; + return true; + } +} diff --git a/src/main/java/component/CongestionMark.java b/src/main/java/component/CongestionMark.java new file mode 100644 index 0000000..f2d044b --- /dev/null +++ b/src/main/java/component/CongestionMark.java @@ -0,0 +1,94 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description:表示一个拥塞标记 TLV 组件 + * @Version: 1.0.0 + * @Date: 15:54 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class CongestionMark implements TlvComponentBase,InitialAble, IEncodingAble { + // 成员变量 todo: 越界问题 + private long congestionMark; + + // 函数 + public long getCongestionLevel(){ + return this.congestionMark; + } + + public void setCongestionLevel(long congestionMark){ + this.congestionMark=congestionMark; + this.doInitial(); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 CongestionMark 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV-VALUE + int tmplen=encoder.prependNonNegativeInteger(this.congestionMark); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-LENGTH + tmplen+=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen+=encoder.prependVarNumber(new VlInt(TLV.TlvCongestionMark)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 CongestionMark + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvCongestionMark))){ + return false; + } + + // 读取 CongestionMark + long value=TLV.readNonNegativeInteger(block.getValue(),0,block.getLength().getVlIntValue2Int()); + if(value<0){ + return false; + } + this.setCongestionLevel(value); + + return true; + } +} diff --git a/src/main/java/component/FreshnessPeriod.java b/src/main/java/component/FreshnessPeriod.java new file mode 100644 index 0000000..bb07c1c --- /dev/null +++ b/src/main/java/component/FreshnessPeriod.java @@ -0,0 +1,94 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示一个内容的新鲜期 TLV 组件 + * @Version: 1.0.0 + * @Date: 16:10 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class FreshnessPeriod implements TlvComponentBase,InitialAble, IEncodingAble { + // 成员变量 + private long freshnessPeriod; + + // 函数 + public long getFreshnessPeriod() { + return this.freshnessPeriod; + } + + public void setFreshnessPeriod(long freshnessPeriod) { + this.freshnessPeriod = freshnessPeriod; + this.doInitial(); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 FreshnessPeriod 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV-VALUE + int tmplen=encoder.prependNonNegativeInteger(this.freshnessPeriod); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-LENGTH + tmplen+=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen+=encoder.prependVarNumber(new VlInt(TLV.TlvFreshnessPeriod)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 FreshnessPeriod + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvFreshnessPeriod))){ + return false; + } + + // 读取 value + long value=TLV.readNonNegativeInteger(block.getValue(),0,block.getLength().getVlIntValue2Int()); + if(value<0){ + return false; + } + this.setFreshnessPeriod(value); + + return true; + } +} diff --git a/src/main/java/component/HopLimit.java b/src/main/java/component/HopLimit.java new file mode 100644 index 0000000..6c26e96 --- /dev/null +++ b/src/main/java/component/HopLimit.java @@ -0,0 +1,89 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 16:38 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class HopLimit implements TlvComponentBase,InitialAble, IEncodingAble { + // 成员变量 + private long hopLimit; + + // 成员函数 + public long getHopLimit() { + return hopLimit; + } + + public void setHopLimit(long hopLimit) { + this.hopLimit = hopLimit; + this.doInitial(); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV-VALUE + int tmplen=encoder.prependNonNegativeInteger(this.hopLimit); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-LENGTH + tmplen+=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen+=encoder.prependVarNumber(new VlInt(TLV.TlvHopLimit)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvHopLimit))){ + return false; + } + + // 读取 HopLimit + long value=TLV.readNonNegativeInteger(block.getValue(),0,block.getLength().getVlIntValue2Int()); + if(value<0){ + return false; + } + this.setHopLimit(value); + + return true; + } +} diff --git a/src/main/java/component/IdentifierComponent.java b/src/main/java/component/IdentifierComponent.java new file mode 100644 index 0000000..d48540d --- /dev/null +++ b/src/main/java/component/IdentifierComponent.java @@ -0,0 +1,47 @@ +package component; + +/* + * @Author: Wang Feng + * @Description: 名称组件 + * @Version: 1.0.0 + * @Date: 21:26 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ + +import encoding.Block; +import encoding.Encoder; +import encoding.IEncodingAble; + +// @Description: +// 1. 参考 => https://named-data.net/doc/tech-memos/naming-conventions.pdf ,借鉴但不是按这个实现的 +// 2. 格式如下: +// IdentifierComponent = 100 TLV-LENGTH +// +// *OCTET +// Marker = OCTET +// 3. Marker 用来标记不同类型的 IdentifierComponent,目前分配如下 +// Marker value Description +// 0x00 普通的UTF-8编码的字符串 +// 0x01 非负整数(可以用1、2、4、8个字节表示) +// 0x02 任意字节数组 +public class IdentifierComponent implements TlvComponentBase, IEncodingAble { + private Block block; + private byte marker; // 标记 => 用来区分不同类型的 IdentifierComponent + private String stringValue; // 如果 Marker == 0x00,则本组件存储一个字符串 + private long intValue; // 如果 Marker == 0x01,则本组件存储一个非负整型 + private byte[] byteArrayValue; // 如果 Marker == 0x02,则本组件存储一个字节数组 + + public static final byte MarkerString = 0x00; + public static final byte MarkerNonNegativeInteger = 0x01; + public static final byte MarkerByteArray = 0x02; + + @Override + public int wireEncode(Encoder encoder) { + return 0; + } + + @Override + public boolean wireDecode(Block block) { + return false; + } +} diff --git a/src/main/java/component/InitialAble.java b/src/main/java/component/InitialAble.java new file mode 100644 index 0000000..91d8a71 --- /dev/null +++ b/src/main/java/component/InitialAble.java @@ -0,0 +1,21 @@ +package component; + +/* + * @Author: Wang Feng + * @Description: 指示当前组件是否有初始化,如果没有初始化,且组件是可选组件,则无需编码 + * @Version: 1.0.0 + * @Date: 10:15 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public interface InitialAble { + // 指示当前组件是否有初始化,如果没有初始化,且组件是可选组件,则无需编码. + // 接口中的变量都是final类型的(常量)。因此,如果需要一个变量, + // 需要在实现该接口的类中定义该变量。 + // boolean initial = false; + + // 将组件标记为已初始化 + public void doInitial(); + + // 判断当前组件是否已经初始化 + public boolean isInitial(); +} diff --git a/src/main/java/component/InterestLifeTime.java b/src/main/java/component/InterestLifeTime.java new file mode 100644 index 0000000..b7ec99f --- /dev/null +++ b/src/main/java/component/InterestLifeTime.java @@ -0,0 +1,94 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 19:46 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class InterestLifeTime implements TlvComponentBase,InitialAble, IEncodingAble { + // 变量 + private long interestLifeTime; + + // 方法 + public long getInterestLifeTime() { + return interestLifeTime; + } + + public void setInterestLifeTime(long interestLifeTime) { + this.interestLifeTime = interestLifeTime; + this.doInitial(); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 InterestLifeTime 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV-VALUE + int tmplen=encoder.prependNonNegativeInteger(this.interestLifeTime); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-LENGTH + tmplen+=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen+=encoder.prependVarNumber(new VlInt(TLV.TlvInterestLifeTime)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 InterestLifeTime + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvInterestLifeTime))){ + return false; + } + + // 读取 value + long value=TLV.readNonNegativeInteger(block.getValue(),0,block.getLength().getVlIntValue2Int()); + if(value<0){ + return false; + } + this.setInterestLifeTime(value); + + return true; + } +} diff --git a/src/main/java/component/MustBeRefresh.java b/src/main/java/component/MustBeRefresh.java new file mode 100644 index 0000000..c14ee00 --- /dev/null +++ b/src/main/java/component/MustBeRefresh.java @@ -0,0 +1,87 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示内容兴趣包中的组件 MustBeRefresh + * @Version: 1.0.0 + * @Date: 16:30 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class MustBeRefresh implements TlvComponentBase,InitialAble, IEncodingAble { + // 成员变量 + private boolean mustBeRefresh; + + // 函数 + public boolean getMustBeRefresh() { + return mustBeRefresh; + } + + public void setMustBeRefresh(boolean mustBeRefresh) { + this.mustBeRefresh = mustBeRefresh; + this.doInitial(); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 MustBeRefresh 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + // 这是一个存在性组件,所以如果值为false,则无需编码 + if(!this.mustBeRefresh){ + return 0; + } + + int totalLength=0; + + // 编码 TLV-LENGTH + int tmplen=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen=encoder.prependVarNumber(new VlInt(TLV.TlvMustBeRefresh)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 MustBeRefresh + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvMustBeRefresh))){ + return false; + } + + // 这是一个存在性组件,所以存在则为 true + this.mustBeRefresh=true; + return true; + } +} diff --git a/src/main/java/component/MutableDangerousField.java b/src/main/java/component/MutableDangerousField.java new file mode 100644 index 0000000..04450a9 --- /dev/null +++ b/src/main/java/component/MutableDangerousField.java @@ -0,0 +1,114 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示一个MIN包格式中的可变非受保护区 + * @Version: 1.0.0 + * @Date: 20:34 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class MutableDangerousField implements TlvComponentBase, IEncodingAble { + private ElementContainer blocks; + + /** + * 往可变非受保护区添加一个Block + * @param block + */ + public void addBlock(Block block){ + blocks.addElement(block); + } + + /** + * 获取可变非受保护区指定位置的 Block + * @return + */ + public Block getBlock(int index){ + return this.blocks.getBlock(index); + } + + /** + * 清空可变非受保护区中,所有的子 Block + */ + public void clearBlocks(){ + this.blocks.clear(); + } + + /** + * 获取可变非受保护区所有的 Block + * @return + */ + public ElementContainer getBlocks(){ + return this.blocks; + } + + /** + * 获取可变非受保护区中,第一个指定TLV-TYPE的子 TLV Block + * @return + */ + public Block getBlockByType(VlInt tlvType){ + return this.blocks.getElement(tlvType); + } + + /** + * 将可变非受保护区线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + // 如果可变非受保护区没有任何子 TLV,则可以去掉可变非受保护区 TLV + if(this.blocks.length()==0){ + return 0; + } + + int totalLength=0; + // 编码TLV-VALUE + // 反向遍历,可以保证解码的时候正向输出 + for(int i=this.blocks.length()-1;i>=0;i++){ + int tmplen=encoder.prependBlock(this.blocks.getBlock(i)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + } + + // 编码 TLV-LENGTH + int tmplen=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen=encoder.prependVarNumber(new VlInt(TLV.TlvReadOnlyField)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 ReadOnlyField + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvReadOnlyField))){ + return false; + } + + // 解析子 TLV + if(!block.parseSubElements()){ + return false; + } + + this.blocks=block.getSubElements(); + return true; + } +} diff --git a/src/main/java/component/MutableField.java b/src/main/java/component/MutableField.java new file mode 100644 index 0000000..546d6ab --- /dev/null +++ b/src/main/java/component/MutableField.java @@ -0,0 +1,98 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示一个MIN包格式中的可变区 + * @Version: 1.0.0 + * @Date: 20:48 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class MutableField implements TlvComponentBase,IEncodingAble { + private MutableProtectField mutableProtectField; + private MutableDangerousField mutableDangerousField; + + public MutableField(){ + mutableProtectField=new MutableProtectField(); + mutableDangerousField=new MutableDangerousField(); + } + + /** + * 将可变区线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV—VALUE + int tmplen=this.mutableDangerousField.wireEncode(encoder); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + tmplen=this.mutableProtectField.wireEncode(encoder); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 如果可变保护区和可变非受保护区均为空,则可以去掉可变区 + if(totalLength==0){ + return 0; + } + + // 编码 TLV-LENGTH + tmplen=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen=encoder.prependVarNumber(new VlInt(TLV.TlvMutableField)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 MutableField + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvMutableField))){ + return false; + } + + // 解析子 TLV + if(!block.parseSubElements()){ + return false; + } + + for (int i = 0; i < block.getSubElements().length(); i++) { + Block subBlock=block.getSubElements().getBlock(i); + if(subBlock.getTlvType().isEqual(TLV.TlvMutableProtectField)){ + if(!this.mutableProtectField.wireDecode(subBlock)){ + return false; + } + }else if(subBlock.getTlvType().isEqual(TLV.TlvMutableDangerousField)){ + if(!this.mutableDangerousField.wireDecode(subBlock)){ + return false; + } + }else{ + return false; + } + } + + return false; + } +} diff --git a/src/main/java/component/MutableProtectField.java b/src/main/java/component/MutableProtectField.java new file mode 100644 index 0000000..bf889b8 --- /dev/null +++ b/src/main/java/component/MutableProtectField.java @@ -0,0 +1,114 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示一个MIN包格式中的可变保护区 + * @Version: 1.0.0 + * @Date: 20:45 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class MutableProtectField implements TlvComponentBase, IEncodingAble { + private ElementContainer blocks; + + /** + * 添加一个Block + * @param block + */ + public void addBlock(Block block){ + blocks.addElement(block); + } + + /** + * 获取指定位置的 Block + * @return + */ + public Block getBlock(int index){ + return this.blocks.getBlock(index); + } + + /** + * 清空所有的子 Block + */ + public void clearBlocks(){ + this.blocks.clear(); + } + + /** + * 获取所有的 Block + * @return + */ + public ElementContainer getBlocks(){ + return this.blocks; + } + + /** + * 获取第一个指定TLV-TYPE的子 TLV Block + * @return + */ + public Block getBlockByType(VlInt tlvType){ + return this.blocks.getElement(tlvType); + } + + /** + * 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + // 如果没有任何子 TLV,则可以去掉它 + if(this.blocks.length()==0){ + return 0; + } + + int totalLength=0; + // 编码TLV-VALUE + // 反向遍历,可以保证解码的时候正向输出 + for(int i=this.blocks.length()-1;i>=0;i++){ + int tmplen=encoder.prependBlock(this.blocks.getBlock(i)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + } + + // 编码 TLV-LENGTH + int tmplen=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen=encoder.prependVarNumber(new VlInt(TLV.TlvReadOnlyField)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 ReadOnlyField + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvReadOnlyField))){ + return false; + } + + // 解析子 TLV + if(!block.parseSubElements()){ + return false; + } + + this.blocks=block.getSubElements(); + return true; + } +} diff --git a/src/main/java/component/NackHeader.java b/src/main/java/component/NackHeader.java new file mode 100644 index 0000000..a82de63 --- /dev/null +++ b/src/main/java/component/NackHeader.java @@ -0,0 +1,94 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 19:52 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class NackHeader implements TlvComponentBase,InitialAble, IEncodingAble { + // 变量 + private long nackReason; + + // 函数 + public long getNackReason() { + return nackReason; + } + + public void setNackReason(long nackReason) { + this.nackReason = nackReason; + this.doInitial(); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 NackHeader 编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV-VALUE + int tmplen=encoder.prependNonNegativeInteger(this.nackReason); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-LENGTH + tmplen+=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen+=encoder.prependVarNumber(new VlInt(TLV.TlvNackHeader)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 Block TLV 中解码出一个 NackHeader + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvNackHeader))){ + return false; + } + + // 读取 value + long value=TLV.readNonNegativeInteger(block.getValue(),0,block.getLength().getVlIntValue2Int()); + if(value<0){ + return false; + } + this.setNackReason(value); + + return true; + } +} diff --git a/src/main/java/component/Nonce.java b/src/main/java/component/Nonce.java new file mode 100644 index 0000000..1a88535 --- /dev/null +++ b/src/main/java/component/Nonce.java @@ -0,0 +1,104 @@ +package component; + +import encoding.*; + +import java.util.Random; + +/* + * @Author: Wang Feng + * @Description: 表示一个随机数 TLV 组件 + * @Version: 1.0.0 + * @Date: 17:13 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class Nonce implements TlvComponentBase,InitialAble, IEncodingAble { + // 成员变量 + private long nonce; + + // 成员函数 + public long getNonce() { + return this.nonce; + } + + public void setNonce(long nonce) { + this.nonce = nonce; + this.doInitial(); + } + + /** + * 刷新Nonce,随机生成一个数值传递给Nonce + */ + public void refreshNonce(){ + long randomLong=Math.abs(new Random().nextLong()); + this.setNonce(randomLong); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 Nonce 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV-VALUE + int tmplen=encoder.prependNonNegativeInteger(this.nonce); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-LENGTH + tmplen+=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen+=encoder.prependVarNumber(new VlInt(TLV.TlvNonce)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 Nonce + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvNonce))){ + return false; + } + + // 读取 value + long value=TLV.readNonNegativeInteger(block.getValue(),0,block.getLength().getVlIntValue2Int()); + if(value<0){ + return false; + } + this.setNonce(value); + + return true; + } +} diff --git a/src/main/java/component/Payload.java b/src/main/java/component/Payload.java new file mode 100644 index 0000000..d26577a --- /dev/null +++ b/src/main/java/component/Payload.java @@ -0,0 +1,107 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示网络包负载 +// 1. 格式如下: +// Payload = PAYLOAD-TYPE TLV-LENGTH *OCTET +// 2. 详情参见:http://gitea.qjm253.cn/PKUSZ-future-network-lab/minlib/src/branch/master/docs/PacketFormat.md#4-signature + * @Version: 1.0.0 + * @Date: 19:26 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class Payload implements TlvComponentBase,InitialAble, IEncodingAble { + // 成员变量 + private byte[] value; + + // 函数 + /** + * 根据 TLV Block 初始化一个 Payload + * @param block + * @return + */ + public boolean buildPayloadByBlock(Block block){ + return this.wireDecode(block); + } + + /** + * 得到Payload TLV中实际包含的数据 + * @return + */ + public byte[] getValue() { + return value; + } + + /** + * 设置 Payload TLV 中的Value + * @param value + */ + public void setValue(byte[] value) { + this.value = value; + this.doInitial(); + } + + // 接口实现-变量区 + private boolean initial=false; + + // 接口实现-方法区 + @Override + public void doInitial() { + initial=true; + } + + @Override + public boolean isInitial() { + return initial; + } + + /** + * 将 Payload 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + + // 编码 TLV-VALUE + int tmplen=encoder.prependByteArray(this.value,new SizeT(this.value.length)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-LENGTH + tmplen+=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen+=encoder.prependVarNumber(new VlInt(TLV.TlvPayload)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvPayload))){ + return false; + } + + // 存储Value +// int len=block.getLength().getVlIntValue2Int(); +// byte[] bytes=new byte[len]; +// System.arraycopy(block.getValue(),0,bytes,0,len); + this.setValue(block.getValue()); + return true; + } +} diff --git a/src/main/java/component/ReadOnlyField.java b/src/main/java/component/ReadOnlyField.java new file mode 100644 index 0000000..78d019c --- /dev/null +++ b/src/main/java/component/ReadOnlyField.java @@ -0,0 +1,114 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: 表示一个MIN包格式中的只读区 + * @Version: 1.0.0 + * @Date: 19:58 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class ReadOnlyField implements TlvComponentBase, IEncodingAble { + private ElementContainer blocks; + + /** + * 往只读区添加一个Block + * @param block + */ + public void addBlock(Block block){ + blocks.addElement(block); + } + + /** + * 获取只读区指定位置的 Block + * @return + */ + public Block getBlock(int index){ + return this.blocks.getBlock(index); + } + + /** + * 清空只读区中,所有的子 Block + */ + public void clearBlocks(){ + this.blocks.clear(); + } + + /** + * 获取只读区所有的 Block + * @return + */ + public ElementContainer getBlocks(){ + return this.blocks; + } + + /** + * 获取只读区中,第一个指定TLV-TYPE的子 TLV Block + * @return + */ + public Block getBlockByType(VlInt tlvType){ + return this.blocks.getElement(tlvType); + } + + /** + * 将只读区线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + // 如果只读区没有任何子 TLV,则可以去掉只读区 TLV + if(this.blocks.length()==0){ + return 0; + } + + int totalLength=0; + // 编码TLV-VALUE + // 反向遍历,可以保证解码的时候正向输出 + for(int i=this.blocks.length()-1;i>=0;i++){ + int tmplen=encoder.prependBlock(this.blocks.getBlock(i)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + } + + // 编码 TLV-LENGTH + int tmplen=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + // 编码 TLV-TYPE + tmplen=encoder.prependVarNumber(new VlInt(TLV.TlvReadOnlyField)); + if(tmplen==0){ + return 0; + } + totalLength+=tmplen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 ReadOnlyField + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查 Type 是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvReadOnlyField))){ + return false; + } + + // 解析子 TLV + if(!block.parseSubElements()){ + return false; + } + + this.blocks=block.getSubElements(); + return true; + } +} diff --git a/src/main/java/component/TTL.java b/src/main/java/component/TTL.java new file mode 100644 index 0000000..35fe92b --- /dev/null +++ b/src/main/java/component/TTL.java @@ -0,0 +1,101 @@ +package component; + +import encoding.*; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 10:20 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class TTL implements IEncodingAble { + /** + * 表示一个 TTL Tlv + * todo: 后台使用的uint64,故这里用long表示,则理论上可能越界 + * // @Description: + * 1. 格式如下: + * TTL = TTL-TYPE TLV-LENGTH NonNegativeInteger + */ + private long ttl; + + public TTL(Block block){ + buildTTLByBlock(block); + } + + /** + * 根据 TLV Block 初始化一个 TTL + * @param block + * @return + */ + public boolean buildTTLByBlock(Block block){ + return this.wireDecode(block); + } + + /** + * 获取 TTL 值 + * @return + */ + public long ttl(){ + return this.ttl; + } + + /** + * 设置 TTL 值 + * @param ttl + */ + public void setTtl(long ttl){ + this.ttl=ttl; + } + + /** + * 将 TTL 线速编码为一个 TLV + * @param encoder + * @return + */ + @Override + public int wireEncode(Encoder encoder) { + int totalLength=0; + // 编码 TLV-VALUE + int tmpLen=encoder.prependNonNegativeInteger(this.ttl); + if(tmpLen==0){ + return 0; + } + totalLength+=tmpLen; + + // 编码 TLV-LENGTH + tmpLen=encoder.prependVarNumber(new VlInt(totalLength)); + if(tmpLen==0){ + return 0; + } + totalLength+=tmpLen; + + // 编码 TLV-TYPE + tmpLen=encoder.prependVarNumber(new VlInt(TLV.TlvTTL)); + if(tmpLen==0){ + return 0; + } + totalLength+=tmpLen; + + return totalLength; + } + + /** + * 从 TLV Block 中解码出一个 TTL + * @param block + * @return + */ + @Override + public boolean wireDecode(Block block) { + // 检查Type是否正确 + if(!TLV.expectType(block.getTlvType(),new VlInt(TLV.TlvTTL))){ + return false; + } + long value=TLV.readNonNegativeInteger(block.getValue(),0,block.getLength().getVlIntValue2Int()); + if(value<0){ + return false; + } + this.ttl=value; + return true; + } +} diff --git a/src/main/java/component/TlvComponentBase.java b/src/main/java/component/TlvComponentBase.java new file mode 100644 index 0000000..b866156 --- /dev/null +++ b/src/main/java/component/TlvComponentBase.java @@ -0,0 +1,12 @@ +package component; + +/* + * @Author: Wang Feng + * @Description: 实现所有 TLV 组件需要的一些通用功能 + * @Version: 1.0.0 + * @Date: 21:49 2021/3/6 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public interface TlvComponentBase { + +} diff --git a/src/main/java/encoding/Block.java b/src/main/java/encoding/Block.java index 8fa9f36..ed95fcc 100644 --- a/src/main/java/encoding/Block.java +++ b/src/main/java/encoding/Block.java @@ -13,73 +13,6 @@ import java.util.List; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -// TLV 组件容器 -class ElementContainer{ - private List elementContainer; - public ElementContainer(){ - elementContainer = new LinkedList<>(); - } - - /** - * 获取所有Block - * @return - */ - public List getElements(){ - return elementContainer; - } - - /** - * 获取block个数 - * @return - */ - public int length(){ - return elementContainer.size(); - } - - /** - * 清除 elements 中所有的子TLV - */ - public void clear(){ - elementContainer.clear(); - } - - /** - * 往 elements 中添加一个子tlv - * @param block - */ - public void addElement(Block block){ - elementContainer.add(block); - } - - /** - * 移除所有指定type的子tlv - * @param tlvType - */ - public void removeElements(VlInt tlvType){ - List elementContainer=new LinkedList<>(); - for(Block block: this.elementContainer){ - if(!block.getTlvType().isEqual(tlvType)){ - elementContainer.add(block); - } - } - this.elementContainer =elementContainer; - } - - /** - * 从 elements 中找到第一个指定type的子TLV - * @param tlvType - * @return - */ - public Block getElement(VlInt tlvType){ - for(Block block: this.elementContainer){ - if(block.getTlvType().isEqual(tlvType)){ - return block; - } - } - return null; - } -} - public class Block { private VlInt tlvType; // TLV-TYPE private VlInt length; // TLV-LENGTH diff --git a/src/main/java/encoding/ElementContainer.java b/src/main/java/encoding/ElementContainer.java new file mode 100644 index 0000000..c57f682 --- /dev/null +++ b/src/main/java/encoding/ElementContainer.java @@ -0,0 +1,86 @@ +package encoding; + +import java.util.LinkedList; +import java.util.List; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 20:01 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +// TLV 组件容器 +public class ElementContainer{ + private List elementContainer; + public ElementContainer(){ + elementContainer = new LinkedList<>(); + } + + /** + * 获取所有Block + * @return + */ + public List getElements(){ + return elementContainer; + } + + /** + * 获取block个数 + * @return + */ + public int length(){ + return elementContainer.size(); + } + + /** + * 清除 elements 中所有的子TLV + */ + public void clear(){ + elementContainer.clear(); + } + + /** + * 往 elements 中添加一个子tlv + * @param block + */ + public void addElement(Block block){ + elementContainer.add(block); + } + + /** + * 移除所有指定type的子tlv + * @param tlvType + */ + public void removeElements(VlInt tlvType){ + List elementContainer=new LinkedList<>(); + for(Block block: this.elementContainer){ + if(!block.getTlvType().isEqual(tlvType)){ + elementContainer.add(block); + } + } + this.elementContainer =elementContainer; + } + + /** + * 从 elements 中找到第一个指定type的子TLV + * @param tlvType + * @return + */ + public Block getElement(VlInt tlvType){ + for(Block block: this.elementContainer){ + if(block.getTlvType().isEqual(tlvType)){ + return block; + } + } + return null; + } + + public Block getBlock(int index){ + if(index>=this.length()){ + return null; + } + + return this.elementContainer.get(index); + } +} \ No newline at end of file diff --git a/src/main/java/encoding/Encoder.java b/src/main/java/encoding/Encoder.java index 4c1463b..0a2f870 100644 --- a/src/main/java/encoding/Encoder.java +++ b/src/main/java/encoding/Encoder.java @@ -122,6 +122,46 @@ public class Encoder { } + /** + * 编码一个非负整数到一个数组当中 + * todo: 越界问题 + * @param uint64 + * @return + */ + public byte[] buildNonNegativeIntegerArr(long uint64){ + VlInt vlInt=new VlInt(uint64); + int len=vlInt.getVlIntBytes().length; + if(len==1){ + return vlInt.getVlIntBytes(); + }else { + byte[] res = new byte[len - 1]; + System.arraycopy(vlInt.getVlIntBytes(),1,res,0,len-1); + return res; + } + } + + /** + * 在前向插入一个非负整数,最大为 uint64::Max + * todo: 越界问题 + * @param uint64_value + * @return + */ + public int prependNonNegativeInteger(long uint64_value){ + byte[] bytes=buildNonNegativeIntegerArr(uint64_value); + return this.prependByteArray(bytes,new SizeT(bytes.length)); + } + + /** + * 在后向插入一个非负整数,最大为 uint64::Max + * todo: 越界问题 + * @param uint64_value + * @return + */ + public int appendNonNegativeInteger(long uint64_value){ + byte[] bytes=buildNonNegativeIntegerArr(uint64_value); + return this.appendByteArray(bytes,new SizeT(bytes.length)); + } + /** * @param array * @param size diff --git a/src/main/java/encoding/IEncodingAble.java b/src/main/java/encoding/IEncodingAble.java new file mode 100644 index 0000000..d1a23d5 --- /dev/null +++ b/src/main/java/encoding/IEncodingAble.java @@ -0,0 +1,27 @@ +package encoding; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 21:06 2021/3/7 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public interface IEncodingAble { + /** + * 线速编码,将一个包编码成网络可传输的格式 + * @Description: + * 1. 可以使用 Encoder.getBuffer() 获取编码的结果 + * @param encoder + * @return + */ + public int wireEncode(Encoder encoder); + + /** + * 线速解码,将一个TLV解码成一个网络包 + * @param block + * @return + */ + public boolean wireDecode(Block block); + +} diff --git a/src/main/java/encoding/TLV.java b/src/main/java/encoding/TLV.java index c6d89d0..4a55963 100644 --- a/src/main/java/encoding/TLV.java +++ b/src/main/java/encoding/TLV.java @@ -117,7 +117,32 @@ public class TLV { return tlvType; } - // todo:从字节数组的指定位置中读取一个非负整型 + /** + * 从字节数组的指定位置中读取一个非负整型 + * todo: 越界问题 + */ + public static long readNonNegativeInteger(byte[] buffer,int start,int end){ + if(start==end){ + return -1; + } + if((start<0)||(end>buffer.length)){ + return -1; + } + int len=end-start; + byte[] bytes=new byte[len]; + System.arraycopy(buffer,start,bytes,0,len); + if(len==1){ + return ByteHelper.uint8ToLong(buffer[start]); + }else if(len==2){ + return ByteHelper.uint16ToLong(bytes); + }else if(len==4){ + return ByteHelper.uint32ToLong(bytes); + }else if(len==8){ + return ByteHelper.uint64ToLong(bytes); + }else{ + return -1; + } + } /** * 检查某个type值是否是指定的 TLV-TYPE diff --git a/src/main/java/minsecurity/certificate/X509/X509CertMaker.java b/src/main/java/minsecurity/certificate/X509/X509CertMaker.java index dabc5ab..0333fce 100644 --- a/src/main/java/minsecurity/certificate/X509/X509CertMaker.java +++ b/src/main/java/minsecurity/certificate/X509/X509CertMaker.java @@ -1,7 +1,6 @@ package minsecurity.certificate.X509; -import minsecurity.Common; -import minsecurity.crypto.sm2.Sm2Base; +import minsecurity.crypto.sm2.SM2Base; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; @@ -34,7 +33,7 @@ public class X509CertMaker { String ou, String cn, long expireTimeInMs, String signAlgo) throws Exception { - KeyPair rootKP = Sm2Base.generateKeyPair(); + KeyPair rootKP = SM2Base.generateKeyPair(); return makeRootCA(rootKP, c, o, ou, cn, expireTimeInMs, signAlgo); } @@ -116,7 +115,7 @@ public class X509CertMaker { public static void main(String[] args) { try { - KeyPair rootKP = Sm2Base.generateKeyPair(); + KeyPair rootKP = SM2Base.generateKeyPair(); X509Certificate rootCA = makeRootCA(rootKP,"CN","MIN", "MIN-GROUP","MIN ROOT CA", 365L * 24 * 60 * 60 * 1000, "SM3withSM2"); diff --git a/src/main/java/minsecurity/certificate/cert/CertUtils.java b/src/main/java/minsecurity/certificate/cert/CertUtils.java index 3859630..8c95094 100644 --- a/src/main/java/minsecurity/certificate/cert/CertUtils.java +++ b/src/main/java/minsecurity/certificate/cert/CertUtils.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import minsecurity.Common; import minsecurity.crypto.*; -import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.slf4j.LoggerFactory; import javax.crypto.BadPaddingException; @@ -70,7 +69,7 @@ public class CertUtils { certificate.setVersion(i.getTbsCertificate().getVersion()); certificate.setSerialNumber(i.getTbsCertificate().getSerialNumber()); - PublicKeyInterface publicKey = PublicKeyUtils.unMarshalPublicKey(i.getTbsCertificate().getPublicKey(),i.getSignatureAlgorithm()); + PublicKeyInterface publicKey = KeyUtils.unMarshalPublicKey(i.getTbsCertificate().getPublicKey(),i.getSignatureAlgorithm()); certificate.setPublicKey(publicKey); certificate.setSignature(i.getSignatureValue()); certificate.setSignatureAlgorithm(i.getTbsCertificate().getSignatureAlgorithm()); @@ -250,23 +249,17 @@ public class CertUtils { byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(certificate)); byte[] ret; if(passwd != null && passwd.length > 0){ - byte[] hashPasswd = HashAlgo.sm3(passwd); - if( hashPasswd.length == 32){ - for(int i = 0; i < 16; i++){ - hashPasswd[i] += hashPasswd[i + 16]; - } - } - byte[] sm4Key = new byte[16]; - System.arraycopy(hashPasswd,0,sm4Key,0,16); + // byte[] sm4Key; + byte[] sm4Key = KeyUtils.get16bytePasswd(passwd); switch (symAlgoMode){ case Common.SM4CBC:{ // TODO: PADDING??? IV????? - ret = Sm4.encrypt_CBC_Padding(sm4Key, new byte[16],bytesOfCert); + ret = SM4.encrypt_CBC_Padding(sm4Key, new byte[16],bytesOfCert); break; } case Common.SM4ECB:{ - ret = Sm4.encrypt_ECB_Padding(sm4Key, bytesOfCert); + ret = SM4.encrypt_ECB_Padding(sm4Key, bytesOfCert); break; } default: @@ -294,21 +287,13 @@ public class CertUtils { byte[] bytesOfPem = Base64.getDecoder().decode(pemString); byte[] bytesOfCert = new byte[0]; if(passwd != null && passwd.length > 0){ - byte[] hashPasswd = HashAlgo.sm3(passwd); - if( hashPasswd.length == 32){ - for(int i = 0; i < 16; i++){ - hashPasswd[i] += hashPasswd[i + 16]; - } - } - byte[] sm4Key = new byte[16]; - System.arraycopy(hashPasswd,0,sm4Key,0,16); - + byte[] sm4Key = KeyUtils.get16bytePasswd(passwd); switch (symAlgoMode){ case Common.SM4CBC: - bytesOfCert = Sm4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem); + bytesOfCert = SM4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem); break; case Common.SM4ECB: - bytesOfCert = Sm4.decrypt_ECB_Padding(sm4Key, bytesOfPem); + bytesOfCert = SM4.decrypt_ECB_Padding(sm4Key, bytesOfPem); break; } } else { diff --git a/src/main/java/minsecurity/certificate/cert/Certificate.java b/src/main/java/minsecurity/certificate/cert/Certificate.java index 2d19775..8c50bd4 100644 --- a/src/main/java/minsecurity/certificate/cert/Certificate.java +++ b/src/main/java/minsecurity/certificate/cert/Certificate.java @@ -1,26 +1,10 @@ package minsecurity.certificate.cert; -import minsecurity.Common; -import minsecurity.crypto.HashAlgo; -import minsecurity.crypto.PrivateKeyInterface; import minsecurity.crypto.PublicKeyInterface; -import minsecurity.crypto.Sm4; -import minsecurity.crypto.sm2.Sm2PublicKey; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.slf4j.LoggerFactory; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import java.lang.reflect.Array; -import java.security.*; -import java.util.Arrays; -import java.util.Base64; - -import static minsecurity.certificate.cert.CertUtils.*; - - /* * @Author: hongyu guo * @Description: 证书bean类 diff --git a/src/main/java/minsecurity/crypto/KeyUtils.java b/src/main/java/minsecurity/crypto/KeyUtils.java new file mode 100644 index 0000000..71ae11a --- /dev/null +++ b/src/main/java/minsecurity/crypto/KeyUtils.java @@ -0,0 +1,62 @@ +package minsecurity.crypto; + +import minsecurity.Common; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 16:02 2021/03/06 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class KeyUtils { + /** + * 返回的数据类型为PublicKeyInterface接口, 必要时调用者需要手动将类型强制转化为需要的类型 + * @param bytesOfPublicKey 公钥的bytes数组 + * @param algorithm 公钥类型 + * @return minsecurity.crypto.PublicKeyInterface + * @author ghy + * @date 2021/3/7 + **/ + public static PublicKeyInterface unMarshalPublicKey(byte[] bytesOfPublicKey, int algorithm) { + if (bytesOfPublicKey == null || bytesOfPublicKey.length == 0) { + return null; + } + switch (algorithm) { + case Common.SM2: + SM2PublicKey sm2PublicKey = new SM2PublicKey(); + sm2PublicKey.setBytes(bytesOfPublicKey); + return sm2PublicKey; + default: + return null; + } + } + + public static PrivateKeyInterface unMarshalPrivateKey(byte[] bytesOfPrivateKey, int algorithm){ + if(bytesOfPrivateKey == null || bytesOfPrivateKey.length == 0){ + return null; + } + switch (algorithm) { + case Common.SM2: + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(); + sm2PrivateKey.setBytes(bytesOfPrivateKey); + return sm2PrivateKey; + default: + return null; + } + } + + public static byte[] get16bytePasswd(byte[] passwd) { + byte[] hashPasswd = HashAlgo.sm3(passwd); + if( hashPasswd.length == 32){ + for(int i = 0; i < 16; i++){ + hashPasswd[i] += hashPasswd[i + 16]; + } + } + byte[] sm4Key = new byte[16]; + System.arraycopy(hashPasswd,0,sm4Key,0,16); + return sm4Key; + } +} diff --git a/src/main/java/minsecurity/crypto/PrivateKeyInterface.java b/src/main/java/minsecurity/crypto/PrivateKeyInterface.java index 7cd3cbd..ecd7b31 100644 --- a/src/main/java/minsecurity/crypto/PrivateKeyInterface.java +++ b/src/main/java/minsecurity/crypto/PrivateKeyInterface.java @@ -13,6 +13,6 @@ import org.bouncycastle.crypto.InvalidCipherTextException; public interface PrivateKeyInterface { public byte[] getBytes(); public boolean setBytes(byte[] bytes); - public byte[] decrypt(byte[] content) throws InvalidCipherTextException; + public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException; public byte[] sign(byte[] content) throws CryptoException; } diff --git a/src/main/java/minsecurity/crypto/PublicKeyUtils.java b/src/main/java/minsecurity/crypto/PublicKeyUtils.java deleted file mode 100644 index bf5baa3..0000000 --- a/src/main/java/minsecurity/crypto/PublicKeyUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -package minsecurity.crypto; - -import minsecurity.Common; -import minsecurity.crypto.sm2.Sm2PublicKey; - -/* - * @Author: hongyu guo - * @Description: - * @Version: 1.0.0 - * @Date: 16:02 2021/03/06 - * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 - */ -public class PublicKeyUtils { - /** - * 返回的数据类型为PublicKeyInterface接口, 必要时调用者需要手动将类型强制转化为需要的类型 - * @param bytesOfPublicKey 公钥的bytes数组 - * @param algorithm 公钥类型 - * @return minsecurity.crypto.PublicKeyInterface - * @author ghy - * @date 2021/3/7 - **/ - public static PublicKeyInterface unMarshalPublicKey(byte[] bytesOfPublicKey, int algorithm) { - if (bytesOfPublicKey == null || bytesOfPublicKey.length == 0) { - return null; - } - switch (algorithm) { - case Common.SM2: - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(); - sm2PublicKey.setBytes(bytesOfPublicKey); - return sm2PublicKey; - default: - return null; - } - } -} diff --git a/src/main/java/minsecurity/crypto/Sm4.java b/src/main/java/minsecurity/crypto/SM4.java similarity index 99% rename from src/main/java/minsecurity/crypto/Sm4.java rename to src/main/java/minsecurity/crypto/SM4.java index d0cc585..6830489 100644 --- a/src/main/java/minsecurity/crypto/Sm4.java +++ b/src/main/java/minsecurity/crypto/SM4.java @@ -14,7 +14,7 @@ import java.security.*; * @Date: 16:26 2021/03/04 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm4 { +public class SM4 { static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2Base.java b/src/main/java/minsecurity/crypto/sm2/SM2Base.java similarity index 98% rename from src/main/java/minsecurity/crypto/sm2/Sm2Base.java rename to src/main/java/minsecurity/crypto/sm2/SM2Base.java index bf86b64..b52a2cb 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2Base.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2Base.java @@ -1,6 +1,5 @@ package minsecurity.crypto.sm2; -import minsecurity.Common; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.ECDomainParameters; @@ -17,7 +16,6 @@ import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve; import org.slf4j.LoggerFactory; -import javax.crypto.KeyGenerator; import java.math.BigInteger; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; @@ -32,13 +30,13 @@ import static minsecurity.Common.ALGO_NAME_EC; * @Date: 18:48 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2Base { +public class SM2Base { static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Sm2Base.class); + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SM2Base.class); /* * 以下为SM2推荐曲线参数 diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2Exception.java b/src/main/java/minsecurity/crypto/sm2/SM2Exception.java similarity index 77% rename from src/main/java/minsecurity/crypto/sm2/Sm2Exception.java rename to src/main/java/minsecurity/crypto/sm2/SM2Exception.java index 0f31a91..79916b2 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2Exception.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2Exception.java @@ -7,8 +7,8 @@ package minsecurity.crypto.sm2; * @Date: 19:00 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2Exception extends java.lang.Exception { - public Sm2Exception(String msg){ +public class SM2Exception extends java.lang.Exception { + public SM2Exception(String msg){ super(msg); } } diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java b/src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java similarity index 84% rename from src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java rename to src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java index 9367ed5..51d4e1a 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java @@ -20,9 +20,9 @@ import java.security.SecureRandom; * @Date: 19:40 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2PrivateKey implements PrivateKeyInterface { +public class SM2PrivateKey implements PrivateKeyInterface { - public Sm2PrivateKey(){} + public SM2PrivateKey(){} /* * @param d @@ -37,24 +37,24 @@ public class Sm2PrivateKey implements PrivateKeyInterface { * @author hongyu guo * @date 2021/3/7 **/ - public Sm2PrivateKey(byte[] d) { + public SM2PrivateKey(byte[] d) { if(d.length == 32 || d.length == 33) - privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS); + privateKey = new ECPrivateKeyParameters(new BigInteger(d), SM2Base.DOMAIN_PARAMS); else { try { - throw new Sm2Exception("SM2私钥中,参数d长度应为32/33"); - } catch (Sm2Exception e) { + throw new SM2Exception("SM2私钥中,参数d长度应为32/33"); + } catch (SM2Exception e) { e.printStackTrace(); } } } - public Sm2PrivateKey(byte[] d, ECDomainParameters parameters){ + public 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) { + throw new SM2Exception("SM2私钥中,参数d长度应为32/33"); + } catch (SM2Exception e) { e.printStackTrace(); } } @@ -69,7 +69,7 @@ public class Sm2PrivateKey implements PrivateKeyInterface { public boolean setBytes(byte[] d) { if(d.length != 32 && d.length != 33) return false; - privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS); + privateKey = new ECPrivateKeyParameters(new BigInteger(d), SM2Base.DOMAIN_PARAMS); return true; } diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java b/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java similarity index 91% rename from src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java rename to src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java index 5b9e76a..cfdd7ce 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java @@ -20,11 +20,11 @@ import java.security.SecureRandom; * @Date: 17:32 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2PublicKey implements PublicKeyInterface { +public class SM2PublicKey implements PublicKeyInterface { - public Sm2PublicKey(){} + public SM2PublicKey(){} - public Sm2PublicKey(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){ + public SM2PublicKey(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){ publicKey = createPublicKey(xBytes,yBytes,curve,domainParameters); } /** @@ -35,11 +35,11 @@ public class Sm2PublicKey implements PublicKeyInterface { * @author ghy * @date 2021/3/7 **/ - public Sm2PublicKey(byte[] xBytes, byte[] yBytes){ - this(xBytes,yBytes, Sm2Base.CURVE, Sm2Base.DOMAIN_PARAMS); + public SM2PublicKey(byte[] xBytes, byte[] yBytes){ + this(xBytes,yBytes, SM2Base.CURVE, SM2Base.DOMAIN_PARAMS); } - public Sm2PublicKey(byte[] bytes){ + public SM2PublicKey(byte[] bytes){ setBytes(bytes); } @@ -105,7 +105,7 @@ public class Sm2PublicKey implements PublicKeyInterface { } private static ECPublicKeyParameters createPublicKey(byte[] xBytes, byte[] yBytes){ - return createPublicKey(xBytes,yBytes,Sm2Base.CURVE,Sm2Base.DOMAIN_PARAMS); + return createPublicKey(xBytes,yBytes, SM2Base.CURVE, SM2Base.DOMAIN_PARAMS); } private static int getCurveLength(ECDomainParameters domainParams) { diff --git a/src/main/java/minsecurity/crypto/sm2/SM4Exception.java b/src/main/java/minsecurity/crypto/sm2/SM4Exception.java new file mode 100644 index 0000000..c187c8c --- /dev/null +++ b/src/main/java/minsecurity/crypto/sm2/SM4Exception.java @@ -0,0 +1,14 @@ +package minsecurity.crypto.sm2; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 15:19 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class SM4Exception extends Exception{ + SM4Exception(String msg){ + super(msg); + } +} diff --git a/src/main/java/minsecurity/identity/Identity.java b/src/main/java/minsecurity/identity/Identity.java new file mode 100644 index 0000000..f678dd4 --- /dev/null +++ b/src/main/java/minsecurity/identity/Identity.java @@ -0,0 +1,270 @@ +package minsecurity.identity; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import minsecurity.Common; +import minsecurity.certificate.cert.CertException; +import minsecurity.certificate.cert.Certificate; +import minsecurity.crypto.KeyUtils; +import minsecurity.crypto.PrivateKeyInterface; +import minsecurity.crypto.PublicKeyInterface; +import minsecurity.crypto.SM4; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; +import org.bouncycastle.crypto.CryptoException; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.slf4j.LoggerFactory; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.IOException; +import java.io.Serializable; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.Arrays; +import java.util.Base64; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 20:25 2021/03/07 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class Identity { + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Identity.class); + private String Name; + private KeyParam KeyParam; + private PrivateKeyInterface Prikey; + private byte[] PrikeyRawByte; + private PublicKeyInterface Pubkey; + private String Passwd; + private Certificate Cert; + private boolean IsDefault; + + public Identity(String name, KeyParam keyParam, + PrivateKeyInterface prikey, byte[] prikeyRawByte, + PublicKeyInterface pubkey, String passwd, Certificate cert, + boolean isDefault) { + Name = name; + KeyParam = keyParam; + Prikey = prikey; + PrikeyRawByte = prikeyRawByte; + Pubkey = pubkey; + Passwd = passwd; + Cert = cert; + IsDefault = isDefault; + } + + + public Identity(){} + + + + public byte[] sign(byte[] digest) throws CryptoException { + if(this.Prikey == null) + return null; + switch (this.KeyParam.PublicKeyAlgorithm){ + case Common.SM2: + SM2PrivateKey sm2PrivateKey = (SM2PrivateKey) this.Prikey; + switch (this.KeyParam.SignatureAlgorithm){ + case Common.SM3withSM2: + return sm2PrivateKey.sign(digest); + default: + return null; + } + default: + return null; + } + } + + public boolean verify(byte[] msg, byte[] digest) { + if(this.Pubkey == null) + return false; + switch (this.KeyParam.PublicKeyAlgorithm){ + case Common.SM2: + SM2PublicKey sm2PublicKey = (SM2PublicKey) this.Pubkey; + switch (this.KeyParam.SignatureAlgorithm){ + case Common.SM3withSM2: + return sm2PublicKey.verify(msg, digest); + default: + return false; + } + default: + return false; + } + } + + public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException { + if(this.Prikey == null) + return null; + return this.Prikey.decrypt(cipher); + } + + public byte[] encrypt(byte[] content) throws InvalidCipherTextException { + if(this.Pubkey == null) + return null; + return this.Pubkey.encrypt(content); + } + + public byte[] dump(String passwd) throws NoSuchPaddingException, InvalidAlgorithmParameterException, CertException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + InnerIdentity innerIdentity = IdentityUtil.parseIdentityToInner(this); + byte[] bytesOfInnerIdentity = mapper.writeValueAsBytes(innerIdentity); + // logger.debug(ByteUtils.toHexString(bytesOfInnerIdentity)); + if(passwd != null && passwd.length() != 0) { + byte[] sm4key = KeyUtils.get16bytePasswd(passwd.getBytes()); + byte[] cipher = SM4.encrypt_CBC_Padding(sm4key, new byte[16], bytesOfInnerIdentity); + return Base64.getEncoder().encode(cipher); + } + return Base64.getEncoder().encode(bytesOfInnerIdentity); + } + + public static Identity load(byte[] data, String passwd) + throws BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException, + NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException, + InvalidKeyException, CertException { + byte[] bytesOfIdentity = Base64.getDecoder().decode(data); + byte[] plain; + if(passwd != null && passwd.length() != 0){ + byte[] sm4Key = KeyUtils.get16bytePasswd(passwd.getBytes()); + plain = SM4.decrypt_CBC_Padding(sm4Key, new byte[16], bytesOfIdentity); + } else{ + plain = bytesOfIdentity; + } + ObjectMapper mapper = new ObjectMapper(); + InnerIdentity innerIdentity = null; + // logger.debug(ByteUtils.toHexString(plain)); + try { + innerIdentity = mapper.readValue(plain, InnerIdentity.class); + } catch (IOException e) { + e.printStackTrace(); + } + return IdentityUtil.parseInnerToIdentity(innerIdentity); + } + // TODO: passwd ??? + public boolean lock(String passwd, int algo) throws IdentityException { + switch (algo){ + case Common.SM4ECB: + if (passwd.length() != 16){ + throw new IdentityException("密码应为16位"); + } + PrikeyRawByte = Prikey.getBytes(); + Prikey = null; + return true; + default: + return false; + } + } + + public boolean isLocked(){ + return PrikeyRawByte != null && PrikeyRawByte.length > 0; + } + + // TODO: passwd ??? + public boolean unLock(String passwd, int algo) throws IdentityException { + switch (algo) { + case Common.SM4ECB: + if(passwd == null || passwd.length() == 0) + return false; + PrivateKeyInterface privateKey = KeyUtils.unMarshalPrivateKey(PrikeyRawByte, KeyParam.PublicKeyAlgorithm); + Prikey = privateKey; + PrikeyRawByte = null; + return true; + default: + throw new IdentityException("未知对称加密算法"); + } + } + + public boolean hasPrivateKey() { + return Prikey != null || (PrikeyRawByte != null && PrikeyRawByte.length > 0); + } + + + + + + public String getName() { + return Name; + } + + public void setName(String name) { + Name = name; + } + + public minsecurity.identity.KeyParam getKeyParam() { + return KeyParam; + } + + public void setKeyParam(minsecurity.identity.KeyParam keyParam) { + KeyParam = keyParam; + } + + public PrivateKeyInterface getPrikey() { + return Prikey; + } + + public void setPrikey(PrivateKeyInterface prikey) { + Prikey = prikey; + } + + public byte[] getPrikeyRawByte() { + return PrikeyRawByte; + } + + public void setPrikeyRawByte(byte[] prikeyRawByte) { + PrikeyRawByte = prikeyRawByte; + } + + public PublicKeyInterface getPubkey() { + return Pubkey; + } + + public void setPubkey(PublicKeyInterface pubkey) { + Pubkey = pubkey; + } + + public String getPasswd() { + return Passwd; + } + + public void setPasswd(String passwd) { + Passwd = passwd; + } + + public Certificate getCert() { + return Cert; + } + + public void setCert(Certificate cert) { + Cert = cert; + } + + public boolean isDefault() { + return IsDefault; + } + + public void setDefault(boolean aDefault) { + IsDefault = aDefault; + } + + @Override + public String toString() { + return "Identity{" + + "Name='" + Name + '\'' + + ", KeyParam.signAlgo=" + KeyParam.SignatureAlgorithm + + ", KeyParam.pubAlgo=" + KeyParam.PublicKeyAlgorithm + + ", Prikey=" + ByteUtils.toHexString(Prikey.getBytes()) + + ", pubKey=" + ByteUtils.toHexString(Pubkey.getBytes()) + + ", PrikeyRawByte=" + (PrikeyRawByte == null ? "null":ByteUtils.toHexString(PrikeyRawByte)) + + ", Pubkey=" + Pubkey + + ", Passwd='" + Passwd + '\'' + + ", Cert=" + Cert + + ", isDefault=" + IsDefault + + '}'; + } +} diff --git a/src/main/java/minsecurity/identity/IdentityException.java b/src/main/java/minsecurity/identity/IdentityException.java new file mode 100644 index 0000000..8bd2431 --- /dev/null +++ b/src/main/java/minsecurity/identity/IdentityException.java @@ -0,0 +1,14 @@ +package minsecurity.identity; + +/* + * @Author: hongyu guo + * @Description: Identity自定义异常 + * @Version: 1.0.0 + * @Date: 14:59 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class IdentityException extends Exception{ + public IdentityException(String msg){ + super(msg); + } +} diff --git a/src/main/java/minsecurity/identity/IdentityUtil.java b/src/main/java/minsecurity/identity/IdentityUtil.java new file mode 100644 index 0000000..87a0814 --- /dev/null +++ b/src/main/java/minsecurity/identity/IdentityUtil.java @@ -0,0 +1,72 @@ +package minsecurity.identity; + +import minsecurity.Common; +import minsecurity.certificate.cert.CertException; +import minsecurity.certificate.cert.CertUtils; +import minsecurity.certificate.cert.Certificate; +import minsecurity.crypto.KeyUtils; +import minsecurity.crypto.PrivateKeyInterface; +import minsecurity.crypto.PublicKeyInterface; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 10:12 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class IdentityUtil { + public static InnerIdentity parseIdentityToInner(Identity identity) + throws NoSuchPaddingException, InvalidKeyException, CertException, + IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, + NoSuchProviderException, InvalidAlgorithmParameterException { + InnerIdentity innerIdentity = new InnerIdentity(); + innerIdentity.setName(identity.getName()); + innerIdentity.setKeyParam(identity.getKeyParam()); + if(identity.getPrikey() != null){ + innerIdentity.setPrikey(identity.getPrikey().getBytes()); + } + if(identity.getPubkey() != null){ + innerIdentity.setPubkey(identity.getPubkey().getBytes()); + } + innerIdentity.setPasswd(identity.getPasswd()); + innerIdentity.setCert(CertUtils.toPem(identity.getCert(), identity.getPasswd().getBytes(), Common.SM4CBC)); + return innerIdentity; + } + + public static Identity parseInnerToIdentity(InnerIdentity innerIdentity) + throws BadPaddingException, InvalidKeyException, CertException, + NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, + InvalidAlgorithmParameterException, IllegalBlockSizeException { + Identity identity = new Identity(); + identity.setName(innerIdentity.getName()); + identity.setKeyParam(innerIdentity.getKeyParam()); + if(innerIdentity.getPubkey() == null || innerIdentity.getPubkey().length == 0){ + return null; + } + if(innerIdentity.getPrikey() == null || innerIdentity.getPrikey().length == 0){ + return null; + } + PublicKeyInterface pub = + KeyUtils.unMarshalPublicKey(innerIdentity.getPubkey(), innerIdentity.getKeyParam().PublicKeyAlgorithm); + identity.setPubkey(pub); + PrivateKeyInterface priv = + KeyUtils.unMarshalPrivateKey(innerIdentity.getPrikey(), innerIdentity.getKeyParam().PublicKeyAlgorithm); + identity.setPrikey(priv); + identity.setPasswd(innerIdentity.getPasswd()); + Certificate certificate = + CertUtils.fromPem(innerIdentity.getCert(), innerIdentity.getPasswd().getBytes(), Common.SM4CBC); + identity.setCert(certificate); + return identity; + } + + +} diff --git a/src/main/java/minsecurity/identity/InnerIdentity.java b/src/main/java/minsecurity/identity/InnerIdentity.java new file mode 100644 index 0000000..927f46a --- /dev/null +++ b/src/main/java/minsecurity/identity/InnerIdentity.java @@ -0,0 +1,96 @@ +package minsecurity.identity; + +import minsecurity.certificate.cert.Certificate; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; + +import java.util.Arrays; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 09:41 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class InnerIdentity { + private String Name; + private KeyParam KeyParam; + private byte[] Prikey; + private byte[] Pubkey; + private String Passwd; + private String Cert; + + public InnerIdentity(String name, minsecurity.identity.KeyParam keyParam, byte[] prikey, byte[] pubkey, String passwd, String cert) { + Name = name; + KeyParam = keyParam; + Prikey = prikey; + Pubkey = pubkey; + Passwd = passwd; + Cert = cert; + } + + public InnerIdentity() { + } + + public String getName() { + return Name; + } + + public void setName(String name) { + Name = name; + } + + public minsecurity.identity.KeyParam getKeyParam() { + return KeyParam; + } + + public void setKeyParam(minsecurity.identity.KeyParam keyParam) { + KeyParam = keyParam; + } + + public byte[] getPrikey() { + return Prikey; + } + + public void setPrikey(byte[] prikey) { + Prikey = prikey; + } + + public byte[] getPubkey() { + return Pubkey; + } + + public void setPubkey(byte[] pubkey) { + Pubkey = pubkey; + } + + public String getPasswd() { + return Passwd; + } + + public void setPasswd(String passwd) { + Passwd = passwd; + } + + public String getCert() { + return Cert; + } + + public void setCert(String cert) { + Cert = cert; + } + + @Override + public String toString() { + return "InnerIdentity{" + + "Name='" + Name + '\'' + + ", KeyParam=" + KeyParam + + ", Prikey=" + (Prikey == null ? "null" : ByteUtils.toHexString(Prikey)) + + ", Pubkey=" + (Pubkey == null ? "null" : ByteUtils.toHexString(Pubkey)) + + ", Passwd='" + Passwd + '\'' + + ", Cert='" + Cert + '\'' + + '}'; + } +} + + diff --git a/src/main/java/minsecurity/identity/KeyParam.java b/src/main/java/minsecurity/identity/KeyParam.java new file mode 100644 index 0000000..7a3ef10 --- /dev/null +++ b/src/main/java/minsecurity/identity/KeyParam.java @@ -0,0 +1,21 @@ +package minsecurity.identity; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 20:31 2021/03/07 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class KeyParam { + public int PublicKeyAlgorithm; + public int SignatureAlgorithm; + + public KeyParam(int publicKeyAlgorithm, int signatureAlgorithm) { + this.PublicKeyAlgorithm = publicKeyAlgorithm; + this.SignatureAlgorithm = signatureAlgorithm; + } + + public KeyParam() { + } +} diff --git a/src/main/java/minsecurity/identity/persist/IdentitySerializer.java b/src/main/java/minsecurity/identity/persist/IdentitySerializer.java new file mode 100644 index 0000000..fea81d4 --- /dev/null +++ b/src/main/java/minsecurity/identity/persist/IdentitySerializer.java @@ -0,0 +1,97 @@ +package minsecurity.identity.persist; + +import com.fasterxml.jackson.databind.ObjectMapper; +import minsecurity.Common; +import minsecurity.certificate.cert.CertException; +import minsecurity.certificate.cert.CertUtils; +import minsecurity.certificate.cert.Certificate; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; +import minsecurity.identity.Identity; +import minsecurity.identity.KeyParam; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.jetbrains.annotations.NotNull; +import org.mapdb.DataInput2; +import org.mapdb.DataOutput2; +import org.mapdb.Serializer; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +/* + * @Author: hongyu guo + * @Description: mapDB需要自定义序列化、反序列化方法 + * @Version: 1.0.0 + * @Date: 20:50 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class IdentitySerializer implements Serializer { + + + @Override + public void serialize(@NotNull DataOutput2 dataOutput2, @NotNull Identity identity) throws IOException { + String name = identity.getName(); + String pub = ByteUtils.toHexString(identity.getPubkey().getBytes()); + String priv = ByteUtils.toHexString(identity.getPrikey().getBytes()); + int pubAlgo = identity.getKeyParam().PublicKeyAlgorithm; + int signAlgo = identity.getKeyParam().SignatureAlgorithm; + String passwd = identity.getPasswd(); + String cert = ""; + try { + cert = CertUtils.toPem(identity.getCert(),null, Common.SM4CBC); + } catch (CertException | NoSuchPaddingException | InvalidAlgorithmParameterException | + NoSuchAlgorithmException | IllegalBlockSizeException | BadPaddingException | + NoSuchProviderException | InvalidKeyException e) { + e.printStackTrace(); + } + boolean isDefault = identity.isDefault(); + String prikeyRawByte = identity.getPrikeyRawByte()== null ? + "" :ByteUtils.toHexString(identity.getPrikeyRawByte()); + + + dataOutput2.writeUTF(name); + dataOutput2.writeUTF(pub); + dataOutput2.writeUTF(priv); + dataOutput2.writeInt(pubAlgo); + dataOutput2.writeInt(signAlgo); + dataOutput2.writeUTF(passwd); + dataOutput2.writeUTF(cert); + dataOutput2.writeBoolean(isDefault); + dataOutput2.writeUTF(prikeyRawByte); + } + + @Override + public Identity deserialize(@NotNull DataInput2 dataInput2, int i) throws IOException { + String name = dataInput2.readUTF(); + byte[] pub = ByteUtils.fromHexString(dataInput2.readUTF()); + byte[] priv = ByteUtils.fromHexString(dataInput2.readUTF()); + int pubAlgo = dataInput2.readInt(); + int signAlgo = dataInput2.readInt(); + String passwd = dataInput2.readUTF(); + String certString = dataInput2.readUTF(); + Certificate certificate = null; + try { + certificate = CertUtils.fromPem(certString, null, Common.SM4CBC); + } catch (CertException | BadPaddingException | NoSuchPaddingException | + InvalidAlgorithmParameterException | NoSuchAlgorithmException | + IllegalBlockSizeException | NoSuchProviderException | InvalidKeyException e) { + e.printStackTrace(); + } + boolean isDefault = dataInput2.readBoolean(); + byte[] prikeyRawByte = dataInput2.readUTF().equals("") ? + null : ByteUtils.fromHexString(dataInput2.readUTF()); + KeyParam keyParam = new KeyParam(pubAlgo, signAlgo); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(); + sm2PrivateKey.setBytes(priv); + SM2PublicKey sm2PublicKey = new SM2PublicKey(); + sm2PublicKey.setBytes(pub); + return new Identity(name,keyParam, sm2PrivateKey,prikeyRawByte, sm2PublicKey, passwd, certificate, isDefault); + } + +} diff --git a/src/test/java/minsecurity/certificate/cert/TestCert.java b/src/test/java/minsecurity/certificate/cert/TestCert.java index eb3f780..70f8249 100644 --- a/src/test/java/minsecurity/certificate/cert/TestCert.java +++ b/src/test/java/minsecurity/certificate/cert/TestCert.java @@ -1,9 +1,9 @@ package minsecurity.certificate.cert; import minsecurity.Common; -import minsecurity.crypto.sm2.Sm2Base; -import minsecurity.crypto.sm2.Sm2PrivateKey; -import minsecurity.crypto.sm2.Sm2PublicKey; +import minsecurity.crypto.sm2.SM2Base; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; @@ -22,15 +22,15 @@ public class TestCert { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestCert.class); @Test public void testCertSignAndVerify() throws Exception { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); // d = Arrays.copyOf(d,32); byte[] x = pubKey.getQ().getAffineXCoord().getEncoded(); byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); Certificate certificate = new Certificate(1,1,sm2PublicKey, @@ -46,15 +46,15 @@ public class TestCert { assertTrue(verify); - AsymmetricCipherKeyPair keyPair2 = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair2 = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey2 = (ECPrivateKeyParameters) keyPair2.getPrivate(); ECPublicKeyParameters pubKey2 = (ECPublicKeyParameters) keyPair2.getPublic(); byte[] d2 = priKey2.getD().toByteArray(); // d = Arrays.copyOf(d,32); byte[] x2 = pubKey2.getQ().getAffineXCoord().getEncoded(); byte[] y2 = pubKey2.getQ().getAffineYCoord().getEncoded(); - Sm2PrivateKey sm2PrivateKey2 = new Sm2PrivateKey(d2); - Sm2PublicKey sm2PublicKey2 = new Sm2PublicKey(x2, y2); + SM2PrivateKey sm2PrivateKey2 = new SM2PrivateKey(d2); + SM2PublicKey sm2PublicKey2 = new SM2PublicKey(x2, y2); Certificate sub = new Certificate(1,2,sm2PublicKey2, null, Common.SM3withSM2,Common.SM2, @@ -69,15 +69,15 @@ public class TestCert { @Test public void testCert2Pem() throws Exception { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); // d = Arrays.copyOf(d,32); byte[] x = pubKey.getQ().getAffineXCoord().getEncoded(); byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); Certificate certificate = new Certificate(1,1,sm2PublicKey, diff --git a/src/test/java/minsecurity/certificate/x509/TestX509.java b/src/test/java/minsecurity/certificate/x509/TestX509.java index 920cdce..79514d9 100644 --- a/src/test/java/minsecurity/certificate/x509/TestX509.java +++ b/src/test/java/minsecurity/certificate/x509/TestX509.java @@ -3,7 +3,7 @@ package minsecurity.certificate.x509; import minsecurity.Common; import minsecurity.certificate.X509.X509CertMaker; import minsecurity.certificate.X509.X509CertUtil; -import minsecurity.crypto.sm2.Sm2Base; +import minsecurity.crypto.sm2.SM2Base; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.bouncycastle.util.io.pem.PemObject; @@ -50,7 +50,7 @@ public class TestX509 { public void testRebuildKeyPair(){ try { - KeyPair rootKP = Sm2Base.generateKeyPair(); + KeyPair rootKP = SM2Base.generateKeyPair(); X509Certificate rootCA = makeRootCA(rootKP,"CN","MIN", "MIN-GROUP","MIN ROOT CA", 365L * 24 * 60 * 60 * 1000, "SM3withSM2"); @@ -77,7 +77,7 @@ public class TestX509 { logger.debug("origin: {}", ByteUtils.toHexString(rootKP.getPublic().getEncoded())); logger.debug("rebuild:{}", ByteUtils.toHexString(rootKeyPair.getPublic().getEncoded())); - KeyPair subKeyPair = Sm2Base.generateKeyPair(); + KeyPair subKeyPair = SM2Base.generateKeyPair(); X509Certificate subCert = X509CertMaker.makeSubCACert(rootKeyPair, cert, diff --git a/src/test/java/minsecurity/crypto/TestSm2.java b/src/test/java/minsecurity/crypto/TestSM2.java similarity index 88% rename from src/test/java/minsecurity/crypto/TestSm2.java rename to src/test/java/minsecurity/crypto/TestSM2.java index 57e616c..274d45e 100644 --- a/src/test/java/minsecurity/crypto/TestSm2.java +++ b/src/test/java/minsecurity/crypto/TestSM2.java @@ -1,8 +1,8 @@ package minsecurity.crypto; -import minsecurity.crypto.sm2.Sm2Base; -import minsecurity.crypto.sm2.Sm2PrivateKey; -import minsecurity.crypto.sm2.Sm2PublicKey; +import minsecurity.crypto.sm2.SM2Base; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.CryptoException; import org.bouncycastle.crypto.InvalidCipherTextException; @@ -24,11 +24,11 @@ import java.util.List; * @Date: 20:15 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class TestSm2 { - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestSm2.class); +public class TestSM2 { + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestSM2.class); @Test public void testSetGet() throws InvalidCipherTextException { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); @@ -36,8 +36,8 @@ public class TestSm2 { byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); logger.debug("d.len = {}, x.len = {}, y.len = {}",d.length, x.length, y.length); // BigInteger bigInteger = priKey.getD(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(); + SM2PublicKey sm2PublicKey = new SM2PublicKey(); sm2PrivateKey.setBytes(d); @@ -62,7 +62,7 @@ public class TestSm2 { @Test public void testEncAndDec() throws InvalidCipherTextException { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); @@ -71,8 +71,8 @@ public class TestSm2 { byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); logger.debug("d.len = {}, x.len = {}, y.len = {}",d.length, x.length, y.length); // BigInteger bigInteger = priKey.getD(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); String content = "hello world"; byte[] encBytes = sm2PublicKey.encrypt(content.getBytes()); @@ -83,7 +83,7 @@ public class TestSm2 { @Test public void testSignAndVerify() throws CryptoException { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); @@ -93,8 +93,8 @@ public class TestSm2 { logger.debug("d.len = {}, x.len = {}, y.len = {}",d.length, x.length, y.length); // BigInteger bigInteger = priKey.getD(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); String content = "7b227462734365727469666963617465223a7b2276657273696f6e223a312c2273657269616c4e756d626572223a312c227075626c69634b6579223a22424a304d7047714e5958706b695879575a4d6e5838776d6b694a51326f576d37336257615932525473706b695058342f37705443666332764e7272596e766c6a644d3448647850537531753272616363506c74485245593d222c227369676e6174757265416c676f726974686d223a302c227075626c69634b6579416c676f726974686d223a302c226973737565546f223a226973737565546f222c22697373756572223a22697373756572222c226e6f744265666f7265223a313631353032303130393339352c226e6f744166746572223a313631353032303130393539352c226b65795573616765223a322c2274696d657374616d70223a313631353032303130393339352c226361223a747275657d2c227369676e6174757265416c676f726974686d223a302c227369676e617475726556616c7565223a6e756c6c7d"; byte[] digest = sm2PrivateKey.sign(ByteUtils.fromHexString(content)); boolean flag = sm2PublicKey.verify(ByteUtils.fromHexString(content), digest); diff --git a/src/test/java/minsecurity/crypto/TestSm4.java b/src/test/java/minsecurity/crypto/TestSM4.java similarity index 82% rename from src/test/java/minsecurity/crypto/TestSm4.java rename to src/test/java/minsecurity/crypto/TestSM4.java index 34cd1a8..0bb09ac 100644 --- a/src/test/java/minsecurity/crypto/TestSm4.java +++ b/src/test/java/minsecurity/crypto/TestSM4.java @@ -2,7 +2,6 @@ package minsecurity.crypto; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import java.util.Arrays; @@ -14,7 +13,7 @@ import java.util.Arrays; * @Date: 16:28 2021/03/04 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class TestSm4 { +public class TestSM4 { public static final byte[] SRC_DATA = new byte[]{1, 2, 3, 4, 5, 6, 7, 8}; public static final byte[] SRC_DATA_16B = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; public static final byte[] SRC_DATA_24B = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; @@ -25,42 +24,42 @@ public class TestSm4 { @Test public void testEncryptAndDecrypt() { try { - byte[] key = Sm4.generateKey(); - byte[] iv = Sm4.generateKey(); + byte[] key = SM4.generateKey(); + byte[] iv = SM4.generateKey(); byte[] cipherText = null; byte[] decryptedData = null; System.out.println("key: " + ByteUtils.toHexString(key)); System.out.println("iv: " + ByteUtils.toHexString(iv)); - cipherText = Sm4.encrypt_ECB_NoPadding(key, SRC_DATA_16B); + cipherText = SM4.encrypt_ECB_NoPadding(key, SRC_DATA_16B); System.out.println("SM4 ECB NoPadding encrypt result:\n" + Arrays.toString(cipherText)); System.out.println(ByteUtils.toHexString(cipherText)); - decryptedData = Sm4.decrypt_ECB_NoPadding(key, cipherText); + decryptedData = SM4.decrypt_ECB_NoPadding(key, cipherText); System.out.println("SM4 ECB NoPadding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA_16B)) { Assert.fail(); } - cipherText = Sm4.encrypt_ECB_Padding(key, SRC_DATA_16B); + cipherText = SM4.encrypt_ECB_Padding(key, SRC_DATA_16B); System.out.println("SM4 ECB Padding encrypt result:\n" + Arrays.toString(cipherText)); System.out.println(ByteUtils.toHexString(cipherText)); - decryptedData = Sm4.decrypt_ECB_Padding(key, cipherText); + decryptedData = SM4.decrypt_ECB_Padding(key, cipherText); System.out.println("SM4 ECB Padding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA_16B)) { Assert.fail(); } - cipherText = Sm4.encrypt_CBC_Padding(key, iv, SRC_DATA); + cipherText = SM4.encrypt_CBC_Padding(key, iv, SRC_DATA); System.out.println("SM4 CBC Padding encrypt result:\n" + Arrays.toString(cipherText)); - decryptedData = Sm4.decrypt_CBC_Padding(key, iv, cipherText); + decryptedData = SM4.decrypt_CBC_Padding(key, iv, cipherText); System.out.println("SM4 CBC Padding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA)) { Assert.fail(); } - cipherText = Sm4.encrypt_CBC_NoPadding(key, iv, SRC_DATA_16B); + cipherText = SM4.encrypt_CBC_NoPadding(key, iv, SRC_DATA_16B); System.out.println("SM4 CBC NoPadding encrypt result:\n" + Arrays.toString(cipherText)); - decryptedData = Sm4.decrypt_CBC_NoPadding(key, iv, cipherText); + decryptedData = SM4.decrypt_CBC_NoPadding(key, iv, cipherText); System.out.println("SM4 CBC NoPadding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA_16B)) { Assert.fail(); diff --git a/src/test/java/minsecurity/identity/TestIdentity.java b/src/test/java/minsecurity/identity/TestIdentity.java new file mode 100644 index 0000000..45394bc --- /dev/null +++ b/src/test/java/minsecurity/identity/TestIdentity.java @@ -0,0 +1,81 @@ +package minsecurity.identity; + +import minsecurity.Common; +import minsecurity.certificate.cert.CertUtils; +import minsecurity.certificate.cert.Certificate; +import minsecurity.crypto.TestSM2; +import minsecurity.crypto.sm2.SM2Base; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.junit.Test; +import static org.junit.Assert.*; +import org.slf4j.LoggerFactory; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 15:24 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class TestIdentity { + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestIdentity.class); + + + @Test + public void testIdentity1() throws Exception { + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); + ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); + ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); + byte[] d = priKey.getD().toByteArray(); + // d = Arrays.copyOf(d,32); + byte[] x = pubKey.getQ().getAffineXCoord().getEncoded(); + byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); + logger.debug("d.len = {}, x.len = {}, y.len = {}",d.length, x.length, y.length); + + // BigInteger bigInteger = priKey.getD(); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); + KeyParam keyParam = new KeyParam(Common.SM2, Common.SM3withSM2); + Identity identity = new Identity("root",keyParam,sm2PrivateKey,null,sm2PublicKey, "123456", null, false); + Certificate certificate = new Certificate(1, 1, sm2PublicKey, null, + Common.SM3withSM2, Common.SM2, "root", "root", + System.currentTimeMillis() - 1000, System.currentTimeMillis() + 5000, + Common.CertSign, true, System.currentTimeMillis()); + CertUtils.signCert(certificate, sm2PrivateKey); + identity.setCert(certificate); + + String text = "2020-03-09"; + // test sign and verify + byte[] signature = identity.sign(text.getBytes()); + boolean flag = identity.verify(text.getBytes(), signature); + logger.debug("identity verify: {}", flag); + assertTrue(flag); + + + // test enc and dec + byte[] cipher = identity.encrypt(text.getBytes()); + byte[] bytesOfDec = identity.decrypt(cipher); + assertArrayEquals(bytesOfDec, text.getBytes()); + + + // test dump and load + byte[] bytesOfDump = identity.dump(identity.getPasswd()); + Identity idFromBytes = Identity.load(bytesOfDump, identity.getPasswd()); + assertEquals(ByteUtils.toHexString(identity.getPrikey().getBytes()), ByteUtils.toHexString(idFromBytes.getPrikey().getBytes())); + assertEquals(ByteUtils.toHexString(identity.getPubkey().getBytes()), ByteUtils.toHexString(idFromBytes.getPubkey().getBytes())); + // test dump and load without passwd + bytesOfDump = identity.dump(null); + idFromBytes = Identity.load(bytesOfDump, null); + assertEquals(ByteUtils.toHexString(identity.getPrikey().getBytes()), ByteUtils.toHexString(idFromBytes.getPrikey().getBytes())); + assertEquals(ByteUtils.toHexString(identity.getPubkey().getBytes()), ByteUtils.toHexString(idFromBytes.getPubkey().getBytes())); + + logger.debug(identity.getPrikey().getBytes().length + " " + identity.getPubkey().getBytes().length); + } + + +} diff --git a/src/test/java/minsecurity/identity/TestPersist.java b/src/test/java/minsecurity/identity/TestPersist.java new file mode 100644 index 0000000..8578ba6 --- /dev/null +++ b/src/test/java/minsecurity/identity/TestPersist.java @@ -0,0 +1,68 @@ +package minsecurity.identity; + + +import minsecurity.Common; +import minsecurity.certificate.cert.CertUtils; +import minsecurity.certificate.cert.Certificate; +import minsecurity.crypto.sm2.SM2Base; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; +import minsecurity.identity.persist.IdentitySerializer; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.junit.Test; +import org.mapdb.BTreeMap; +import org.mapdb.DB; +import org.mapdb.DBMaker; +import org.mapdb.Serializer; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ConcurrentMap; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 17:35 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class TestPersist { + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestIdentity.class); + + @Test + public void testMapDB() throws Exception { + + + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); + ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); + ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); + byte[] d = priKey.getD().toByteArray(); + // d = Arrays.copyOf(d,32); + byte[] x = pubKey.getQ().getAffineXCoord().getEncoded(); + byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); + // BigInteger bigInteger = priKey.getD(); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); + KeyParam keyParam = new KeyParam(Common.SM2, Common.SM3withSM2); + Identity identity = new Identity("root",keyParam,sm2PrivateKey,null,sm2PublicKey, "123456", null, false); + Certificate certificate = new Certificate(1, 1, sm2PublicKey, null, + Common.SM3withSM2, Common.SM2, "root", "root", + System.currentTimeMillis() - 1000, System.currentTimeMillis() + 5000, + Common.CertSign, true, System.currentTimeMillis()); + CertUtils.signCert(certificate, sm2PrivateKey); + identity.setCert(certificate); + DB db = DBMaker.fileDB("./target/test.db").closeOnJvmShutdown().transactionEnable().make(); + Serializer customSerializer = new IdentitySerializer(); + ConcurrentMap map = db.hashMap("identity") + .keySerializer(Serializer.STRING) + .valueSerializer(customSerializer) + .createOrOpen(); + // map.put("/min/test05", new Identity()); + map.put("/min/test06", identity); + db.commit(); + logger.debug(identity.toString()); + Identity id = map.get("/min/test06"); + logger.debug(id.toString()); + } +} diff --git a/src/test/java/others/Animal.java b/src/test/java/others/Animal.java new file mode 100644 index 0000000..528dbce --- /dev/null +++ b/src/test/java/others/Animal.java @@ -0,0 +1,15 @@ +package others; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 9:15 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +interface Animal { +// private String name="灵长类动物"; + + + public void sayHi(); +} diff --git a/src/test/java/others/God.java b/src/test/java/others/God.java new file mode 100644 index 0000000..3db3f9b --- /dev/null +++ b/src/test/java/others/God.java @@ -0,0 +1,13 @@ +package others; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 9:15 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +interface God { + + public void makeWorld(); +} diff --git a/src/test/java/others/HumanImpl.java b/src/test/java/others/HumanImpl.java new file mode 100644 index 0000000..4385ccb --- /dev/null +++ b/src/test/java/others/HumanImpl.java @@ -0,0 +1,26 @@ +package others; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 10:10 2021/3/9 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class HumanImpl implements God,Animal { + @Override + public void sayHi() { + System.out.println("hi"); + } + + @Override + public void makeWorld() { + System.out.println("world"); + } + + public static void main(String[] args){ + HumanImpl h=new HumanImpl(); + h.sayHi(); + h.makeWorld(); + } +}