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 36175f4..8c95094 100644 --- a/src/main/java/minsecurity/certificate/cert/CertUtils.java +++ b/src/main/java/minsecurity/certificate/cert/CertUtils.java @@ -3,12 +3,18 @@ package minsecurity.certificate.cert; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import minsecurity.Common; -import minsecurity.crypto.PublicKeyInterface; -import minsecurity.crypto.PublicKeyUtils; -import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import minsecurity.crypto.*; import org.slf4j.LoggerFactory; +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; +import java.util.Base64; /* * @Author: hongyu guo @@ -21,6 +27,13 @@ public class CertUtils { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CertUtils.class); public static final int VERSION1 = 1; + /** + * Certificate -> InnerCertificate + * @param certificate + * @return InnerCertificate + * @author hongyu guo + * @date 2021/3/7 + **/ public static InnerCertificate parseCertToInnerCert(Certificate certificate){ TbsCertificate tbsCertificate = new TbsCertificate(); tbsCertificate.setVersion(certificate.getVersion()); @@ -43,12 +56,20 @@ public class CertUtils { return innerCertificate; } + + /** + * InnerCertificate -> Certificate + * @param i + * @return minsecurity.certificate.cert.Certificate + * @author hongyu guo + * @date 2021/3/7 + **/ public static Certificate parseInnerCertToCert(InnerCertificate i){ Certificate certificate = new Certificate(); 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()); @@ -64,6 +85,13 @@ public class CertUtils { return certificate; } + /** + * 检查证书是否在有效期内 + * @param innerCertificate + * @return boolean + * @author hongyu guo + * @date 2021/3/7 + **/ public static boolean checkDuration(InnerCertificate innerCertificate){ long curTime = System.currentTimeMillis(); // logger.debug("current time: {}", curTime); @@ -74,26 +102,32 @@ public class CertUtils { return true; } - // cur = 1615018693993 - // notbefore = 1615018693858 - // notafter = 1615018694058 - + /** + * 使用publicKey验证签名 + * @param cert + * @param publicKey + * @return boolean + * @author hongyu guo + * @date 2021/3/7 + **/ public static boolean checkSign(InnerCertificate cert, PublicKeyInterface publicKey) throws Exception { switch (cert.getTbsCertificate().getSignatureAlgorithm()){ case Common.SM3withSM2: - // TODO: 证书序列化方法 byte[] bytesOfCert = serialization(cert.getTbsCertificate()); - logger.debug("验签序列化bytes: {}", ByteUtils.toHexString(bytesOfCert)); - // byte[] digest = HashAlgo.sm3(bytesOfCert); - logger.debug("验签sign: {}", ByteUtils.toHexString(cert.getSignatureValue())); return publicKey.verify(bytesOfCert, cert.getSignatureValue()); default: throw new Exception("未定义的签名方法"); } } - // TODO: 证书序列化方法 + /** + * 将TbsCertificate类型实例转化为字节流 + * @param tbsCertificate + * @return byte[] + * @author hongyu guo + * @date 2021/3/7 + **/ public static byte[] serialization(TbsCertificate tbsCertificate){ ObjectMapper mapper = new ObjectMapper(); byte[] bytesOfCertJson; @@ -106,6 +140,13 @@ public class CertUtils { return new byte[0]; } + /** + * 将InnerCertificate类型实例转化为字节流 + * @param innerCertificate + * @return byte[] + * @author hongyu guo + * @date 2021/3/7 + **/ public static byte[] serialization(InnerCertificate innerCertificate){ ObjectMapper mapper = new ObjectMapper(); byte[] bytesOfCertJson; @@ -118,17 +159,23 @@ public class CertUtils { return new byte[0]; } - // TODO: 证书反序列化 + /** + * 根据typeOfCert可将字节流反序列化为TbsCertificate或InnerCertificate, + * 返回Object类型, 调用者调用时需要手动强制类型转化 + * @param bytesOfCert 字节流 + * @param typeOfCert Common.TbsCertificate或Common.InnerCertificate + * @return java.lang.Object + * @author hongyu guo + * @date 2021/3/7 + **/ public static Object deserialization(byte[] bytesOfCert, int typeOfCert){ ObjectMapper mapper = new ObjectMapper(); try { switch (typeOfCert) { case Common.TbsCertificate: - TbsCertificate tbsCertificate = mapper.readValue(bytesOfCert, TbsCertificate.class); - return tbsCertificate; + return mapper.readValue(bytesOfCert, TbsCertificate.class); case Common.InnerCertificate: - InnerCertificate innerCertificate = mapper.readValue(bytesOfCert, InnerCertificate.class); - return innerCertificate; + return mapper.readValue(bytesOfCert, InnerCertificate.class); default: throw new CertException("未知证书类型"); } @@ -139,4 +186,120 @@ public class CertUtils { } + /** + * 使用priv私钥给Certificate类型实例签名 + * @param certificate 未签名证书 + * @param priv 私钥 + * @return void + * @author hongyu guo + * @date 2021/3/7 + **/ + public static void signCert(Certificate certificate, PrivateKeyInterface priv) throws Exception { + byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(certificate).getTbsCertificate()); + // logger.debug("签名序列化bytes: {}", ByteUtils.toHexString(bytesOfCert)); + switch (certificate.getSignatureAlgorithm()){ + case Common.SM3withSM2: + certificate.setSignature(priv.sign(bytesOfCert)); + break; + default: + logger.debug("signAlgo: {}", certificate.getSignatureAlgorithm()); + throw new Exception("未定义的签名方法"); + } + } + + /** + * 使用ca的公钥对sub进行验签, 如果时根证书验签, 调用时ca与sub指向同一个实例 + * @param ca + * @param sub + * @return boolean + * @author hongyu guo + * @date 2021/3/7 + **/ + public static boolean verifyCert(Certificate ca, Certificate sub) throws Exception { + InnerCertificate innerCertificate = CertUtils.parseCertToInnerCert(sub); + switch (innerCertificate.getTbsCertificate().getVersion()){ + case CertUtils.VERSION1: + boolean isValid = CertUtils.checkDuration(innerCertificate); + // logger.debug("有效期内:{}", isValid); + if(!isValid) + return false; + if(sub.isCA()){ // 根证书, 自验证 + return checkSign(innerCertificate, sub.getPublicKey()); + } else { // 使用ca验证sub + return checkSign(innerCertificate, ca.getPublicKey()); + } + default: + return false; + } + } + + /** + * 证书序列化为String类型, 密码为null或为空时不对证书进行加密保存 + * @param certificate + * @param passwd + * @param symAlgoMode Common.SM4CBC / Common.SM4ECB + * @return java.lang.String + * @author hongyu guo + * @date 2021/3/7 + **/ + public static String toPem(Certificate certificate, byte[] passwd, int symAlgoMode) throws CertException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException { + if(certificate.getSignature() == null){ + throw new CertException("该证书未签名"); + } + byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(certificate)); + byte[] ret; + if(passwd != null && passwd.length > 0){ + // 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); + break; + } + case Common.SM4ECB:{ + ret = SM4.encrypt_ECB_Padding(sm4Key, bytesOfCert); + break; + } + default: + throw new CertException("未定义的对称加密算法"); + } + } else { + ret = bytesOfCert; + } + return Base64.getEncoder().encodeToString(ret); + } + + /** + * String类型证书转化为Certificate对象 + * @param pemString + * @param passwd + * @param symAlgoMode Common.SM4CBC / Common.SM4ECB + * @return minsecurity.certificate.cert.Certificate + * @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 { + if(pemString == null || pemString.equals("")){ + throw new CertException("pem串为空"); + } + byte[] bytesOfPem = Base64.getDecoder().decode(pemString); + byte[] bytesOfCert = new byte[0]; + if(passwd != null && passwd.length > 0){ + byte[] sm4Key = KeyUtils.get16bytePasswd(passwd); + switch (symAlgoMode){ + case Common.SM4CBC: + bytesOfCert = SM4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem); + break; + case Common.SM4ECB: + bytesOfCert = SM4.decrypt_ECB_Padding(sm4Key, bytesOfPem); + break; + } + } else { + bytesOfCert = bytesOfPem; + } + InnerCertificate innerCertificate = (InnerCertificate) deserialization(bytesOfCert, Common.InnerCertificate); + return CertUtils.parseInnerCertToCert(innerCertificate); + } } diff --git a/src/main/java/minsecurity/certificate/cert/Certificate.java b/src/main/java/minsecurity/certificate/cert/Certificate.java index 7984fe2..8c50bd4 100644 --- a/src/main/java/minsecurity/certificate/cert/Certificate.java +++ b/src/main/java/minsecurity/certificate/cert/Certificate.java @@ -1,28 +1,13 @@ 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.Base64; - -import static minsecurity.certificate.cert.CertUtils.*; - - /* * @Author: hongyu guo - * @Description: + * @Description: 证书bean类 * @Version: 1.0.0 * @Date: 17:05 2021/03/05 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 @@ -174,104 +159,23 @@ public class Certificate { this.publicKey = publicKey; } - - public void signCert(PrivateKeyInterface priv) throws Exception { - byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(this).getTbsCertificate()); - logger.debug("签名序列化bytes: {}", ByteUtils.toHexString(bytesOfCert)); - switch (this.signatureAlgorithm){ - case Common.SM3withSM2: - // byte[] digest = HashAlgo.sm3(bytesOfCert); - this.signature = priv.sign(bytesOfCert); - logger.debug("签名sign: {}", ByteUtils.toHexString(this.signature)); - // Sm2PublicKey sm2PublicKey = (Sm2PublicKey) this.publicKey; - // logger.debug("临时验签: {}", sm2PublicKey.verify(bytesOfCert, signature)); - break; - default: - logger.debug("signAlgo: {}",this.signatureAlgorithm); - throw new Exception("未定义的签名方法"); - } - } - - public static boolean verifyCert(Certificate ca, Certificate sub) throws Exception { - InnerCertificate innerCertificate = CertUtils.parseCertToInnerCert(sub); - switch (innerCertificate.getTbsCertificate().getVersion()){ - case CertUtils.VERSION1: - boolean isValid = CertUtils.checkDuration(innerCertificate); - logger.debug("有效期内:{}", isValid); - if(!isValid) - return false; - if(sub.isCA()){ - return checkSign(innerCertificate, sub.getPublicKey()); - } else { - return checkSign(innerCertificate, ca.getPublicKey()); - } - default: - return false; - } - } - - public String toPem(byte[] passwd, int symAlgoMode) throws CertException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException { - if(this.getSignature() == null){ - throw new CertException("该证书未签名"); - } - byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(this)); - byte[] ret = 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); - - switch (symAlgoMode){ - case Common.SM4CBC:{ - // TODO: PADDING??? IV????? - ret = Sm4.encrypt_CBC_Padding(sm4Key, new byte[16],bytesOfCert); - break; - } - case Common.SM4ECB:{ - ret = Sm4.encrypt_ECB_Padding(sm4Key, bytesOfCert); - break; - } - default: - throw new CertException("未定义的对称加密算法"); - } - } else { - ret = bytesOfCert; - } - return Base64.getEncoder().encodeToString(ret); - } - - 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]; - 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); - - switch (symAlgoMode){ - case Common.SM4CBC: - bytesOfCert = Sm4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem); - case Common.SM4ECB: - bytesOfCert = Sm4.decrypt_ECB_Padding(sm4Key, bytesOfPem); - } - } else { - bytesOfCert = bytesOfPem; - } - InnerCertificate innerCertificate = (InnerCertificate) deserialization(bytesOfCert, Common.InnerCertificate); - return CertUtils.parseInnerCertToCert(innerCertificate); + @Override + public String toString() { + return "Certificate{" + + "version=" + version + + ", serialNumber=" + serialNumber + + ", publicKey=" + publicKey + + ", signature=" + ByteUtils.toHexString(signature) + + ", signatureAlgorithm=" + signatureAlgorithm + + ", publicKeyAlgorithm=" + publicKeyAlgorithm + + ", issueTo='" + issueTo + '\'' + + ", issuer='" + issuer + '\'' + + ", notBefore=" + notBefore + + ", notAfter=" + notAfter + + ", keyUsage=" + keyUsage + + ", isCA=" + isCA + + ", timestamp=" + timestamp + + '}'; } } diff --git a/src/main/java/minsecurity/certificate/cert/InnerCertificate.java b/src/main/java/minsecurity/certificate/cert/InnerCertificate.java index 056cd20..d36caa4 100644 --- a/src/main/java/minsecurity/certificate/cert/InnerCertificate.java +++ b/src/main/java/minsecurity/certificate/cert/InnerCertificate.java @@ -7,7 +7,7 @@ import java.util.Arrays; /* * @Author: hongyu guo - * @Description: + * @Description: 将签名和签名类型单独拎出来, 签名时签TbsCertificate * @Version: 1.0.0 * @Date: 17:07 2021/03/05 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 diff --git a/src/main/java/minsecurity/certificate/cert/TbsCertificate.java b/src/main/java/minsecurity/certificate/cert/TbsCertificate.java index cdbdfda..f024096 100644 --- a/src/main/java/minsecurity/certificate/cert/TbsCertificate.java +++ b/src/main/java/minsecurity/certificate/cert/TbsCertificate.java @@ -7,7 +7,7 @@ import java.util.Arrays; /* * @Author: hongyu guo - * @Description: + * @Description: 内层结构, 不包含签名和签名类型 * @Version: 1.0.0 * @Date: 17:00 2021/03/05 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 diff --git a/src/main/java/minsecurity/crypto/HashAlgo.java b/src/main/java/minsecurity/crypto/HashAlgo.java index 3f52396..949cb87 100644 --- a/src/main/java/minsecurity/crypto/HashAlgo.java +++ b/src/main/java/minsecurity/crypto/HashAlgo.java @@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class HashAlgo { - // TODO: 单元测试 + // TODO: 单元测试 基本上只需要对sm3做单元测试 /////////////// ///// SM3 ///// /////////////// 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 f2d4221..0000000 --- a/src/main/java/minsecurity/crypto/PublicKeyUtils.java +++ /dev/null @@ -1,27 +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 { - 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 77% rename from src/main/java/minsecurity/crypto/sm2/Sm2Base.java rename to src/main/java/minsecurity/crypto/sm2/SM2Base.java index 9304228..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,17 @@ 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推荐曲线参数 + */ public static final SM2P256V1Curve CURVE = new SM2P256V1Curve(); public final static BigInteger SM2_ECC_P = CURVE.getQ(); public final static BigInteger SM2_ECC_A = CURVE.getA().toBigInteger(); @@ -56,6 +58,14 @@ public class Sm2Base { private static final String PEM_STRING_PUBLIC = "PUBLIC KEY"; private static final String PEM_STRING_ECPRIVATEKEY = "EC PRIVATE KEY"; + + /** + * 生成BC自定义的SM2公私钥 + * @param + * @return org.bouncycastle.crypto.AsymmetricCipherKeyPair + * @author hongyu guo + * @date 2021/3/7 + **/ public static AsymmetricCipherKeyPair generateKeyPairParameter(){ SecureRandom random = new SecureRandom(); ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(DOMAIN_PARAMS, @@ -66,12 +76,27 @@ public class Sm2Base { return keyPair; } + /** + * 生成java.security.KeyPair类型的SM2公私钥 + * @param + * @return java.security.KeyPair + * @author hongyu guo + * @date 2021/3/7 + **/ public static KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { SecureRandom random = new SecureRandom(); return generateKeyPair(DOMAIN_PARAMS, random); } + /** + * 生成java.security.KeyPair类型的SM2公私钥, 需自定义曲线参数 + * @param domainParameters + * @param random + * @return + * @author hongyu guo + * @date 2021/3/7 + **/ public static KeyPair generateKeyPair(ECDomainParameters domainParameters, SecureRandom random) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { @@ -82,7 +107,13 @@ public class Sm2Base { return kpg.generateKeyPair(); } - + /** + * BC公私钥转换为java.security.KeyPair公私钥 + * @param bcKeyPair + * @return + * @author hongyu guo + * @date 2021/3/7 + **/ public static KeyPair convertBcToJceKeyPair(AsymmetricCipherKeyPair bcKeyPair) throws Exception { byte[] pkcs8Encoded = PrivateKeyInfoFactory.createPrivateKeyInfo(bcKeyPair.getPrivate()).getEncoded(); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pkcs8Encoded); @@ -92,13 +123,27 @@ public class Sm2Base { return new KeyPair(keyFac.generatePublic(spkiKeySpec), keyFac.generatePrivate(pkcs8KeySpec)); } + /** + * java.security.KeyPair转换为BC类型的公私钥对 + * @param keyPair + * @return + * @author hongyu guo + * @date 2021/3/7 + **/ public static AsymmetricCipherKeyPair convertKeyPair2Bc(KeyPair keyPair) { ECPrivateKeyParameters priKey = convertPrivateKeyToParameters((BCECPrivateKey) keyPair.getPrivate()); ECPublicKeyParameters pubKey = convertPublicKeyToParameters((BCECPublicKey) keyPair.getPublic()); return new AsymmetricCipherKeyPair(priKey,pubKey); } - + /** + * BCECPrivateKey类型私钥转化为ECPrivateKeyParameters类型的私钥, + * 调用者若想将java.security.PrivateKey转化为ECPrivateKeyParameters, 调用时将其强制转换为BCECPrivateKey类型 + * @param ecPriKey + * @return ECPrivateKeyParameters + * @author hongyu guo + * @date 2021/3/7 + **/ public static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) { ECParameterSpec parameterSpec = ecPriKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), @@ -106,6 +151,14 @@ public class Sm2Base { return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters); } + /** + * BCECPublicKey类型私钥转化为ECPublicKeyParameters类型的私钥, + * 调用者若想将java.security.PublicKey转化为ECPublicKeyParameters, 调用时将其强制转换为BCECPublicKey类型 + * @param ecPubKey + * @return ECPrivateKeyParameters + * @author hongyu guo + * @date 2021/3/7 + **/ public static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) { ECParameterSpec parameterSpec = ecPubKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), 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 78% rename from src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java rename to src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java index 71d8ccd..51d4e1a 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java @@ -20,28 +20,41 @@ 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(byte[] d) { + public SM2PrivateKey(){} + + /* + * @param d + * @return + * @author hongyu guo + * @date 2021/3/7 + **/ + + /* + * @param d 大数 + * @return + * @author hongyu guo + * @date 2021/3/7 + **/ + 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(); } } @@ -56,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 82% rename from src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java rename to src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java index 9251ff2..cfdd7ce 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java @@ -15,21 +15,32 @@ import java.security.SecureRandom; /* * @Author: hongyu guo - * @Description: 国密sm2 非对称加密公钥 + * @Description: 国密sm2 非对称加密公钥, 实现PublicKeyInterface中的方法 * @Version: 1.0.0 * @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); } + /** + * 使用SM2推荐曲线参数 + * @param xBytes 曲线x参数 + * @param yBytes 曲线y参数 + * @return + * @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){ + setBytes(bytes); } @@ -55,6 +66,12 @@ public class Sm2PublicKey implements PublicKeyInterface { return true; } + /** + * @param content + * @return byte[] 密文 + * @author ghy + * @date 2021/3/7 + **/ @Override public byte[] encrypt(byte[] content) throws InvalidCipherTextException { SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C2C3); @@ -88,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) { @@ -108,7 +125,10 @@ public class Sm2PublicKey implements PublicKeyInterface { } return result; } + + + + private ECPublicKeyParameters publicKey; ////////////////////////////////////////////// private end ////////////////////////////////////////////// - ECPublicKeyParameters publicKey; } 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..b16efd0 --- /dev/null +++ b/src/main/java/minsecurity/identity/Identity.java @@ -0,0 +1,255 @@ +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.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; + + public Identity(String name, KeyParam keyParam, + PrivateKeyInterface prikey, byte[] prikeyRawByte, + PublicKeyInterface pubkey, String passwd, Certificate cert) { + Name = name; + KeyParam = keyParam; + Prikey = prikey; + PrikeyRawByte = prikeyRawByte; + Pubkey = pubkey; + Passwd = passwd; + Cert = cert; + } + + + 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; + } + + @Override + public String toString() { + return "Identity{" + + "Name='" + Name + '\'' + + ", KeyParam=" + KeyParam + + ", Prikey=" + Prikey + + ", PrikeyRawByte=" + (PrikeyRawByte == null ? "null":ByteUtils.toHexString(PrikeyRawByte)) + + ", Pubkey=" + Pubkey + + ", Passwd='" + Passwd + '\'' + + ", Cert=" + Cert + + '}'; + } +} 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/test/java/minsecurity/certificate/cert/TestCert.java b/src/test/java/minsecurity/certificate/cert/TestCert.java index 73bee78..70f8249 100644 --- a/src/test/java/minsecurity/certificate/cert/TestCert.java +++ b/src/test/java/minsecurity/certificate/cert/TestCert.java @@ -1,23 +1,16 @@ 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.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.junit.Assert; import org.junit.Test; import static org.junit.Assert.*; import org.slf4j.LoggerFactory; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import java.security.*; - /* * @Author: hongyu guo * @Description: @@ -29,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, @@ -45,24 +38,46 @@ public class TestCert { "issueTo","issuer",System.currentTimeMillis(), System.currentTimeMillis() + 200, Common.CertSign, true,System.currentTimeMillis()); - certificate.signCert(sm2PrivateKey); + CertUtils.signCert(certificate, sm2PrivateKey); // logger.debug(certificate.toString()); - boolean verify = Certificate.verifyCert(certificate, certificate); + // 根证书验签 + boolean verify = CertUtils.verifyCert(certificate, certificate); assertTrue(verify); + + + 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); + + Certificate sub = new Certificate(1,2,sm2PublicKey2, + null, Common.SM3withSM2,Common.SM2, + "sub","issuer",System.currentTimeMillis() - 1000, + System.currentTimeMillis() + 2000, Common.CertSign, + false, System.currentTimeMillis()); + CertUtils.signCert(sub, sm2PrivateKey); + // 下层证书验签 + boolean verify2 = CertUtils.verifyCert(certificate, sub); + assertTrue(verify2); } @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, @@ -70,17 +85,17 @@ public class TestCert { "issueTo","issuer",System.currentTimeMillis(), System.currentTimeMillis() + 111111, Common.CertSign, true,System.currentTimeMillis()); - certificate.signCert(sm2PrivateKey); + CertUtils.signCert(certificate, sm2PrivateKey); - String pem = certificate.toPem(null,0); - Certificate certFromPem = Certificate.fromPem(pem, null,0); + String pem = CertUtils.toPem(certificate,null,0); + Certificate certFromPem = CertUtils.fromPem(pem, null,0); logger.debug(certFromPem.toString()); - assertTrue(Certificate.verifyCert(certFromPem,certFromPem)); + assertTrue(CertUtils.verifyCert(certFromPem,certFromPem)); - String pem2 = certificate.toPem(new byte[]{1,2,3,4,5,6,7,8},Common.SM4ECB); - Certificate certFromPem2 = Certificate.fromPem(pem2, new byte[]{1,2,3,4,5,6,7,8},Common.SM4ECB); + String pem2 = CertUtils.toPem(certificate, new byte[]{1,2,3,4,5,6,7,8},Common.SM4ECB); + Certificate certFromPem2 = CertUtils.fromPem(pem2, new byte[]{1,2,3,4,5,6,7,8},Common.SM4ECB); logger.debug(certFromPem.toString()); - assertTrue(Certificate.verifyCert(certFromPem2,certFromPem2)); + assertTrue(CertUtils.verifyCert(certFromPem2,certFromPem2)); } } diff --git a/src/test/java/minsecurity/certificate/x509/TestX509.java b/src/test/java/minsecurity/certificate/x509/TestX509.java index 7d42326..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; @@ -32,6 +32,14 @@ import static minsecurity.certificate.X509.X509CertMaker.makeRootCA; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class TestX509 { + + // WARNING: X509不需要测试!!!!!!! + // WARNING: X509不需要测试!!!!!!! + // WARNING: X509不需要测试!!!!!!! + // WARNING: X509不需要测试!!!!!!! + // WARNING: X509不需要测试!!!!!!! + + static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } @@ -42,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"); @@ -69,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/sm2/TestSm2.java b/src/test/java/minsecurity/crypto/TestSM2.java similarity index 70% rename from src/test/java/minsecurity/crypto/sm2/TestSm2.java rename to src/test/java/minsecurity/crypto/TestSM2.java index 41cb631..274d45e 100644 --- a/src/test/java/minsecurity/crypto/sm2/TestSm2.java +++ b/src/test/java/minsecurity/crypto/TestSM2.java @@ -1,5 +1,8 @@ -package minsecurity.crypto.sm2; +package minsecurity.crypto; +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; @@ -11,6 +14,8 @@ import static org.junit.Assert.*; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; /* * @Author: hongyu guo @@ -19,11 +24,11 @@ import java.nio.ByteBuffer; * @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(); @@ -31,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); @@ -57,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(); @@ -66,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()); @@ -78,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(); @@ -86,12 +91,45 @@ public class TestSm2 { 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); + 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); assertTrue(flag); } + + // 按照艾宾浩斯记忆曲线 + // 第x天刷完题, 需要在第x+1,x+2,x+4,x+7,x+15时重新记忆 + public static void testMemory(int total, int numsInOneDay){ + int days = total / numsInOneDay + 1; + List[] res = new List[days + 15]; + for(int i = 0; i < days + 15; i++){ + res[i] = new ArrayList(); + } + + for(int i = 0; i < days; i++){ + + for(int j = 1; j <= numsInOneDay; j++){ + if(i * numsInOneDay + j <= total) { + res[i].add((i * numsInOneDay + j) * -1); + res[i + 1].add(i * numsInOneDay + j); + res[i + 2].add(i * numsInOneDay + j); + res[i + 4].add(i * numsInOneDay + j); + res[i + 7].add(i * numsInOneDay + j); + res[i + 15].add(i * numsInOneDay + j); + } + } + + } + for(int i = 0; i < days + 15; i++){ + System.out.println("第" + (i + 1) + "天: " + res[i]); + } + } + + public static void main(String[] args) { + testMemory(75,2); + } } 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..d8df6ae --- /dev/null +++ b/src/test/java/minsecurity/identity/TestIdentity.java @@ -0,0 +1,79 @@ +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); + 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())); + } + + +}