diff --git a/src/main/java/minsecurity/Common.java b/src/main/java/minsecurity/Common.java index 35b9f7a..a8b6e1b 100644 --- a/src/main/java/minsecurity/Common.java +++ b/src/main/java/minsecurity/Common.java @@ -2,7 +2,7 @@ package minsecurity; /* * @Author: hongyu guo - * @Description: + * @Description: 归纳所用常用变量 * @Version: 1.0.0 * @Date: 16:40 2021/03/04 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 diff --git a/src/main/java/minsecurity/certificate/cert/CertUtils.java b/src/main/java/minsecurity/certificate/cert/CertUtils.java index 8c95094..58a52a7 100644 --- a/src/main/java/minsecurity/certificate/cert/CertUtils.java +++ b/src/main/java/minsecurity/certificate/cert/CertUtils.java @@ -125,10 +125,11 @@ public class CertUtils { * 将TbsCertificate类型实例转化为字节流 * @param tbsCertificate * @return byte[] + * @throws CertException * @author hongyu guo * @date 2021/3/7 **/ - public static byte[] serialization(TbsCertificate tbsCertificate){ + public static byte[] serialization(TbsCertificate tbsCertificate) throws CertException { ObjectMapper mapper = new ObjectMapper(); byte[] bytesOfCertJson; try { @@ -137,17 +138,18 @@ public class CertUtils { } catch (JsonProcessingException e) { e.printStackTrace(); } - return new byte[0]; + throw new CertException("tbsCertificate serialization failed"); } /** * 将InnerCertificate类型实例转化为字节流 * @param innerCertificate * @return byte[] + * @throws CertException * @author hongyu guo * @date 2021/3/7 **/ - public static byte[] serialization(InnerCertificate innerCertificate){ + public static byte[] serialization(InnerCertificate innerCertificate) throws CertException { ObjectMapper mapper = new ObjectMapper(); byte[] bytesOfCertJson; try { @@ -156,7 +158,7 @@ public class CertUtils { } catch (JsonProcessingException e) { e.printStackTrace(); } - return new byte[0]; + throw new CertException("innerCertificate serialization failed"); } /** @@ -280,12 +282,15 @@ public class CertUtils { * @author hongyu guo * @date 2021/3/7 **/ - public static Certificate fromPem(String pemString, byte[] passwd, int symAlgoMode) throws CertException, BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException, InvalidKeyException { + public static Certificate fromPem(String pemString, byte[] passwd, int symAlgoMode) + throws CertException, BadPaddingException, NoSuchPaddingException, + InvalidAlgorithmParameterException, NoSuchAlgorithmException, + IllegalBlockSizeException, NoSuchProviderException, InvalidKeyException { if(pemString == null || pemString.equals("")){ throw new CertException("pem串为空"); } byte[] bytesOfPem = Base64.getDecoder().decode(pemString); - byte[] bytesOfCert = new byte[0]; + byte[] bytesOfCert; if(passwd != null && passwd.length > 0){ byte[] sm4Key = KeyUtils.get16bytePasswd(passwd); switch (symAlgoMode){ @@ -295,6 +300,8 @@ public class CertUtils { case Common.SM4ECB: bytesOfCert = SM4.decrypt_ECB_Padding(sm4Key, bytesOfPem); break; + default: + throw new CertException("未知的对称加密算法"); } } else { bytesOfCert = bytesOfPem; diff --git a/src/main/java/minsecurity/crypto/AsymKeyException.java b/src/main/java/minsecurity/crypto/AsymKeyException.java new file mode 100644 index 0000000..ca034ec --- /dev/null +++ b/src/main/java/minsecurity/crypto/AsymKeyException.java @@ -0,0 +1,14 @@ +package minsecurity.crypto; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 10:51 2021/03/12 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class AsymKeyException extends Exception{ + public AsymKeyException(String msg){ + super(msg); + } +} diff --git a/src/main/java/minsecurity/crypto/sm2/SM2Base.java b/src/main/java/minsecurity/crypto/sm2/SM2Base.java index b52a2cb..afe9531 100644 --- a/src/main/java/minsecurity/crypto/sm2/SM2Base.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2Base.java @@ -166,5 +166,9 @@ public class SM2Base { return new ECPublicKeyParameters(ecPubKey.getQ(), domainParameters); } + public static SM2KeyPair generateSM2KeyPair(){ + return SM2KeyPair.generateKeyPair(); + } + } diff --git a/src/main/java/minsecurity/crypto/sm2/SM2Exception.java b/src/main/java/minsecurity/crypto/sm2/SM2Exception.java index 79916b2..d776020 100644 --- a/src/main/java/minsecurity/crypto/sm2/SM2Exception.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2Exception.java @@ -1,5 +1,7 @@ package minsecurity.crypto.sm2; +import minsecurity.crypto.AsymKeyException; + /* * @Author: hongyu guo * @Description: sm2的自定义异常 @@ -7,7 +9,7 @@ package minsecurity.crypto.sm2; * @Date: 19:00 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class SM2Exception extends java.lang.Exception { +public class SM2Exception extends AsymKeyException { public SM2Exception(String msg){ super(msg); } diff --git a/src/main/java/minsecurity/crypto/sm2/SM2KeyPair.java b/src/main/java/minsecurity/crypto/sm2/SM2KeyPair.java new file mode 100644 index 0000000..d1730a2 --- /dev/null +++ b/src/main/java/minsecurity/crypto/sm2/SM2KeyPair.java @@ -0,0 +1,41 @@ +package minsecurity.crypto.sm2; + +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 09:57 2021/03/11 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class SM2KeyPair { + private final SM2PublicKey sm2PublicKey; + private final SM2PrivateKey sm2PrivateKey; + + public SM2KeyPair(SM2PublicKey sm2PublicKey, SM2PrivateKey sm2PrivateKey) { + this.sm2PublicKey = sm2PublicKey; + this.sm2PrivateKey = sm2PrivateKey; + } + + public static SM2KeyPair generateKeyPair(){ + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); + ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); + ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); + byte[] d = priKey.getD().toByteArray(); + byte[] x = pubKey.getQ().getAffineXCoord().getEncoded(); + byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); + return new SM2KeyPair(new SM2PublicKey(x,y), new SM2PrivateKey(d)); + } + + + public SM2PublicKey getSm2PublicKey() { + return sm2PublicKey; + } + + public SM2PrivateKey getSm2PrivateKey() { + return sm2PrivateKey; + } +} diff --git a/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java b/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java index cfdd7ce..be2e269 100644 --- a/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java @@ -49,7 +49,7 @@ public class SM2PublicKey implements PublicKeyInterface { public byte[] getBytes() { if(publicKey != null) return publicKey.getQ().getEncoded(false); //不压缩 - return new byte[0]; + return null; } @Override diff --git a/src/main/java/minsecurity/identity/Identity.java b/src/main/java/minsecurity/identity/Identity.java index f678dd4..262cbf5 100644 --- a/src/main/java/minsecurity/identity/Identity.java +++ b/src/main/java/minsecurity/identity/Identity.java @@ -5,12 +5,11 @@ 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.*; +import minsecurity.crypto.sm2.SM2Exception; 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; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; @@ -60,12 +59,36 @@ public class Identity { IsDefault = isDefault; } + /** + * 参数中不包含PrikeyRawByte + * @author hongyu guo + * @date 2021/3/12 + **/ + public Identity(String name, KeyParam keyParam, + PrivateKeyInterface prikey, PublicKeyInterface pubkey, + String passwd, Certificate cert, + boolean isDefault) { + Name = name; + KeyParam = keyParam; + Prikey = prikey; + Pubkey = pubkey; + Passwd = passwd; + Cert = cert; + IsDefault = isDefault; + } + public Identity(){} - - public byte[] sign(byte[] digest) throws CryptoException { + /*** + * 使用identity的私钥对数据进行签名 + * @param content 被签名数据 + * @return byte[] 签名成功时返回摘要, 失败时返回null + * @author hongyu guo + * @date 2021/3/12 + **/ + public byte[] sign(byte[] content) throws CryptoException { if(this.Prikey == null) return null; switch (this.KeyParam.PublicKeyAlgorithm){ @@ -73,7 +96,7 @@ public class Identity { SM2PrivateKey sm2PrivateKey = (SM2PrivateKey) this.Prikey; switch (this.KeyParam.SignatureAlgorithm){ case Common.SM3withSM2: - return sm2PrivateKey.sign(digest); + return sm2PrivateKey.sign(content); default: return null; } @@ -82,9 +105,24 @@ public class Identity { } } - public boolean verify(byte[] msg, byte[] digest) { + /*** + * 使用identity的公钥进行验签 + * 目前支持使用sm2公钥进行验签 + * @param msg + * @param digest + * @return boolean + * @throws IdentityException + * @throws AsymKeyException + * @author hongyu guo + * @date 2021/3/12 + **/ + public boolean verify(byte[] msg, byte[] digest) throws IdentityException, AsymKeyException { + if(msg == null) + throw new IdentityException("source data should not be null"); + if(digest == null) + throw new IdentityException("digest should not be null"); if(this.Pubkey == null) - return false; + throw new IdentityException("pubkey in identity is null"); switch (this.KeyParam.PublicKeyAlgorithm){ case Common.SM2: SM2PublicKey sm2PublicKey = (SM2PublicKey) this.Pubkey; @@ -92,26 +130,57 @@ public class Identity { case Common.SM3withSM2: return sm2PublicKey.verify(msg, digest); default: - return false; + throw new AsymKeyException("unknown signatureAlgorithm"); } default: - return false; + throw new AsymKeyException("unknown asymmetric algorithm"); } } - public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException { + /** + * 使用identity的密钥对密文进行解密, 返回解密数据. + * identity中的私钥为空或密文有误时时将抛出异常 + * @param cipher 密文 + * @return byte[] + * @throws IdentityException + * @throws InvalidCipherTextException + * @author hongyu guo + * @date 2021/3/12 + **/ + public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException, IdentityException { if(this.Prikey == null) - return null; + throw new IdentityException("prikey in identity should not be null"); return this.Prikey.decrypt(cipher); } - - public byte[] encrypt(byte[] content) throws InvalidCipherTextException { + /** + * 使用identity的密钥对密文进行加密, 返回加密数据. + * identity中的公钥为空或原文有误时时将抛出异常 + * @param content 原文 + * @return byte[] + * @throws IdentityException + * @throws InvalidCipherTextException + * @author hongyu guo + * @date 2021/3/12 + **/ + public byte[] encrypt(byte[] content) throws InvalidCipherTextException, IdentityException { if(this.Pubkey == null) - return null; + throw new IdentityException("public in identity should not be null"); return this.Pubkey.encrypt(content); } - public byte[] dump(String passwd) throws NoSuchPaddingException, InvalidAlgorithmParameterException, CertException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, JsonProcessingException { + /** + * 对Identity进行序列化, 如果为passwd不为空, 会对序列化后的代码进行SM4对称加密, + * 最后返回base64编码后的序列化结果 + * @param passwd 密码, 不为空(null || "")时进行加密 + * @return byte[] + * @throws IdentityException ... + * @author hongyu guo + * @date 2021/3/12 + **/ + public byte[] dump(String passwd) + throws NoSuchPaddingException, InvalidAlgorithmParameterException, CertException, + IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, + NoSuchProviderException, InvalidKeyException, JsonProcessingException, IdentityException { ObjectMapper mapper = new ObjectMapper(); InnerIdentity innerIdentity = IdentityUtil.parseIdentityToInner(this); byte[] bytesOfInnerIdentity = mapper.writeValueAsBytes(innerIdentity); @@ -124,11 +193,20 @@ public class Identity { return Base64.getEncoder().encode(bytesOfInnerIdentity); } - public static Identity load(byte[] data, String passwd) + /** + * 将序列化的identity byte数组反序列化为identity实例 + * @param bytesOfSerialization 已经序列化的identity + * @param passwd 密码, 不为空(null || "")时进行解密 + * @return minsecurity.identity.Identity + * @throws CertException + * @author hongyu guo + * @date 2021/3/12 + **/ + public static Identity load(byte[] bytesOfSerialization, String passwd) throws BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException, InvalidKeyException, CertException { - byte[] bytesOfIdentity = Base64.getDecoder().decode(data); + byte[] bytesOfIdentity = Base64.getDecoder().decode(bytesOfSerialization); byte[] plain; if(passwd != null && passwd.length() != 0){ byte[] sm4Key = KeyUtils.get16bytePasswd(passwd.getBytes()); diff --git a/src/main/java/minsecurity/identity/IdentityUtil.java b/src/main/java/minsecurity/identity/IdentityUtil.java index 87a0814..4735725 100644 --- a/src/main/java/minsecurity/identity/IdentityUtil.java +++ b/src/main/java/minsecurity/identity/IdentityUtil.java @@ -24,24 +24,43 @@ import java.security.NoSuchProviderException; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class IdentityUtil { + /** + * 将identity转化为内部结构(innerIdentity), 便于编码 + * identity的公私钥以及证书都不能为空 + * @param identity + * @return minsecurity.identity.InnerIdentity + * @throws CertException ... + * @author hongyu guo + * @date 2021/3/12 + **/ public static InnerIdentity parseIdentityToInner(Identity identity) throws NoSuchPaddingException, InvalidKeyException, CertException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, - NoSuchProviderException, InvalidAlgorithmParameterException { + NoSuchProviderException, InvalidAlgorithmParameterException, IdentityException { + if(identity.getPubkey() == null) + throw new IdentityException("public key in identity is null"); + if(identity.getPrikey() == null) + throw new IdentityException("private key in identity is null"); + if(identity.getCert() == null) + throw new IdentityException("certificate in identity is null"); 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.setPrikey(identity.getPrikey().getBytes()); + innerIdentity.setPubkey(identity.getPubkey().getBytes()); innerIdentity.setPasswd(identity.getPasswd()); innerIdentity.setCert(CertUtils.toPem(identity.getCert(), identity.getPasswd().getBytes(), Common.SM4CBC)); + return innerIdentity; } + /** + * @param innerIdentity + * @return minsecurity.identity.Identity + * @throws CertException ... + * @author hongyu guo + * @date 2021/3/12 + **/ public static Identity parseInnerToIdentity(InnerIdentity innerIdentity) throws BadPaddingException, InvalidKeyException, CertException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, diff --git a/src/main/java/minsecurity/identity/InnerIdentity.java b/src/main/java/minsecurity/identity/InnerIdentity.java index 927f46a..c74226e 100644 --- a/src/main/java/minsecurity/identity/InnerIdentity.java +++ b/src/main/java/minsecurity/identity/InnerIdentity.java @@ -1,13 +1,10 @@ package minsecurity.identity; -import minsecurity.certificate.cert.Certificate; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; -import java.util.Arrays; - /* * @Author: hongyu guo - * @Description: + * @Description: 将公私钥转化为byte数组格式、 证书转化为pem格式, 方便对identity进行序列化 * @Version: 1.0.0 * @Date: 09:41 2021/03/09 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 diff --git a/src/main/java/minsecurity/identity/persist/MapDB.java b/src/main/java/minsecurity/identity/persist/MapDB.java index 308a969..a06785c 100644 --- a/src/main/java/minsecurity/identity/persist/MapDB.java +++ b/src/main/java/minsecurity/identity/persist/MapDB.java @@ -24,6 +24,8 @@ public class MapDB { public static final String defaultPath = "./target/test.db"; public static final String defaultIdentity = "identity"; public static final String defaultName = "/default"; + + private DB db; private ConcurrentMap identityMap; private Serializer customSerializer; diff --git a/src/main/java/security/IdentifyManager.java b/src/main/java/security/IdentifyManager.java new file mode 100644 index 0000000..5b42385 --- /dev/null +++ b/src/main/java/security/IdentifyManager.java @@ -0,0 +1,187 @@ +package security; + +import minsecurity.Common; +import minsecurity.crypto.sm2.SM2Base; +import minsecurity.crypto.sm2.SM2KeyPair; +import minsecurity.identity.Identity; +import minsecurity.identity.IdentityException; +import minsecurity.identity.KeyParam; +import minsecurity.identity.persist.MapDB; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.concurrent.ConcurrentMap; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 15:45 2021/03/10 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +// TODO: 测试 +public class IdentifyManager { + + private final ConcurrentMap identifies; // 一个map,存储了身份名字和网络身份实体的映射 + private Identity defaultIdentity; // 默认网络身份 + private int privateKeyEncryptionAlgorithm; // 对秘钥加密所使用的加密算法 + + + /** + * 1. 尝试从本地持久化存储中拉取所有的网络身份信息; + * 2. 尝试获取本地持久化记录当中本系统的默认网络身份信息; + * @param + * @return + * @author hongyu guo + * @date 2021/3/11 + **/ + public IdentifyManager(){ + MapDB mapDB = MapDB.getInstance(); + // TODO: 目前使用浅拷贝, 是否需要修改为深拷贝? + this.identifies = mapDB.getIdentityMap(); + this.defaultIdentity = MapDB.getInstance().getDefaultIdentity(); + this.privateKeyEncryptionAlgorithm = Common.SM4ECB; + } + + + /** + * 通过身份的名字获取网络身份 + * @param name 身份名 + * @return minsecurity.identity.Identity + * @author hongyu guo + * @date 2021/3/11 + **/ + public Identity getIdentityByName(String name){ + return MapDB.getInstance().getIdentityByName(name); + } + + /** + * 通过网络身份的名字和对应的密码删除一个网络身份, + * 如果commit为false,则需要手动执行commit()函数 + * @param name 身份名 + * @param commit true: 将本次修改提交到硬盘数据库中, false: 本次修改只修改内存中的内容 + * @return boolean + * @author hongyu guo + * @date 2021/3/11 + **/ + public boolean deleteIdentityByName(String name, boolean commit){ + Identity identity = MapDB.getInstance().deleteIdentity(name, commit); + return identity != null; + } + + /** + * 将一个网络身份保存到本地. + * 1. 首先检查网络身份在本地是否存在,如果存在,且 force = false,则不覆盖,保存失败 + * 2. 如果网络身份已存在,且 force = true,则覆盖原先的网络身份 + * 3. 如果网络身份不存在,则直接保存 + * @param newIdentity 将要保存的identity + * @param force 是否强制覆盖 + * @param commit true: 将本次修改提交到硬盘数据库中, false: 本次修改只修改内存中的内容 + * @return boolean + * @author hongyu guo + * @date 2021/3/11 + **/ + public boolean saveIdentity(Identity newIdentity, boolean force, boolean commit){ + // identifies.con + if(identifies.containsKey(newIdentity.getName()) && !force) { + return false; + } + MapDB.getInstance().addIdentity(newIdentity.getName(), newIdentity, commit); + return true; + } + + /** + * 指定一个身份名字和KeyParam,在本地创建一个网络身份 + * 1. 首先检查指定的身份名字在本地存储中是否已经存在,如果已经存在则创建失败; + * 2. 如果名字不冲突,则检查 password 是否为空字符串: + * a. 如果 password 为空字符串,则不对身份的秘钥进行加密保护; + * b. 如果 password 为非空字符串,则认为需要用其对秘钥进行加密保护,调用 Identify.Lock(password) + * @param name 身份的名字 + * @param keyParam 密钥类型 + * @param passwd 如果为null或为空字符串, 则表示没有加密 + * @param commit true: 将本次修改提交到硬盘数据库中, false: 本次修改只修改内存中的内容 + * @return minsecurity.identity.Identity + * @author hongyu guo + * @date 2021/3/11 + **/ + public Identity createIdentityByNameAndKeyParam(String name, KeyParam keyParam, String passwd, boolean commit){ + if(identifies.containsKey(name)){ + return null; + } + SM2KeyPair sm2KeyPair = SM2Base.generateSM2KeyPair(); + Identity newIdentity = new Identity(name, keyParam, sm2KeyPair.getSm2PrivateKey(), + sm2KeyPair.getSm2PublicKey(), passwd, null,false); + if(passwd != null && !passwd.equals("")){ + try { + if(!newIdentity.lock(passwd, Common.SM4ECB)) + return null; + } catch (IdentityException e) { + e.printStackTrace(); + } + } + return MapDB.getInstance().addIdentity(name, newIdentity, commit); + } + + /** + * 指定一个身份名字,在本地创建一个网络身份, 默认使用sm2加密和sm3签名 + * 1. 首先检查指定的身份名字在本地存储中是否已经存在,如果已经存在则创建失败; + * 2. 如果名字不冲突,则检查 password 是否为空字符串: + * a. 如果 password 为空字符串,则不对身份的秘钥进行加密保护; + * b. 如果 password 为非空字符串,则认为需要用其对秘钥进行加密保护,调用 Identify.Lock(password) + * @param name 身份的名字 + * @param passwd 如果为null或为空字符串, 则表示没有加密 + * @param commit true: 将本次修改提交到硬盘数据库中, false: 本次修改只修改内存中的内容 + * @return minsecurity.identity.Identity + * @author hongyu guo + * @date 2021/3/11 + **/ + public Identity createIdentityByName(String name, String passwd, boolean commit){ + return createIdentityByNameAndKeyParam(name, new KeyParam(Common.SM2, Common.SM3withSM2), passwd, commit); + } + + /** + * 设置当前系统的默认网络身份 + * @param identity 将被设置为默认identity + * @param commit true: 将本次修改提交到硬盘数据库中, false: 本次修改只修改内存中的内容 + * @return boolean + * @author hongyu guo + * @date 2021/3/11 + **/ + public boolean setDefaultIdentity(Identity identity, boolean commit) { + if(identity == null) + return false; + this.defaultIdentity = identity; + return MapDB.getInstance().setDefaultIdentity(identity.getName(), commit); + } + + /** + * 根据名字判断某个网络身份是否存在 + * @param name identity的名字 + * @return boolean + * @author hongyu guo + * @date 2021/3/11 + **/ + public boolean existIdentity(String name){ + return identifies.containsKey(name); + } + + public ConcurrentMap getIdentifies() { + return identifies; + } + + public Identity getDefaultIdentity() { + return defaultIdentity; + } + + public void setDefaultIdentity(Identity defaultIdentity) { + this.defaultIdentity = defaultIdentity; + } + + public int getPrivateKeyEncryptionAlgorithm() { + return privateKeyEncryptionAlgorithm; + } + + public void setPrivateKeyEncryptionAlgorithm(int privateKeyEncryptionAlgorithm) { + this.privateKeyEncryptionAlgorithm = privateKeyEncryptionAlgorithm; + } +} diff --git a/src/main/java/security/KeyChain.java b/src/main/java/security/KeyChain.java new file mode 100644 index 0000000..b20c04f --- /dev/null +++ b/src/main/java/security/KeyChain.java @@ -0,0 +1,89 @@ +package security; + +import minsecurity.identity.Identity; +import minsecurity.identity.IdentityException; +import org.checkerframework.checker.units.qual.K; + +/* + * @Author: hongyu guo + * @Description: 用于给网络包签名和验签 + * @Version: 1.0.0 + * @Date: 15:49 2021/03/11 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class KeyChain { + private IdentifyManager identifyManager; + private Identity currentIdentity; + + /** + * 指定当前使用默认的网络身份 + * @param + * @return + * @author hongyu guo + * @date 2021/3/11 + **/ + public KeyChain(){ + identifyManager = new IdentifyManager(); + currentIdentity = identifyManager.getDefaultIdentity(); + + // TODO: 考虑是否需要在没有默认身份的时候创建一个缺省的本地网络身份 + } + + /** + * 设置当前使用的网络身份 + * @param identity + * @param passwd 如果passwd不为null 且不为空字符串, 则使用该passwd对identity进行解密 + * @return void + * @author hongyu guo + * @date 2021/3/11 + **/ + public void setCurrentIdentity(Identity identity, String passwd) { + try { + if(passwd != null && !passwd.equals("")) + identity.unLock(passwd, identifyManager.getPrivateKeyEncryptionAlgorithm()); + } catch (IdentityException e) { + e.printStackTrace(); + } + } + + /** + * 为一个网络身份申请证书 + * @param identity + * @param force + * @return void + * @author hongyu guo + * @date 2021/3/11 + **/ + public void generateCertificationForIdentity(Identity identity, boolean force) { + // TODO: 这边应该发起网络通信,向 MIS 请求给这个网络身份签发一个证书,留待 MIR 完成后进行补充 + } + + /** + * 检查一个网络身份是否可用 + * + * 1. 首先检查 identity 是否为空; + * 2. 接着检查 identity 是否包含私钥; + * 3. 接着检查 identify 是否被锁定 + * @param identity + * @return void + * @author hongyu guo + * @date 2021/3/11 + **/ + public void checkIdentifyCanUseToSign(Identity identity) throws KeyChainException { + if(identity == null) + throw new KeyChainException("identity is null"); + if(!identity.hasPrivateKey()){ + throw new KeyChainException("Identify not have Private key, so can't use to sign!"); + } + if(identity.isLocked()){ + throw new KeyChainException("Identify is locked, so can't use to sign"); + } + } + + // TODO: packet类暂未完成 + // public void getIdentifierAndReadOnlyValueFromPacket(){ + // + // } + + +} diff --git a/src/main/java/security/KeyChainException.java b/src/main/java/security/KeyChainException.java new file mode 100644 index 0000000..cfbceb9 --- /dev/null +++ b/src/main/java/security/KeyChainException.java @@ -0,0 +1,14 @@ +package security; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 15:57 2021/03/11 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class KeyChainException extends Exception{ + public KeyChainException(String msg){ + super(msg); + } +} \ No newline at end of file diff --git a/src/main/java/security/SafeBag.java b/src/main/java/security/SafeBag.java new file mode 100644 index 0000000..6a3e4e9 --- /dev/null +++ b/src/main/java/security/SafeBag.java @@ -0,0 +1,12 @@ +package security; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 16:08 2021/03/11 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class SafeBag { + private byte[] value; +} diff --git a/src/test/java/minsecurity/identity/TestIdentity.java b/src/test/java/minsecurity/identity/TestIdentity.java index 45394bc..f1b4346 100644 --- a/src/test/java/minsecurity/identity/TestIdentity.java +++ b/src/test/java/minsecurity/identity/TestIdentity.java @@ -41,7 +41,7 @@ public class TestIdentity { 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); + Identity identity = new Identity("root",keyParam,sm2PrivateKey,sm2PublicKey, "123456", null, false); Certificate certificate = new Certificate(1, 1, sm2PublicKey, null, Common.SM3withSM2, Common.SM2, "root", "root", System.currentTimeMillis() - 1000, System.currentTimeMillis() + 5000, diff --git a/src/test/java/minsecurity/identity/TestPersist.java b/src/test/java/minsecurity/identity/TestPersist.java index a67c655..5c41cdc 100644 --- a/src/test/java/minsecurity/identity/TestPersist.java +++ b/src/test/java/minsecurity/identity/TestPersist.java @@ -46,7 +46,7 @@ public class TestPersist { 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); + Identity identity = new Identity("root",keyParam,sm2PrivateKey,sm2PublicKey, "123456", null, false); Certificate certificate = new Certificate(1, 1, sm2PublicKey, null, Common.SM3withSM2, Common.SM2, "root", "root", System.currentTimeMillis() - 1000, System.currentTimeMillis() + 5000, @@ -81,7 +81,7 @@ public class TestPersist { 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); + Identity identity = new Identity("root",keyParam,sm2PrivateKey,sm2PublicKey, "123456", null, false); Certificate certificate = new Certificate(1, 1, sm2PublicKey, null, Common.SM3withSM2, Common.SM2, "root", "root", System.currentTimeMillis() - 1000, System.currentTimeMillis() + 5000, @@ -155,7 +155,7 @@ public class TestPersist { SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); KeyParam keyParam = new KeyParam(Common.SM2, Common.SM3withSM2); - Identity identity = new Identity(name,keyParam,sm2PrivateKey,null,sm2PublicKey, "123456", null, false); + Identity identity = new Identity(name,keyParam,sm2PrivateKey,sm2PublicKey, "123456", null, false); Certificate certificate = new Certificate(1, 1, sm2PublicKey, null, Common.SM3withSM2, Common.SM2, "root", "root", System.currentTimeMillis() - 1000, System.currentTimeMillis() + 5000,