fix:单元测试时Packet模块中遇到的NullPointerException

add:KeyChain单元测试
This commit is contained in:
ChessNineeee
2021-04-14 22:17:48 +08:00
parent bbee7f879e
commit 528141ab5f
5 changed files with 431 additions and 27 deletions
+8 -5
View File
@@ -157,12 +157,15 @@ public class CPacket implements InteractWithField, IEncodingAble {
// 填充只读区
// 首先清除所有的Block
minPacket.readOnlyField.clearBlocks();
block = new SelfEncodingBase().selfWireEncode(this.payload);
if (block == null) {
return false;
if (this.payload.getValue() != null){
minPacket.readOnlyField.clearBlocks();
block = new SelfEncodingBase().selfWireEncode(this.payload);
if (block == null) {
return false;
}
minPacket.readOnlyField.addBlock(block);
}
minPacket.readOnlyField.addBlock(block);
// 填充标识区
// 首先清除所有的标识
+7 -4
View File
@@ -154,11 +154,14 @@ public class Data implements IEncodingAble, InteractWithField {
}
// Payload
block = new SelfEncodingBase().selfWireEncode(this.payload);
if (block == null) {
return false;
if (this.payload.getValue() != null){
block = new SelfEncodingBase().selfWireEncode(this.payload);
if (block == null) {
return false;
}
minPacket.readOnlyField.addBlock(block);
}
minPacket.readOnlyField.addBlock(block);
/////////////////////////////////////////////////////////////
//// 填充标识区
+6 -4
View File
@@ -237,11 +237,13 @@ public class Interest implements InteractWithField, IEncodingAble {
}
// Payload
block = new SelfEncodingBase().selfWireEncode(this.payload);
if (block == null) {
return false;
if (this.payload.getValue() != null){
block = new SelfEncodingBase().selfWireEncode(this.payload);
if (block == null) {
return false;
}
minPacket.readOnlyField.addBlock(block);
}
minPacket.readOnlyField.addBlock(block);
/////////////////////////////////////////////////////////////
//// 填充标识区
+100 -14
View File
@@ -28,6 +28,7 @@ import java.util.IdentityHashMap;
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
public class KeyChain {
private static final String defaultIdentifyName = "/localhost/operator";
public IdentifyManager getIdentifyManager() {
return identifyManager;
}
@@ -54,14 +55,19 @@ public class KeyChain {
* @author hongyu guo
* @date 2021/3/11
**/
public KeyChain(){
public KeyChain() throws Exception{
identifyManager = new IdentifyManager();
currentIdentity = identifyManager.getDefaultIdentity();
// TODO: 考虑是否需要在没有默认身份的时候创建一个缺省的本地网络身份
// DONE: 考虑是否需要在没有默认身份的时候创建一个缺省的本地网络身份
if (currentIdentity == null){
Identity newId = this.identifyManager.createIdentityByName(defaultIdentifyName, "", true);
this.identifyManager.setDefaultIdentity(newId);
this.currentIdentity = newId;
}
}
/**
* 设置当前使用的网络身份
* 设置当前使用的网络身份,用 password 对目标网络身份进行解锁
* @param identity
* @param passwd 如果passwd不为null 且不为空字符串, 则使用该passwd对identity进行解密
* @return void
@@ -70,8 +76,10 @@ public class KeyChain {
**/
public void setCurrentIdentity(Identity identity, String passwd) {
try {
if(passwd != null && !passwd.equals(""))
if(passwd != null && !passwd.equals("")){
identity.unLock(passwd, identifyManager.getPrivateKeyEncryptionAlgorithm());
currentIdentity = identity;
}
} catch (IdentityException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
@@ -124,20 +132,45 @@ public class KeyChain {
}
/**
* 从 MIN 网络包中提取出标识区和只读区的值,用于签名和验签
* @param packet MINPacket
* @return byte[]
* @throws Exception
*/
private byte[] getIdentifierAndReadOnlyValueFromPacket(MINPacket packet) throws Exception{
Block iBlock = new SelfEncodingBase().selfWireEncode(packet.identifierField);
Block rBlock = new SelfEncodingBase().selfWireEncode(packet.readOnlyField);
byte[] iBlockValue = iBlock.getValue();
byte[] rBlockValue = rBlock.getValue();
byte[] rawData = new byte[iBlockValue.length + rBlockValue.length];
System.arraycopy(iBlockValue, 0, rawData, 0, iBlockValue.length);
System.arraycopy(rBlockValue, 0, rawData, iBlockValue.length, rBlockValue.length);
byte[] rawData = null;
byte[] iBlockValue = null;
byte[] rBlockValue = null;
int totalLength = 0;
// 1. 获取标识区数据
Block iBlock = new SelfEncodingBase().selfWireEncode(packet.identifierField);
if (iBlock != null){
iBlockValue = iBlock.getValue();
totalLength += iBlockValue.length;
}
// 2. 获取只读区数据
Block rBlock = new SelfEncodingBase().selfWireEncode(packet.readOnlyField);
if (rBlock != null){
rBlockValue = rBlock.getValue();
totalLength += rBlockValue.length;
}
// 3. 合并数据
if (totalLength == 0)
return rawData;
rawData = new byte[totalLength];
if (iBlock != null)
System.arraycopy(iBlockValue, 0, rawData, 0, iBlockValue.length);
if (rBlock != null)
System.arraycopy(rBlockValue, 0, rawData, iBlockValue.length, rBlockValue.length);
return rawData;
}
/**
* 给一个通用的网络包签名
* @param packet
* @throws Exception
*/
public void sign(MINPacket packet) throws Exception{
// 首先检查当前使用的身份是否可以用来签名
checkIdentifyCanUseToSign(this.currentIdentity);
@@ -153,21 +186,41 @@ public class KeyChain {
packet.signatureField.addSignature(signature);
}
/**
* 对CPacket进行签名
* @param cPacket
* @throws Exception
*/
public void signCPacket(CPacket cPacket) throws Exception{
cPacket.fillDataToFields();
this.sign(cPacket.minPacket);
}
/**
* 对Interest进行签名
* @param interest
* @throws Exception
*/
public void signInterest(Interest interest) throws Exception{
interest.fillDataToFields();
this.sign(interest.minPacket);
}
/**
* 对Data进行签名
* @param data
* @throws Exception
*/
public void signData(Data data) throws Exception{
data.fillDataToFields();
this.sign(data.minPacket);
}
/**
* 验证一个MIN网络包中的签名是否有效
* @param minPacket
* @throws Exception
*/
public void verify(MINPacket minPacket) throws Exception{
// 提取签名区的第一个签名进行验证(认为签名区的第一个签名为包的签名,包含标识区和只读区签名)
Signature signature = minPacket.signatureField.getSignature(0);
@@ -183,28 +236,61 @@ public class KeyChain {
identity.verify(rawData, signature.getSigValue().getValue());
}
/**
* 验证一个 CPacket 中的签名是否有效
* @param packet
* @throws Exception
*/
public void verifyCPacket(CPacket packet) throws Exception{
packet.fillDataToFields();
verify(packet.minPacket);
}
/**
* 验证一个 Interest 中的签名是否有效
* @param interest
* @throws Exception
*/
public void verifyInterest(Interest interest) throws Exception{
interest.fillDataToFields();
verify(interest.minPacket);
}
/**
* 验证一个 Data 中的签名是否有效
* @param data
* @throws Exception
*/
public void verifyData(Data data) throws Exception{
data.fillDataToFields();
verify(data.minPacket);
}
/**
* 将一个网络身份导出为一个 SafeBag 对象
* @param identity
* @param passwd
* @return SafeBag
* @throws Exception
*/
public SafeBag exportSafeBag(Identity identity, String passwd) throws Exception{
if (identity == null)
return null;
byte[] res = identity.dump(passwd);
SafeBag safeBag = new SafeBag(res);
return safeBag;
}
/**
* 从一个 SafeBag 中导入网络身份,保存到本地
* @param safeBag
* @param passwd
* @param force
* @throws Exception
*/
public void importSafeBag(SafeBag safeBag, String passwd, boolean force) throws Exception{
if (safeBag == null)
throw new KeyChainException(String.format("SafeBag is %s", safeBag));
Identity identity = Identity.load(safeBag.getValue(), passwd);
if (!this.identifyManager.existIdentity(identity.getName()) || force){
+310
View File
@@ -1,13 +1,66 @@
package security;
import component.Identifier;
import component.TTL;
import encoding.TLV;
import encoding.VlInt;
import minsecurity.Common;
import minsecurity.certificate.cert.CertUtils;
import minsecurity.certificate.cert.Certificate;
import minsecurity.crypto.sm2.SM2KeyPair;
import minsecurity.identity.Identity;
import minsecurity.identity.KeyParam;
import minsecurity.identity.TestIdentity;
import org.checkerframework.checker.units.qual.C;
import org.checkerframework.checker.units.qual.K;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import packet.CPacket;
import packet.Data;
import packet.Interest;
import packet.MINPacket;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
public class KeyChainTest {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestIdentity.class);
/**
* 随机生成身份数据
* @return Identity
*/
private Identity createRandomIdentity() throws Exception{
// 测试PersistIdentity
SM2KeyPair pair = SM2KeyPair.generateKeyPair();
Identity identity = new Identity();
identity.setName("/wzq"+Math.random()); // 身份名称必须以/开头 Identifier规定
KeyParam keyParam = new KeyParam();
keyParam.PublicKeyAlgorithm = 0;
keyParam.SignatureAlgorithm = 0;
identity.setKeyParam(keyParam);
identity.setPrikey(pair.getSm2PrivateKey());
identity.setPubkey(pair.getSm2PublicKey());
identity.setPasswd("2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99");
identity.lock("0123456789abcdef", Common.SM4ECB);
Certificate cert = new Certificate();
cert.setVersion(1);
cert.setSerialNumber(1);
cert.setPublicKey(pair.getSm2PublicKey());
cert.setSignatureAlgorithm(Common.SM3withSM2); // TODO 名字有误? SM2withSM3?
cert.setPublicKeyAlgorithm(Common.SM2);
cert.setIssueTo("root");
cert.setIssuer("root");
long timestamp = System.currentTimeMillis() / 1000;
cert.setTimestamp(timestamp); // 10bit timestamp
cert.setNotAfter(timestamp); // 10bit timestamp
cert.setNotBefore(timestamp + 1000); // 10bit timestamp
cert.setKeyUsage(Common.CertSign);
cert.setCA(true);
CertUtils.signCert(cert, pair.getSm2PrivateKey());
identity.setCert(cert);
return identity;
}
@Test
public void testCreateKeyChain(){
try{
@@ -19,6 +72,7 @@ public class KeyChainTest {
ConcurrentHashMap<String, Identity> identityHashMap = new ConcurrentHashMap<>();
identityHashMap.put("/wzq", identity);
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
keyChain.getIdentifyManager().setIdentifies(identityHashMap);
keyChain.getIdentifyManager().setDefaultIdentity(identity);
@@ -26,8 +80,264 @@ public class KeyChainTest {
Identity identity1 = keyChain.getIdentifyManager().createIdentityByName("/wzq1", passwd, false);
identity1.unLock(passwd, Common.SM4ECB);
System.out.println(identity1.getPrikey());
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
}catch (Exception ex){
System.out.println(ex.getMessage());
}
}
@Test
public void testInitialKeyChain(){
try {
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id = createRandomIdentity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testSignAndVerifyInterest(){
try {
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id = createRandomIdentity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
// 身份允许签名与验证签名
Identifier id1 = new Identifier("/min/pku/sz");
Identifier id2 = new Identifier("/install");
//////////////////// 构建兴趣包 ////////////////////////
Interest interest = new Interest();
interest.minPacket.packetType = new VlInt(3);
interest.setName(id1);
interest.canBePrefix.setCanBePrefix(true);
interest.mustBeRefresh.setMustBeRefresh(true);
interest.nonce.setNonce(1234);
interest.hopLimit.setHopLimit(1234);
interest.congestionMark.setCongestionLevel(1234);
interest.ttl.setTtl(1234);
interest.payload.setValue(new byte[]{1, 2, 3, 4, 5});
// 正常测试签名与验签
keyChain.signInterest(interest);
keyChain.verifyInterest(interest);
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testSignAndVerifyInterest2(){
try {
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id = createRandomIdentity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
// 身份允许签名与验证签名
Identifier id1 = new Identifier("/min/pku/sz");
Identifier id2 = new Identifier("/install");
//////////////////// 构建兴趣包 只读区与标识区为空 ////////////////////////
Interest interest = new Interest();
interest.minPacket.packetType = new VlInt(3);
// interest.setName(id1);
// interest.canBePrefix.setCanBePrefix(true);
// interest.mustBeRefresh.setMustBeRefresh(true);
// interest.nonce.setNonce(1234);
// interest.hopLimit.setHopLimit(1234);
// interest.interestLifeTime.setInterestLifeTime(1234);
interest.congestionMark.setCongestionLevel(1234);
interest.ttl.setTtl(1234);
// interest.payload.setValue(new byte[]{1, 2, 3, 4, 5});
// 测试无数据的签名与验签 通过
keyChain.signInterest(interest);
keyChain.verifyInterest(interest);
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testSignAndVerifyCPacket2(){
try {
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id = createRandomIdentity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
// 身份允许签名与验证签名
// Identifier id1 = new Identifier("/min/pku/sz");
// Identifier id2 = new Identifier("/install");
CPacket cPacket = new CPacket();
cPacket.minPacket.packetType = new VlInt(3);
// cPacket.setSrcIdentifier(id1);
// cPacket.setDstIdentifier(id2);
cPacket.setTtl(new TTL(16546418374324163L));
// cPacket.payload.setValue(new byte[]{1, 2, 3, 4, 6});
// 测试无数据的签名与验证 通过
keyChain.signCPacket(cPacket);
keyChain.verifyCPacket(cPacket);
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testSignAndVerifyCPacket(){
try {
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id = createRandomIdentity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
// 身份允许签名与验证签名
Identifier id1 = new Identifier("/min/pku/sz");
Identifier id2 = new Identifier("/install");
CPacket cPacket = new CPacket();
cPacket.minPacket.packetType = new VlInt(3);
cPacket.setSrcIdentifier(id1);
cPacket.setDstIdentifier(id2);
cPacket.setTtl(new TTL(16546418374324163L));
cPacket.payload.setValue(new byte[]{1, 2, 3, 4, 6});
// 正常测试签名与验签
keyChain.signCPacket(cPacket);
keyChain.verifyCPacket(cPacket);
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testSignAndVerifyData(){
try{
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id = createRandomIdentity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
//////////////////// 构建Data包 ////////////////////////
Data data = new Data();
data.freshnessPeriod.setFreshnessPeriod(02346345465453L);
data.payload.setValue(new byte[]{1, 2, 3, 4, 5});
data.congestionMark.setCongestionLevel(1234L);
Identifier id2 = new Identifier("/wzq");
data.setName(id2);
data.minPacket.packetType = new VlInt(3);
// 正常测试签名与验签
keyChain.signData(data);
keyChain.verifyData(data);
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testSignAndVerifyData2(){
try{
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id = createRandomIdentity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
//////////////////// 构建Data包 无只读区与标识区 ////////////////////////
Data data = new Data();
// data.freshnessPeriod.setFreshnessPeriod(02346345465453L);
// data.payload.setValue(new byte[]{1, 2, 3, 4, 5});
data.congestionMark.setCongestionLevel(1234L);
Identifier id2 = new Identifier("/wzq");
data.setName(id2);
data.minPacket.packetType = new VlInt(3);
// 测试无数据的签名与验证 通过
keyChain.signData(data);
keyChain.verifyData(data);
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testExportAndImportSafeBag(){
try{
Identity id = createRandomIdentity();
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id2 = createRandomIdentity();
id2.unLock("0123456789abcdef", Common.SM4ECB); // 锁住的Identity无法导出
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
// 正常导入导出 通过
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
SafeBag bag = keyChain.exportSafeBag(id2, "1234");
keyChain.importSafeBag(bag, "1234", true);
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testExportAndImportSafeBag2(){
try{
Identity id = createRandomIdentity();
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id2 = createRandomIdentity();
id2.unLock("0123456789abcdef", Common.SM4ECB); // 锁住的Identity无法导出
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
// 导入null 抛出异常
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
SafeBag bag = keyChain.exportSafeBag(null, "1234");
keyChain.importSafeBag(bag, "1234", true);
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
@Test
public void testExportAndImportSafeBag3(){
try{
Identity id = createRandomIdentity();
// 测试设置新身份为当前身份
KeyChain keyChain = new KeyChain();
Identity id2 = new Identity();
keyChain.getIdentifyManager().setDefaultIdentity(id, true);
// 输入密码用于解锁身份
keyChain.setCurrentIdentity(keyChain.getIdentifyManager().getDefaultIdentity(), "0123456789abcdef");
// 导入空Identity 抛出异常
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
SafeBag bag = keyChain.exportSafeBag(null, "1234");
keyChain.importSafeBag(bag, "1234", true);
logger.debug(String.format("身份数量:%d", keyChain.getIdentifyManager().getIdentifies().size()));
}catch (Exception ex){
logger.debug(ex.getMessage());
}
}
}