diff --git a/docs/吴政琪&赵峰-安全模块性能测试报告-20210423.docx b/docs/吴政琪&赵峰-安全模块性能测试报告-20210423.docx index 99ba56d..2a61b85 100644 Binary files a/docs/吴政琪&赵峰-安全模块性能测试报告-20210423.docx and b/docs/吴政琪&赵峰-安全模块性能测试报告-20210423.docx differ diff --git a/src/main/java/security/KeyChain.java b/src/main/java/security/KeyChain.java index c2c9a90..3c4eee5 100644 --- a/src/main/java/security/KeyChain.java +++ b/src/main/java/security/KeyChain.java @@ -3,8 +3,10 @@ package security; import component.Signature; import encoding.Block; import encoding.SelfEncodingBase; +import minsecurity.crypto.AsymKeyException; import minsecurity.identity.Identity; import minsecurity.identity.IdentityException; +import org.bouncycastle.crypto.CryptoException; import packet.CPacket; import packet.Data; import packet.Interest; @@ -16,6 +18,7 @@ import javax.crypto.NoSuchPaddingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.util.Arrays; /* * @Author: hongyu guo @@ -260,6 +263,25 @@ public class KeyChain { this.sign(data.minPacket); } + /** + * 对已经合并好的标识区和只读区进行签名 + * @param mergeArray 原文:已经合并好的标识区和只读区 + * @return 密文 + */ + public byte[] signBytes(byte[] mergeArray) throws Exception { + return this.currentIdentity.sign(mergeArray); + } + + /** + * 验证签名 + * @param mergeArray 原文 + * @param digest 密文 + * @return + */ + public boolean verifyBytes(byte[] mergeArray,byte[] digest) throws Exception { + return this.currentIdentity.verify(mergeArray,digest); + } + /** * 验证一个MIN网络包中的签名是否有效 * @param minPacket diff --git a/src/test/java/mgmt/RegisterPrefixHelperTest.java b/src/test/java/mgmt/RegisterPrefixHelperTest.java index a129af0..3c8c8f6 100644 --- a/src/test/java/mgmt/RegisterPrefixHelperTest.java +++ b/src/test/java/mgmt/RegisterPrefixHelperTest.java @@ -31,10 +31,10 @@ public class RegisterPrefixHelperTest { // 初始化KeyChain // KeyChain keyChain=new KeyChain(); - RegisterPrefixHelper helper=new RegisterPrefixHelper(); +// RegisterPrefixHelper helper=new RegisterPrefixHelper(); KeyManagerExample.INSTANCE.initKeyChain("/wefree/test","D://"); face.setKeyChain(KeyManagerExample.INSTANCE.getKeyChain()); - helper.registerPrefix(identifier,face,KeyManagerExample.INSTANCE.getKeyChain()); +// helper.registerPrefix(identifier,face,KeyManagerExample.INSTANCE.getKeyChain()); // 测试发包速率 Identifier serverIden = null; diff --git a/src/test/java/testPrivate.java b/src/test/java/testPrivate.java index 2b09a1a..4d8638c 100644 --- a/src/test/java/testPrivate.java +++ b/src/test/java/testPrivate.java @@ -1,5 +1,16 @@ +import component.ComponentException; +import component.Identifier; +import encoding.TLV; +import encoding.TLVException; +import encoding.VlInt; +import encoding.VlIntException; import minsecurity.crypto.sm2.SM2KeyPair; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import packet.CPacket; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Random; /* * @Author: hongyu guo @@ -17,4 +28,160 @@ public class testPrivate { System.out.println("a = " + a); System.out.println("private key = " + ByteUtils.toHexString(sm2KeyPair.getSm2PrivateKey().getBytes())); } + + public static String getFixLenthString(int strLength) { + Random rm = new Random(); + // 获得随机数 + double pross = (1 + rm.nextDouble()) * Math.pow(10, strLength); + // 将获得的获得随机数转化为字符串 + String fixLenthString = String.valueOf(pross); + // 返回固定的长度的随机数 + return fixLenthString.substring(1, strLength + 1); + } + + public static String getAll0String() { + return new String("0000000000"); + } + + public static void main(String[] args) throws VlIntException { + // 测试vlint + VlInt a=new VlInt(1200); + System.out.println("1200 is bytes: "+ Arrays.toString(a.getVlIntBytes())); + System.out.println("1200 len: "+a.size()); + a=new VlInt(1204); + System.out.println("1204 is bytes: "+ Arrays.toString(a.getVlIntBytes())); + System.out.println("1204 len: "+a.size()); + a=new VlInt(1298); + System.out.println("1298 is bytes: "+ Arrays.toString(a.getVlIntBytes())); + System.out.println("1298 len: "+a.size()); + + byte[] matchArray=new byte[]{(byte)11,(byte) 0,(byte) 48,(byte) 48,(byte) 48,(byte) 48,(byte) 48}; + System.out.println(Arrays.toString(matchArray)); + System.out.println(findThePos(matchArray)); + + int seq=11; + Identifier clientIden = null; + try { + clientIden=new Identifier("/min/gdcni9/default/"+seq); + } catch (ComponentException e) { + e.printStackTrace(); + return; + } + Identifier serverIden = null; + try { +// serverIden=new Identifier("/hk/vpnserver/10/"+getFixLenthString(10)); + serverIden=new Identifier("/hk/vpnserver/10/"+getAll0String()); + } catch (ComponentException e) { + e.printStackTrace(); + return; + } + CPacket cPacket=new CPacket(); + cPacket.setSrcIdentifier(clientIden); + cPacket.setDstIdentifier(serverIden); + cPacket.ttl.setTtl(64); + byte[] pay=new byte[10]; + cPacket.payload.setValue(pay); + cPacket.encodeSelf(); // 先编码!!!减少发包阻塞。 + + System.out.println(Arrays.toString(cPacket.getRawData())); + System.out.println(cPacket.getRawData().length); + +// byte[] ta=cPacket.getRawData(); +// System.out.println("ta len: "+ta.length); + int pos=findThePos(cPacket.getRawData()); +// System.out.println("pos: "+pos); +// byte[] newData=replaceRandomPos(cPacket.getRawData(),pos); +// System.out.println("替换结果: "+ Arrays.toString(newData)); + byte[] newData=replaceRandomPos(cPacket.getRawData(),pos,pos+10,1200); + System.out.println("替换结果: "+ Arrays.toString(newData)); + } + +// [5, 108, +// 50, 85, 102, 36, +// 101, 34, 100, 2, 0, 47, +// 100, 4, 0, 109, 105, 110, 100, 7, 0, 103, +//100, 99, 110, 105, 57, 100, 8, 0, +//100, 101, 102, 97, 117, 108, 116, +//100, 3, 0, 49, 49, 102, 45, 101, 43, +//100, 2, 0, 47, 100, 3, 0, 104, 107, +//100, 10, 0, 118, 112, 110, 115, 101, 114, 118, 101, 114, +//100, 3, 0, 49, 48, +//100, 11, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 2, 4, 10, 52, 12, -52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 5, 55, 3, -44, 1, 64 + // 要找的字符数组是:100, 11, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48 + // 分析其特点,找到连续的五个48,且前面依次是11、0,即可。假定是10个连续随机数 + public static int findThePos(byte[] targetArray){ + byte[] matchArray=new byte[]{(byte)11,(byte) 0,(byte) 48}; + System.out.println("target: "+Arrays.toString(targetArray)); + System.out.println("match: "+ Arrays.toString(matchArray)); + for (int i = 0; i < (targetArray.length-7); i++) { + if((targetArray[i]==matchArray[0]) + && (targetArray[i+1]==matchArray[1]) + && (targetArray[i+2]==matchArray[2]) + && (targetArray[i+3]==matchArray[2]) + && (targetArray[i+4]==matchArray[2]) + && (targetArray[i+5]==matchArray[2]) + && (targetArray[i+6]==matchArray[2])){ + System.out.println("我中了"); + return i+2; + } + } + return -1; + } + + public static byte[] replaceRandomPos(byte[] targetArray,int pos){ + System.arraycopy(getFixLenthString(10).getBytes(StandardCharsets.UTF_8),0,targetArray,pos,10); + return targetArray; + } + + public static byte[] replaceRandomPos(byte[] targetArray,int randomPos,int readPos,int payloadLen) + throws VlIntException { + System.out.println("ttt1"); + // 先读取原头部的总长度 + VlInt oldLen; + try { + oldLen= TLV.readVarNumber(targetArray,new VlInt(1)); + } catch (TLVException e) { + e.printStackTrace(); + return null; + } + System.out.println("ttt2"); + // 计算需要总长度 + VlInt payLen=new VlInt(payloadLen); // 负载长度 + VlInt readLen=new VlInt(payloadLen+payLen.size()+1); // 可读区长度 + VlInt packetLen=new VlInt((readPos-1-oldLen.size()) + +(readLen.getVlIntValue2Int()+readLen.size()+1) + +7);// 通用包长度 + System.out.println("pk len: "+packetLen); + int allLen=(packetLen.getVlIntValue2Int()+packetLen.size()+1)-7-payloadLen; // 总长度 + System.out.println("ttt3"); + // 构造最后的返回数组 + byte[] totalData=new byte[allLen]; + // 1. 拷贝包头 + totalData[0]=(byte)5; + System.arraycopy(packetLen.getVlIntBytes(),0,totalData,1,packetLen.size()); + System.out.println("ttt4"); + // 2. 拷贝随机段之前的数据(固定标识字段) + System.arraycopy(targetArray,1+oldLen.size(),totalData,1+packetLen.size(), + randomPos-1-oldLen.size()); + System.out.println("ttt5"); + System.out.println("readpos: "+readPos); + System.out.println("packetLen.size: "+packetLen.size()); + System.out.println("oldlen.size: "+oldLen.size()); + // 3. 拷贝随机段(目的标识的活动字段) + System.arraycopy(getFixLenthString(10).getBytes(StandardCharsets.UTF_8), + 0,totalData,randomPos+packetLen.size()-oldLen.size(),10); + System.out.println("ttt6"); + // 4. 拷贝负载区头部 + totalData[readPos+packetLen.size()-oldLen.size()]=(byte)52; + System.arraycopy(readLen.getVlIntBytes(),0,totalData, + readPos+packetLen.size()-oldLen.size()+1,readLen.size()); + totalData[readPos+packetLen.size()-oldLen.size()+1+readLen.size()]=(byte)204; + System.arraycopy(payLen.getVlIntBytes(),0,totalData, + readPos+packetLen.size()-oldLen.size()+1+readLen.size()+1,payLen.size()); + System.out.println("ttt7"); + int newRandomPos=randomPos-oldLen.size()+packetLen.size(); + System.out.println("pos: "+randomPos); + System.out.println("newpos: "+newRandomPos); + return totalData; + } } diff --git a/src/test/java/testQuickEncodeWithSignature.java b/src/test/java/testQuickEncodeWithSignature.java new file mode 100644 index 0000000..d3ef46b --- /dev/null +++ b/src/test/java/testQuickEncodeWithSignature.java @@ -0,0 +1,314 @@ +import component.ComponentException; +import component.Identifier; +import encoding.TLV; +import encoding.TLVException; +import encoding.VlInt; +import encoding.VlIntException; +import examples.KeyManagerExample; +import org.bouncycastle.crypto.CryptoException; +import packet.CPacket; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +/* + * @Author: Wang Feng + * @Description: 测试带签名的打印信息 + * @Version: 1.0.0 + * @Date: 11:00 2021/10/28 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class testQuickEncodeWithSignature { + public static void main(String[] args){ + Identifier clientIden = null; + try { + clientIden=new Identifier("/wefree/test"); + } catch (ComponentException e) { + e.printStackTrace(); + return; + } + Identifier serverIden = null; + try { +// serverIden=new Identifier("/hk/vpnserver/10/"+getFixLenthString(10)); + serverIden=new Identifier("/hk/vpnserver/10/"+testPrivate.getAll0String()); + } catch (ComponentException e) { + e.printStackTrace(); + return; + } + CPacket cPacket=new CPacket(); + cPacket.setSrcIdentifier(clientIden); + cPacket.setDstIdentifier(serverIden); + cPacket.ttl.setTtl(64); + byte[] pay=new byte[10]; + cPacket.payload.setValue(pay); + cPacket.encodeSelf(); // 先编码!!!减少发包阻塞。 + + System.out.println("签名前: "+Arrays.toString(cPacket.getRawData())); + System.out.println("签名前len: "+cPacket.getRawData().length); + +// byte[] ta=cPacket.getRawData(); +// System.out.println("ta len: "+ta.length); + int pos=testPrivate.findThePos(cPacket.getRawData()); + System.out.println("pos: "+pos); +// byte[] newData=replaceRandomPos(cPacket.getRawData(),pos); +// System.out.println("替换结果: "+ Arrays.toString(newData)); +// byte[] newData=replaceRandomPos(cPacket.getRawData(),pos,pos+10,1200); +// System.out.println("替换结果: "+ Arrays.toString(newData)); + + // 签名CPacket + KeyManagerExample.INSTANCE.initKeyChain("/wefree/test","D://"); + try { + KeyManagerExample.INSTANCE.getKeyChain().signCPacket(cPacket); + } catch (Exception e) { + e.printStackTrace(); + } + cPacket.encodeSelf(); + // 打印分析签名字段 + System.out.println("签名后: "+Arrays.toString(cPacket.getRawData())); + System.out.println("签名后len: "+cPacket.getRawData().length); + + // 打印带签名的CPacket的标识区 + byte[] oldIdentifierArea=extractIdentifierArea(cPacket.getRawData()); + System.out.println("&标识区: "+Arrays.toString(oldIdentifierArea)); + + // 更新标识区 +// byte[] newIdentifierArea=getNewIdentifierArea(oldIdentifierArea); +// System.out.println("新标识区:"+ Arrays.toString(newIdentifierArea)); + + // 提取签名参数区 + byte[] sigParamsArea=extractSigParamsArea(cPacket.getRawData()); + System.out.println("&签名参数区:"+ Arrays.toString(sigParamsArea)); + + // 制造只读区 + byte[] bytes=new byte[10]; + byte[] reayonlyArea=genReayonlyArea(bytes); + System.out.println("&只读区: "+Arrays.toString(reayonlyArea)); + + // 合并标识区和只读区 + assert oldIdentifierArea != null; +// byte[] idenAndReadonly=new byte[oldIdentifierArea.length+reayonlyArea.length]; +// System.arraycopy(oldIdentifierArea,0,idenAndReadonly,0,oldIdentifierArea.length); +// System.arraycopy(reayonlyArea,0,idenAndReadonly,oldIdentifierArea.length,reayonlyArea.length); + byte[] idenAndReadonly=mergeIdentityAndReayonly(oldIdentifierArea,reayonlyArea); + System.out.println("合并标识区和只读区:"+ Arrays.toString(idenAndReadonly)); + // 计算签名值区的密文 + byte[] signValueBytes; + try { + System.out.println("签名名称: "+KeyManagerExample.INSTANCE.getKeyChain().getCurrentIdentity().getName()); + signValueBytes=KeyManagerExample.INSTANCE.getKeyChain().signBytes(idenAndReadonly); + } catch (Exception e) { + e.printStackTrace(); + return; + } + System.out.println("签名值区的密文: "+ Arrays.toString(signValueBytes)); + System.out.println("签名值区的密文长度: "+signValueBytes.length); + // 验签:由于每次签名的结果(长度和数值)有一定随机性,因此这里使用验签来辩证是否成功签名 + try { + System.out.println("验签结果: "+KeyManagerExample.INSTANCE.getKeyChain().verifyBytes( + idenAndReadonly,signValueBytes)); + } catch (Exception e) { + e.printStackTrace(); + } + // 根据密文构造签名值区 + byte[] sigValueArea=genSigValueArea(signValueBytes); + System.out.println("&签名值区: "+ Arrays.toString(sigValueArea)); + + // 构造签名区 + assert sigParamsArea != null; + byte[] sigArea=genSigArea(sigParamsArea,sigValueArea); + System.out.println("签名区: "+ Arrays.toString(sigArea)); + + // 构造可变区 + byte[] varDataArea = new byte[]{(byte)53,(byte)5,(byte)55,(byte)3, + (byte)212,(byte)1,(byte)64}; // 可变区:TTL字段,TTL为64 + + // 构造整个包 + System.out.println(Arrays.toString(genCPacket(oldIdentifierArea, sigArea, reayonlyArea, varDataArea))); + } + + /** + * + * @param identifierArea 标识区 + * @param sigArea 签名区 + * @param reayonlyArea 只读区 + * @param varDataArea 可变区 + * @return + */ + public static byte[] genCPacket(byte[] identifierArea,byte[] sigArea, + byte[] reayonlyArea,byte[] varDataArea){ + VlInt packetlen=new VlInt(identifierArea.length+sigArea.length + +reayonlyArea.length+varDataArea.length); + int allLen; + try { + allLen=1+packetlen.size()+packetlen.getVlIntValue2Int(); + } catch (VlIntException e) { + e.printStackTrace(); + return null; + } + int startIndex=0; + byte[] cpacketBytes=new byte[allLen]; + cpacketBytes[startIndex]=(byte) 5; + startIndex++; + System.arraycopy(packetlen.getVlIntBytes(),0,cpacketBytes,startIndex,packetlen.size()); + startIndex+=packetlen.size(); + System.arraycopy(identifierArea,0,cpacketBytes,startIndex,identifierArea.length); + startIndex+=identifierArea.length; + System.arraycopy(sigArea,0,cpacketBytes,startIndex,sigArea.length); + startIndex+=sigArea.length; + System.arraycopy(reayonlyArea,0,cpacketBytes,startIndex,reayonlyArea.length); + startIndex+=reayonlyArea.length; + System.arraycopy(varDataArea,0,cpacketBytes,startIndex,varDataArea.length); + return cpacketBytes; + } + + public static byte[] genSigArea(byte[] sigParamsArea,byte[] sigValueArea){ + VlInt siglen=new VlInt(sigParamsArea.length+sigValueArea.length); + int allLen=1+siglen.size()+sigParamsArea.length+sigValueArea.length; + byte[] sigArea=new byte[allLen]; + sigArea[0]=(byte) 51; + System.arraycopy(siglen.getVlIntBytes(),0,sigArea,1,siglen.size()); + System.arraycopy(sigParamsArea,0,sigArea,1+siglen.size(),sigParamsArea.length); + System.arraycopy(sigValueArea,0,sigArea,1+siglen.size()+sigParamsArea.length,sigValueArea.length); + return sigArea; + } + + public static byte[] genSigValueArea(byte[] sigValue){ + VlInt vlInt=new VlInt(sigValue.length); + int allLen=sigValue.length+vlInt.size()+1; + byte[] sigValueArea=new byte[allLen]; + sigValueArea[0]=(byte) 200; + System.arraycopy(vlInt.getVlIntBytes(),0,sigValueArea,1,vlInt.size()); + System.arraycopy(sigValue,0,sigValueArea,1+vlInt.size(),sigValue.length); + return sigValueArea; + } + + public static byte[] mergeIdentityAndReayonly(byte[] identifierArea,byte[] readonlyArea){ + // 读取标识区负载长度 + VlInt identifierLen; + try { + identifierLen= TLV.readVarNumber(identifierArea,new VlInt(1)); + } catch (TLVException e) { + e.printStackTrace(); + return null; + } + // 读取只读区负载长度 + VlInt readLen; + try { + readLen= TLV.readVarNumber(readonlyArea,new VlInt(1)); + } catch (TLVException e) { + e.printStackTrace(); + return null; + } + // 合并区总长度 + int allLen; + try { + allLen=identifierLen.getVlIntValue2Int()+readLen.getVlIntValue2Int(); + } catch (VlIntException e) { + e.printStackTrace(); + return null; + } + // 拷贝到合并数组 + byte[] mergeArray=new byte[allLen]; + try { + System.arraycopy(identifierArea,1+identifierLen.size(), + mergeArray,0,identifierLen.getVlIntValue2Int()); + System.arraycopy(readonlyArea,1+readLen.size(), + mergeArray,identifierLen.getVlIntValue2Int(),readLen.getVlIntValue2Int()); + } catch (VlIntException e) { + e.printStackTrace(); + return null; + } + return mergeArray; + } + + /** + * 计算整个标识区的长度,并返回该标识区 + * @param targetArray 带签名的CPacket做编码得到的byte[] + * @return + */ + public static byte[] extractIdentifierArea(byte[] targetArray){ + int identifierEndPos=testPrivate.findThePos(targetArray)+10; + // 读取整个CPacket的总长度 + VlInt allLen; + try { + allLen= TLV.readVarNumber(targetArray,new VlInt(1)); + } catch (TLVException e) { + e.printStackTrace(); + return null; + } + System.out.println("CPacket-负载长度: "+allLen); + // 计算标识区的长度 + int identifierLen=identifierEndPos-1-allLen.size(); + // 提取标识区 + byte[] identifierArea=new byte[identifierLen]; + System.arraycopy(targetArray,1+allLen.size(),identifierArea,0,identifierLen); + return identifierArea; + } + + /** + * 提取签名参数区 + * @param targetArray + * @return + */ + public static byte[] extractSigParamsArea(byte[] targetArray){ + int identifierEndPos=testPrivate.findThePos(targetArray)+10; + // 读取整个签名区的总长度 + VlInt sigAreaLen; + try { + sigAreaLen = TLV.readVarNumber(targetArray,new VlInt(identifierEndPos+1)); + } catch (TLVException e) { + e.printStackTrace(); + return null; + } + System.out.println("签名区-负载长度: "+sigAreaLen); + // 计算签名参数区的长度 + VlInt sigParamsAreaLen; + try { + sigParamsAreaLen=TLV.readVarNumber(targetArray,new VlInt(identifierEndPos+1 + +sigAreaLen.size()+1)); + } catch (TLVException e) { + e.printStackTrace(); + return null; + } + System.out.println("签名参数区-负载长度: "+sigParamsAreaLen); + // 提取签名参数区 + int sigParamsAllLen; + byte[] sigParamsArea; + try { + sigParamsAllLen=sigParamsAreaLen.getVlIntValue2Int()+1+sigParamsAreaLen.size(); + sigParamsArea = new byte[sigParamsAllLen]; + } catch (VlIntException e) { + e.printStackTrace(); + return null; + } + System.out.println("签名参数区-总长度:"+sigParamsAllLen); + System.arraycopy(targetArray,identifierEndPos+1+sigAreaLen.size(), + sigParamsArea,0,sigParamsAllLen); + return sigParamsArea; + } + + /** + * 产生一个新的标识区:替换最后10个字节为随机的byte[] + * @return + */ + public static byte[] getNewIdentifierArea(byte[] oldIdentifierArray){ + System.arraycopy(testPrivate.getFixLenthString(10).getBytes(StandardCharsets.UTF_8), + 0,oldIdentifierArray,oldIdentifierArray.length-10,10); + return oldIdentifierArray; + } + + public static byte[] genReayonlyArea(byte[] buf){ + VlInt payloadLen=new VlInt(buf.length); + VlInt readonlyLen=new VlInt(buf.length+payloadLen.size()+1); + int allLen=buf.length+payloadLen.size()+1+readonlyLen.size()+1; + byte[] readonlyArea=new byte[allLen]; + readonlyArea[0]=(byte)52; + System.arraycopy(readonlyLen.getVlIntBytes(),0,readonlyArea,1,readonlyLen.size()); + readonlyArea[1+readonlyLen.size()]=(byte)204; + System.arraycopy(payloadLen.getVlIntBytes(),0,readonlyArea, + 1+readonlyLen.size()+1,payloadLen.size()); + System.arraycopy(buf,0,readonlyArea, + 1+readonlyLen.size()+1+payloadLen.size(),buf.length); + return readonlyArea; + } +}