From 9d370a53532eab77ba44b2dcfea132a6887030c5 Mon Sep 17 00:00:00 2001 From: ghy Date: Sun, 7 Mar 2021 20:17:19 +0800 Subject: [PATCH 1/3] =?UTF-8?q?security=E9=83=A8=E5=88=86=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../certificate/cert/CertUtils.java | 210 ++++++++++++++++-- .../certificate/cert/Certificate.java | 118 ++-------- .../certificate/cert/InnerCertificate.java | 2 +- .../certificate/cert/TbsCertificate.java | 2 +- .../java/minsecurity/crypto/HashAlgo.java | 2 +- .../minsecurity/crypto/PublicKeyUtils.java | 8 + .../java/minsecurity/crypto/sm2/Sm2Base.java | 59 ++++- .../minsecurity/crypto/sm2/Sm2PrivateKey.java | 15 +- .../minsecurity/crypto/sm2/Sm2PublicKey.java | 26 ++- .../certificate/cert/TestCert.java | 47 ++-- .../certificate/x509/TestX509.java | 8 + .../minsecurity/crypto/{sm2 => }/TestSm2.java | 40 +++- 12 files changed, 396 insertions(+), 141 deletions(-) rename src/test/java/minsecurity/crypto/{sm2 => }/TestSm2.java (79%) diff --git a/src/main/java/minsecurity/certificate/cert/CertUtils.java b/src/main/java/minsecurity/certificate/cert/CertUtils.java index 36175f4..3859630 100644 --- a/src/main/java/minsecurity/certificate/cert/CertUtils.java +++ b/src/main/java/minsecurity/certificate/cert/CertUtils.java @@ -3,12 +3,19 @@ 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 minsecurity.crypto.*; 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.Base64; /* * @Author: hongyu guo @@ -21,6 +28,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,6 +57,14 @@ 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(); @@ -64,6 +86,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 +103,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 +141,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 +160,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 +187,134 @@ 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[] 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); + } + + /** + * 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[] 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); + 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..2d19775 100644 --- a/src/main/java/minsecurity/certificate/cert/Certificate.java +++ b/src/main/java/minsecurity/certificate/cert/Certificate.java @@ -15,6 +15,7 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.lang.reflect.Array; import java.security.*; +import java.util.Arrays; import java.util.Base64; import static minsecurity.certificate.cert.CertUtils.*; @@ -22,7 +23,7 @@ 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 +175,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/PublicKeyUtils.java b/src/main/java/minsecurity/crypto/PublicKeyUtils.java index f2d4221..bf5baa3 100644 --- a/src/main/java/minsecurity/crypto/PublicKeyUtils.java +++ b/src/main/java/minsecurity/crypto/PublicKeyUtils.java @@ -11,6 +11,14 @@ import minsecurity.crypto.sm2.Sm2PublicKey; * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class PublicKeyUtils { + /** + * 返回的数据类型为PublicKeyInterface接口, 必要时调用者需要手动将类型强制转化为需要的类型 + * @param bytesOfPublicKey 公钥的bytes数组 + * @param algorithm 公钥类型 + * @return minsecurity.crypto.PublicKeyInterface + * @author ghy + * @date 2021/3/7 + **/ public static PublicKeyInterface unMarshalPublicKey(byte[] bytesOfPublicKey, int algorithm) { if (bytesOfPublicKey == null || bytesOfPublicKey.length == 0) { return null; diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2Base.java b/src/main/java/minsecurity/crypto/sm2/Sm2Base.java index 9304228..bf86b64 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2Base.java +++ b/src/main/java/minsecurity/crypto/sm2/Sm2Base.java @@ -39,6 +39,10 @@ public class Sm2Base { } 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 +60,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 +78,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 +109,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 +125,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 +153,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/Sm2PrivateKey.java b/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java index 71d8ccd..9367ed5 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java +++ b/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java @@ -23,7 +23,20 @@ import java.security.SecureRandom; public class Sm2PrivateKey implements PrivateKeyInterface { 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); diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java b/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java index 9251ff2..5b9e76a 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java +++ b/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java @@ -15,7 +15,7 @@ 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;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 @@ -27,11 +27,22 @@ public class Sm2PublicKey implements PublicKeyInterface { 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[] bytes){ + setBytes(bytes); + } + @Override @@ -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); @@ -108,7 +125,10 @@ public class Sm2PublicKey implements PublicKeyInterface { } return result; } + + + + private ECPublicKeyParameters publicKey; ////////////////////////////////////////////// private end ////////////////////////////////////////////// - ECPublicKeyParameters publicKey; } diff --git a/src/test/java/minsecurity/certificate/cert/TestCert.java b/src/test/java/minsecurity/certificate/cert/TestCert.java index 73bee78..eb3f780 100644 --- a/src/test/java/minsecurity/certificate/cert/TestCert.java +++ b/src/test/java/minsecurity/certificate/cert/TestCert.java @@ -4,20 +4,13 @@ import minsecurity.Common; import minsecurity.crypto.sm2.Sm2Base; import minsecurity.crypto.sm2.Sm2PrivateKey; import minsecurity.crypto.sm2.Sm2PublicKey; -import minsecurity.crypto.sm2.TestSm2; 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: @@ -45,11 +38,33 @@ 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 @@ -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..920cdce 100644 --- a/src/test/java/minsecurity/certificate/x509/TestX509.java +++ b/src/test/java/minsecurity/certificate/x509/TestX509.java @@ -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()); } diff --git a/src/test/java/minsecurity/crypto/sm2/TestSm2.java b/src/test/java/minsecurity/crypto/TestSm2.java similarity index 79% rename from src/test/java/minsecurity/crypto/sm2/TestSm2.java rename to src/test/java/minsecurity/crypto/TestSm2.java index 41cb631..57e616c 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 @@ -86,6 +91,7 @@ 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); @@ -94,4 +100,36 @@ public class TestSm2 { 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); + } } From 755ddc212902c81fd02f170be78de034dcff5165 Mon Sep 17 00:00:00 2001 From: ghy Date: Tue, 9 Mar 2021 15:22:58 +0800 Subject: [PATCH 2/3] identity(without persist & without test) --- .../certificate/X509/X509CertMaker.java | 7 +- .../certificate/cert/CertUtils.java | 31 +-- .../certificate/cert/Certificate.java | 16 -- .../java/minsecurity/crypto/KeyUtils.java | 62 +++++ .../crypto/PrivateKeyInterface.java | 2 +- .../minsecurity/crypto/PublicKeyUtils.java | 35 --- .../minsecurity/crypto/{Sm4.java => SM4.java} | 2 +- .../crypto/sm2/{Sm2Base.java => SM2Base.java} | 6 +- .../{Sm2Exception.java => SM2Exception.java} | 4 +- ...{Sm2PrivateKey.java => SM2PrivateKey.java} | 20 +- .../{Sm2PublicKey.java => SM2PublicKey.java} | 14 +- .../minsecurity/crypto/sm2/SM4Exception.java | 14 ++ .../java/minsecurity/identity/Identity.java | 235 ++++++++++++++++++ .../identity/IdentityException.java | 14 ++ .../minsecurity/identity/IdentityUtil.java | 72 ++++++ .../minsecurity/identity/InnerIdentity.java | 96 +++++++ .../java/minsecurity/identity/KeyParam.java | 21 ++ .../certificate/cert/TestCert.java | 24 +- .../certificate/x509/TestX509.java | 6 +- .../crypto/{TestSm2.java => TestSM2.java} | 28 +-- .../crypto/{TestSm4.java => TestSM4.java} | 23 +- 21 files changed, 588 insertions(+), 144 deletions(-) create mode 100644 src/main/java/minsecurity/crypto/KeyUtils.java delete mode 100644 src/main/java/minsecurity/crypto/PublicKeyUtils.java rename src/main/java/minsecurity/crypto/{Sm4.java => SM4.java} (99%) rename src/main/java/minsecurity/crypto/sm2/{Sm2Base.java => SM2Base.java} (98%) rename src/main/java/minsecurity/crypto/sm2/{Sm2Exception.java => SM2Exception.java} (77%) rename src/main/java/minsecurity/crypto/sm2/{Sm2PrivateKey.java => SM2PrivateKey.java} (84%) rename src/main/java/minsecurity/crypto/sm2/{Sm2PublicKey.java => SM2PublicKey.java} (91%) create mode 100644 src/main/java/minsecurity/crypto/sm2/SM4Exception.java create mode 100644 src/main/java/minsecurity/identity/Identity.java create mode 100644 src/main/java/minsecurity/identity/IdentityException.java create mode 100644 src/main/java/minsecurity/identity/IdentityUtil.java create mode 100644 src/main/java/minsecurity/identity/InnerIdentity.java create mode 100644 src/main/java/minsecurity/identity/KeyParam.java rename src/test/java/minsecurity/crypto/{TestSm2.java => TestSM2.java} (88%) rename src/test/java/minsecurity/crypto/{TestSm4.java => TestSM4.java} (82%) diff --git a/src/main/java/minsecurity/certificate/X509/X509CertMaker.java b/src/main/java/minsecurity/certificate/X509/X509CertMaker.java index dabc5ab..0333fce 100644 --- a/src/main/java/minsecurity/certificate/X509/X509CertMaker.java +++ b/src/main/java/minsecurity/certificate/X509/X509CertMaker.java @@ -1,7 +1,6 @@ package minsecurity.certificate.X509; -import minsecurity.Common; -import minsecurity.crypto.sm2.Sm2Base; +import minsecurity.crypto.sm2.SM2Base; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; @@ -34,7 +33,7 @@ public class X509CertMaker { String ou, String cn, long expireTimeInMs, String signAlgo) throws Exception { - KeyPair rootKP = Sm2Base.generateKeyPair(); + KeyPair rootKP = SM2Base.generateKeyPair(); return makeRootCA(rootKP, c, o, ou, cn, expireTimeInMs, signAlgo); } @@ -116,7 +115,7 @@ public class X509CertMaker { public static void main(String[] args) { try { - KeyPair rootKP = Sm2Base.generateKeyPair(); + KeyPair rootKP = SM2Base.generateKeyPair(); X509Certificate rootCA = makeRootCA(rootKP,"CN","MIN", "MIN-GROUP","MIN ROOT CA", 365L * 24 * 60 * 60 * 1000, "SM3withSM2"); diff --git a/src/main/java/minsecurity/certificate/cert/CertUtils.java b/src/main/java/minsecurity/certificate/cert/CertUtils.java index 3859630..8c95094 100644 --- a/src/main/java/minsecurity/certificate/cert/CertUtils.java +++ b/src/main/java/minsecurity/certificate/cert/CertUtils.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import minsecurity.Common; import minsecurity.crypto.*; -import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.slf4j.LoggerFactory; import javax.crypto.BadPaddingException; @@ -70,7 +69,7 @@ public class CertUtils { certificate.setVersion(i.getTbsCertificate().getVersion()); certificate.setSerialNumber(i.getTbsCertificate().getSerialNumber()); - PublicKeyInterface publicKey = PublicKeyUtils.unMarshalPublicKey(i.getTbsCertificate().getPublicKey(),i.getSignatureAlgorithm()); + PublicKeyInterface publicKey = KeyUtils.unMarshalPublicKey(i.getTbsCertificate().getPublicKey(),i.getSignatureAlgorithm()); certificate.setPublicKey(publicKey); certificate.setSignature(i.getSignatureValue()); certificate.setSignatureAlgorithm(i.getTbsCertificate().getSignatureAlgorithm()); @@ -250,23 +249,17 @@ public class CertUtils { byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(certificate)); byte[] ret; if(passwd != null && passwd.length > 0){ - byte[] hashPasswd = HashAlgo.sm3(passwd); - if( hashPasswd.length == 32){ - for(int i = 0; i < 16; i++){ - hashPasswd[i] += hashPasswd[i + 16]; - } - } - byte[] sm4Key = new byte[16]; - System.arraycopy(hashPasswd,0,sm4Key,0,16); + // byte[] sm4Key; + byte[] sm4Key = KeyUtils.get16bytePasswd(passwd); switch (symAlgoMode){ case Common.SM4CBC:{ // TODO: PADDING??? IV????? - ret = Sm4.encrypt_CBC_Padding(sm4Key, new byte[16],bytesOfCert); + ret = SM4.encrypt_CBC_Padding(sm4Key, new byte[16],bytesOfCert); break; } case Common.SM4ECB:{ - ret = Sm4.encrypt_ECB_Padding(sm4Key, bytesOfCert); + ret = SM4.encrypt_ECB_Padding(sm4Key, bytesOfCert); break; } default: @@ -294,21 +287,13 @@ public class CertUtils { byte[] bytesOfPem = Base64.getDecoder().decode(pemString); byte[] bytesOfCert = new byte[0]; if(passwd != null && passwd.length > 0){ - byte[] hashPasswd = HashAlgo.sm3(passwd); - if( hashPasswd.length == 32){ - for(int i = 0; i < 16; i++){ - hashPasswd[i] += hashPasswd[i + 16]; - } - } - byte[] sm4Key = new byte[16]; - System.arraycopy(hashPasswd,0,sm4Key,0,16); - + byte[] sm4Key = KeyUtils.get16bytePasswd(passwd); switch (symAlgoMode){ case Common.SM4CBC: - bytesOfCert = Sm4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem); + bytesOfCert = SM4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem); break; case Common.SM4ECB: - bytesOfCert = Sm4.decrypt_ECB_Padding(sm4Key, bytesOfPem); + bytesOfCert = SM4.decrypt_ECB_Padding(sm4Key, bytesOfPem); break; } } else { diff --git a/src/main/java/minsecurity/certificate/cert/Certificate.java b/src/main/java/minsecurity/certificate/cert/Certificate.java index 2d19775..8c50bd4 100644 --- a/src/main/java/minsecurity/certificate/cert/Certificate.java +++ b/src/main/java/minsecurity/certificate/cert/Certificate.java @@ -1,26 +1,10 @@ package minsecurity.certificate.cert; -import minsecurity.Common; -import minsecurity.crypto.HashAlgo; -import minsecurity.crypto.PrivateKeyInterface; import minsecurity.crypto.PublicKeyInterface; -import minsecurity.crypto.Sm4; -import minsecurity.crypto.sm2.Sm2PublicKey; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.slf4j.LoggerFactory; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import java.lang.reflect.Array; -import java.security.*; -import java.util.Arrays; -import java.util.Base64; - -import static minsecurity.certificate.cert.CertUtils.*; - - /* * @Author: hongyu guo * @Description: 证书bean类 diff --git a/src/main/java/minsecurity/crypto/KeyUtils.java b/src/main/java/minsecurity/crypto/KeyUtils.java new file mode 100644 index 0000000..71ae11a --- /dev/null +++ b/src/main/java/minsecurity/crypto/KeyUtils.java @@ -0,0 +1,62 @@ +package minsecurity.crypto; + +import minsecurity.Common; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 16:02 2021/03/06 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class KeyUtils { + /** + * 返回的数据类型为PublicKeyInterface接口, 必要时调用者需要手动将类型强制转化为需要的类型 + * @param bytesOfPublicKey 公钥的bytes数组 + * @param algorithm 公钥类型 + * @return minsecurity.crypto.PublicKeyInterface + * @author ghy + * @date 2021/3/7 + **/ + public static PublicKeyInterface unMarshalPublicKey(byte[] bytesOfPublicKey, int algorithm) { + if (bytesOfPublicKey == null || bytesOfPublicKey.length == 0) { + return null; + } + switch (algorithm) { + case Common.SM2: + SM2PublicKey sm2PublicKey = new SM2PublicKey(); + sm2PublicKey.setBytes(bytesOfPublicKey); + return sm2PublicKey; + default: + return null; + } + } + + public static PrivateKeyInterface unMarshalPrivateKey(byte[] bytesOfPrivateKey, int algorithm){ + if(bytesOfPrivateKey == null || bytesOfPrivateKey.length == 0){ + return null; + } + switch (algorithm) { + case Common.SM2: + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(); + sm2PrivateKey.setBytes(bytesOfPrivateKey); + return sm2PrivateKey; + default: + return null; + } + } + + public static byte[] get16bytePasswd(byte[] passwd) { + byte[] hashPasswd = HashAlgo.sm3(passwd); + if( hashPasswd.length == 32){ + for(int i = 0; i < 16; i++){ + hashPasswd[i] += hashPasswd[i + 16]; + } + } + byte[] sm4Key = new byte[16]; + System.arraycopy(hashPasswd,0,sm4Key,0,16); + return sm4Key; + } +} diff --git a/src/main/java/minsecurity/crypto/PrivateKeyInterface.java b/src/main/java/minsecurity/crypto/PrivateKeyInterface.java index 7cd3cbd..ecd7b31 100644 --- a/src/main/java/minsecurity/crypto/PrivateKeyInterface.java +++ b/src/main/java/minsecurity/crypto/PrivateKeyInterface.java @@ -13,6 +13,6 @@ import org.bouncycastle.crypto.InvalidCipherTextException; public interface PrivateKeyInterface { public byte[] getBytes(); public boolean setBytes(byte[] bytes); - public byte[] decrypt(byte[] content) throws InvalidCipherTextException; + public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException; public byte[] sign(byte[] content) throws CryptoException; } diff --git a/src/main/java/minsecurity/crypto/PublicKeyUtils.java b/src/main/java/minsecurity/crypto/PublicKeyUtils.java deleted file mode 100644 index bf5baa3..0000000 --- a/src/main/java/minsecurity/crypto/PublicKeyUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -package minsecurity.crypto; - -import minsecurity.Common; -import minsecurity.crypto.sm2.Sm2PublicKey; - -/* - * @Author: hongyu guo - * @Description: - * @Version: 1.0.0 - * @Date: 16:02 2021/03/06 - * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 - */ -public class PublicKeyUtils { - /** - * 返回的数据类型为PublicKeyInterface接口, 必要时调用者需要手动将类型强制转化为需要的类型 - * @param bytesOfPublicKey 公钥的bytes数组 - * @param algorithm 公钥类型 - * @return minsecurity.crypto.PublicKeyInterface - * @author ghy - * @date 2021/3/7 - **/ - public static PublicKeyInterface unMarshalPublicKey(byte[] bytesOfPublicKey, int algorithm) { - if (bytesOfPublicKey == null || bytesOfPublicKey.length == 0) { - return null; - } - switch (algorithm) { - case Common.SM2: - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(); - sm2PublicKey.setBytes(bytesOfPublicKey); - return sm2PublicKey; - default: - return null; - } - } -} diff --git a/src/main/java/minsecurity/crypto/Sm4.java b/src/main/java/minsecurity/crypto/SM4.java similarity index 99% rename from src/main/java/minsecurity/crypto/Sm4.java rename to src/main/java/minsecurity/crypto/SM4.java index d0cc585..6830489 100644 --- a/src/main/java/minsecurity/crypto/Sm4.java +++ b/src/main/java/minsecurity/crypto/SM4.java @@ -14,7 +14,7 @@ import java.security.*; * @Date: 16:26 2021/03/04 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm4 { +public class SM4 { static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2Base.java b/src/main/java/minsecurity/crypto/sm2/SM2Base.java similarity index 98% rename from src/main/java/minsecurity/crypto/sm2/Sm2Base.java rename to src/main/java/minsecurity/crypto/sm2/SM2Base.java index bf86b64..b52a2cb 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2Base.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2Base.java @@ -1,6 +1,5 @@ package minsecurity.crypto.sm2; -import minsecurity.Common; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.ECDomainParameters; @@ -17,7 +16,6 @@ import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve; import org.slf4j.LoggerFactory; -import javax.crypto.KeyGenerator; import java.math.BigInteger; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; @@ -32,13 +30,13 @@ import static minsecurity.Common.ALGO_NAME_EC; * @Date: 18:48 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2Base { +public class SM2Base { static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Sm2Base.class); + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SM2Base.class); /* * 以下为SM2推荐曲线参数 diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2Exception.java b/src/main/java/minsecurity/crypto/sm2/SM2Exception.java similarity index 77% rename from src/main/java/minsecurity/crypto/sm2/Sm2Exception.java rename to src/main/java/minsecurity/crypto/sm2/SM2Exception.java index 0f31a91..79916b2 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2Exception.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2Exception.java @@ -7,8 +7,8 @@ package minsecurity.crypto.sm2; * @Date: 19:00 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2Exception extends java.lang.Exception { - public Sm2Exception(String msg){ +public class SM2Exception extends java.lang.Exception { + public SM2Exception(String msg){ super(msg); } } diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java b/src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java similarity index 84% rename from src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java rename to src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java index 9367ed5..51d4e1a 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PrivateKey.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2PrivateKey.java @@ -20,9 +20,9 @@ import java.security.SecureRandom; * @Date: 19:40 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2PrivateKey implements PrivateKeyInterface { +public class SM2PrivateKey implements PrivateKeyInterface { - public Sm2PrivateKey(){} + public SM2PrivateKey(){} /* * @param d @@ -37,24 +37,24 @@ public class Sm2PrivateKey implements PrivateKeyInterface { * @author hongyu guo * @date 2021/3/7 **/ - public Sm2PrivateKey(byte[] d) { + public SM2PrivateKey(byte[] d) { if(d.length == 32 || d.length == 33) - privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS); + privateKey = new ECPrivateKeyParameters(new BigInteger(d), SM2Base.DOMAIN_PARAMS); else { try { - throw new Sm2Exception("SM2私钥中,参数d长度应为32/33"); - } catch (Sm2Exception e) { + throw new SM2Exception("SM2私钥中,参数d长度应为32/33"); + } catch (SM2Exception e) { e.printStackTrace(); } } } - public Sm2PrivateKey(byte[] d, ECDomainParameters parameters){ + public SM2PrivateKey(byte[] d, ECDomainParameters parameters){ if(d.length == 32 || d.length == 33) privateKey = new ECPrivateKeyParameters(new BigInteger(d), parameters); else { try { - throw new Sm2Exception("SM2私钥中,参数d长度应为32/33"); - } catch (Sm2Exception e) { + throw new SM2Exception("SM2私钥中,参数d长度应为32/33"); + } catch (SM2Exception e) { e.printStackTrace(); } } @@ -69,7 +69,7 @@ public class Sm2PrivateKey implements PrivateKeyInterface { public boolean setBytes(byte[] d) { if(d.length != 32 && d.length != 33) return false; - privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS); + privateKey = new ECPrivateKeyParameters(new BigInteger(d), SM2Base.DOMAIN_PARAMS); return true; } diff --git a/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java b/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java similarity index 91% rename from src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java rename to src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java index 5b9e76a..cfdd7ce 100644 --- a/src/main/java/minsecurity/crypto/sm2/Sm2PublicKey.java +++ b/src/main/java/minsecurity/crypto/sm2/SM2PublicKey.java @@ -20,11 +20,11 @@ import java.security.SecureRandom; * @Date: 17:32 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class Sm2PublicKey implements PublicKeyInterface { +public class SM2PublicKey implements PublicKeyInterface { - public Sm2PublicKey(){} + public SM2PublicKey(){} - public Sm2PublicKey(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){ + public SM2PublicKey(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){ publicKey = createPublicKey(xBytes,yBytes,curve,domainParameters); } /** @@ -35,11 +35,11 @@ public class Sm2PublicKey implements PublicKeyInterface { * @author ghy * @date 2021/3/7 **/ - public Sm2PublicKey(byte[] xBytes, byte[] yBytes){ - this(xBytes,yBytes, Sm2Base.CURVE, Sm2Base.DOMAIN_PARAMS); + public SM2PublicKey(byte[] xBytes, byte[] yBytes){ + this(xBytes,yBytes, SM2Base.CURVE, SM2Base.DOMAIN_PARAMS); } - public Sm2PublicKey(byte[] bytes){ + public SM2PublicKey(byte[] bytes){ setBytes(bytes); } @@ -105,7 +105,7 @@ public class Sm2PublicKey implements PublicKeyInterface { } private static ECPublicKeyParameters createPublicKey(byte[] xBytes, byte[] yBytes){ - return createPublicKey(xBytes,yBytes,Sm2Base.CURVE,Sm2Base.DOMAIN_PARAMS); + return createPublicKey(xBytes,yBytes, SM2Base.CURVE, SM2Base.DOMAIN_PARAMS); } private static int getCurveLength(ECDomainParameters domainParams) { diff --git a/src/main/java/minsecurity/crypto/sm2/SM4Exception.java b/src/main/java/minsecurity/crypto/sm2/SM4Exception.java new file mode 100644 index 0000000..c187c8c --- /dev/null +++ b/src/main/java/minsecurity/crypto/sm2/SM4Exception.java @@ -0,0 +1,14 @@ +package minsecurity.crypto.sm2; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 15:19 2021/03/09 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class SM4Exception extends Exception{ + SM4Exception(String msg){ + super(msg); + } +} diff --git a/src/main/java/minsecurity/identity/Identity.java b/src/main/java/minsecurity/identity/Identity.java new file mode 100644 index 0000000..572bf39 --- /dev/null +++ b/src/main/java/minsecurity/identity/Identity.java @@ -0,0 +1,235 @@ +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 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 + * @Description: + * @Version: 1.0.0 + * @Date: 20:25 2021/03/07 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class Identity { + + 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); + 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, IOException, 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 = mapper.readValue(plain, InnerIdentity.class); + 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; + } + + + +} 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..e9ba140 --- /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.setPrikey(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..e804b57 --- /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=" + ByteUtils.toHexString(Prikey) + + ", Pubkey=" + 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 eb3f780..70f8249 100644 --- a/src/test/java/minsecurity/certificate/cert/TestCert.java +++ b/src/test/java/minsecurity/certificate/cert/TestCert.java @@ -1,9 +1,9 @@ package minsecurity.certificate.cert; import minsecurity.Common; -import minsecurity.crypto.sm2.Sm2Base; -import minsecurity.crypto.sm2.Sm2PrivateKey; -import minsecurity.crypto.sm2.Sm2PublicKey; +import minsecurity.crypto.sm2.SM2Base; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; @@ -22,15 +22,15 @@ public class TestCert { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestCert.class); @Test public void testCertSignAndVerify() throws Exception { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); // d = Arrays.copyOf(d,32); byte[] x = pubKey.getQ().getAffineXCoord().getEncoded(); byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); Certificate certificate = new Certificate(1,1,sm2PublicKey, @@ -46,15 +46,15 @@ public class TestCert { assertTrue(verify); - AsymmetricCipherKeyPair keyPair2 = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair2 = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey2 = (ECPrivateKeyParameters) keyPair2.getPrivate(); ECPublicKeyParameters pubKey2 = (ECPublicKeyParameters) keyPair2.getPublic(); byte[] d2 = priKey2.getD().toByteArray(); // d = Arrays.copyOf(d,32); byte[] x2 = pubKey2.getQ().getAffineXCoord().getEncoded(); byte[] y2 = pubKey2.getQ().getAffineYCoord().getEncoded(); - Sm2PrivateKey sm2PrivateKey2 = new Sm2PrivateKey(d2); - Sm2PublicKey sm2PublicKey2 = new Sm2PublicKey(x2, y2); + SM2PrivateKey sm2PrivateKey2 = new SM2PrivateKey(d2); + SM2PublicKey sm2PublicKey2 = new SM2PublicKey(x2, y2); Certificate sub = new Certificate(1,2,sm2PublicKey2, null, Common.SM3withSM2,Common.SM2, @@ -69,15 +69,15 @@ public class TestCert { @Test public void testCert2Pem() throws Exception { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); // d = Arrays.copyOf(d,32); byte[] x = pubKey.getQ().getAffineXCoord().getEncoded(); byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); Certificate certificate = new Certificate(1,1,sm2PublicKey, diff --git a/src/test/java/minsecurity/certificate/x509/TestX509.java b/src/test/java/minsecurity/certificate/x509/TestX509.java index 920cdce..79514d9 100644 --- a/src/test/java/minsecurity/certificate/x509/TestX509.java +++ b/src/test/java/minsecurity/certificate/x509/TestX509.java @@ -3,7 +3,7 @@ package minsecurity.certificate.x509; import minsecurity.Common; import minsecurity.certificate.X509.X509CertMaker; import minsecurity.certificate.X509.X509CertUtil; -import minsecurity.crypto.sm2.Sm2Base; +import minsecurity.crypto.sm2.SM2Base; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.bouncycastle.util.io.pem.PemObject; @@ -50,7 +50,7 @@ public class TestX509 { public void testRebuildKeyPair(){ try { - KeyPair rootKP = Sm2Base.generateKeyPair(); + KeyPair rootKP = SM2Base.generateKeyPair(); X509Certificate rootCA = makeRootCA(rootKP,"CN","MIN", "MIN-GROUP","MIN ROOT CA", 365L * 24 * 60 * 60 * 1000, "SM3withSM2"); @@ -77,7 +77,7 @@ public class TestX509 { logger.debug("origin: {}", ByteUtils.toHexString(rootKP.getPublic().getEncoded())); logger.debug("rebuild:{}", ByteUtils.toHexString(rootKeyPair.getPublic().getEncoded())); - KeyPair subKeyPair = Sm2Base.generateKeyPair(); + KeyPair subKeyPair = SM2Base.generateKeyPair(); X509Certificate subCert = X509CertMaker.makeSubCACert(rootKeyPair, cert, diff --git a/src/test/java/minsecurity/crypto/TestSm2.java b/src/test/java/minsecurity/crypto/TestSM2.java similarity index 88% rename from src/test/java/minsecurity/crypto/TestSm2.java rename to src/test/java/minsecurity/crypto/TestSM2.java index 57e616c..274d45e 100644 --- a/src/test/java/minsecurity/crypto/TestSm2.java +++ b/src/test/java/minsecurity/crypto/TestSM2.java @@ -1,8 +1,8 @@ package minsecurity.crypto; -import minsecurity.crypto.sm2.Sm2Base; -import minsecurity.crypto.sm2.Sm2PrivateKey; -import minsecurity.crypto.sm2.Sm2PublicKey; +import minsecurity.crypto.sm2.SM2Base; +import minsecurity.crypto.sm2.SM2PrivateKey; +import minsecurity.crypto.sm2.SM2PublicKey; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.CryptoException; import org.bouncycastle.crypto.InvalidCipherTextException; @@ -24,11 +24,11 @@ import java.util.List; * @Date: 20:15 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class TestSm2 { - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestSm2.class); +public class TestSM2 { + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestSM2.class); @Test public void testSetGet() throws InvalidCipherTextException { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); @@ -36,8 +36,8 @@ public class TestSm2 { byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); logger.debug("d.len = {}, x.len = {}, y.len = {}",d.length, x.length, y.length); // BigInteger bigInteger = priKey.getD(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(); + SM2PublicKey sm2PublicKey = new SM2PublicKey(); sm2PrivateKey.setBytes(d); @@ -62,7 +62,7 @@ public class TestSm2 { @Test public void testEncAndDec() throws InvalidCipherTextException { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); @@ -71,8 +71,8 @@ public class TestSm2 { byte[] y = pubKey.getQ().getAffineYCoord().getEncoded(); logger.debug("d.len = {}, x.len = {}, y.len = {}",d.length, x.length, y.length); // BigInteger bigInteger = priKey.getD(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); String content = "hello world"; byte[] encBytes = sm2PublicKey.encrypt(content.getBytes()); @@ -83,7 +83,7 @@ public class TestSm2 { @Test public void testSignAndVerify() throws CryptoException { - AsymmetricCipherKeyPair keyPair = Sm2Base.generateKeyPairParameter(); + AsymmetricCipherKeyPair keyPair = SM2Base.generateKeyPairParameter(); ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate(); ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic(); byte[] d = priKey.getD().toByteArray(); @@ -93,8 +93,8 @@ public class TestSm2 { logger.debug("d.len = {}, x.len = {}, y.len = {}",d.length, x.length, y.length); // BigInteger bigInteger = priKey.getD(); - Sm2PrivateKey sm2PrivateKey = new Sm2PrivateKey(d); - Sm2PublicKey sm2PublicKey = new Sm2PublicKey(x,y); + SM2PrivateKey sm2PrivateKey = new SM2PrivateKey(d); + SM2PublicKey sm2PublicKey = new SM2PublicKey(x,y); String content = "7b227462734365727469666963617465223a7b2276657273696f6e223a312c2273657269616c4e756d626572223a312c227075626c69634b6579223a22424a304d7047714e5958706b695879575a4d6e5838776d6b694a51326f576d37336257615932525473706b695058342f37705443666332764e7272596e766c6a644d3448647850537531753272616363506c74485245593d222c227369676e6174757265416c676f726974686d223a302c227075626c69634b6579416c676f726974686d223a302c226973737565546f223a226973737565546f222c22697373756572223a22697373756572222c226e6f744265666f7265223a313631353032303130393339352c226e6f744166746572223a313631353032303130393539352c226b65795573616765223a322c2274696d657374616d70223a313631353032303130393339352c226361223a747275657d2c227369676e6174757265416c676f726974686d223a302c227369676e617475726556616c7565223a6e756c6c7d"; byte[] digest = sm2PrivateKey.sign(ByteUtils.fromHexString(content)); boolean flag = sm2PublicKey.verify(ByteUtils.fromHexString(content), digest); diff --git a/src/test/java/minsecurity/crypto/TestSm4.java b/src/test/java/minsecurity/crypto/TestSM4.java similarity index 82% rename from src/test/java/minsecurity/crypto/TestSm4.java rename to src/test/java/minsecurity/crypto/TestSM4.java index 34cd1a8..0bb09ac 100644 --- a/src/test/java/minsecurity/crypto/TestSm4.java +++ b/src/test/java/minsecurity/crypto/TestSM4.java @@ -2,7 +2,6 @@ package minsecurity.crypto; import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import java.util.Arrays; @@ -14,7 +13,7 @@ import java.util.Arrays; * @Date: 16:28 2021/03/04 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ -public class TestSm4 { +public class TestSM4 { public static final byte[] SRC_DATA = new byte[]{1, 2, 3, 4, 5, 6, 7, 8}; public static final byte[] SRC_DATA_16B = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; public static final byte[] SRC_DATA_24B = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; @@ -25,42 +24,42 @@ public class TestSm4 { @Test public void testEncryptAndDecrypt() { try { - byte[] key = Sm4.generateKey(); - byte[] iv = Sm4.generateKey(); + byte[] key = SM4.generateKey(); + byte[] iv = SM4.generateKey(); byte[] cipherText = null; byte[] decryptedData = null; System.out.println("key: " + ByteUtils.toHexString(key)); System.out.println("iv: " + ByteUtils.toHexString(iv)); - cipherText = Sm4.encrypt_ECB_NoPadding(key, SRC_DATA_16B); + cipherText = SM4.encrypt_ECB_NoPadding(key, SRC_DATA_16B); System.out.println("SM4 ECB NoPadding encrypt result:\n" + Arrays.toString(cipherText)); System.out.println(ByteUtils.toHexString(cipherText)); - decryptedData = Sm4.decrypt_ECB_NoPadding(key, cipherText); + decryptedData = SM4.decrypt_ECB_NoPadding(key, cipherText); System.out.println("SM4 ECB NoPadding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA_16B)) { Assert.fail(); } - cipherText = Sm4.encrypt_ECB_Padding(key, SRC_DATA_16B); + cipherText = SM4.encrypt_ECB_Padding(key, SRC_DATA_16B); System.out.println("SM4 ECB Padding encrypt result:\n" + Arrays.toString(cipherText)); System.out.println(ByteUtils.toHexString(cipherText)); - decryptedData = Sm4.decrypt_ECB_Padding(key, cipherText); + decryptedData = SM4.decrypt_ECB_Padding(key, cipherText); System.out.println("SM4 ECB Padding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA_16B)) { Assert.fail(); } - cipherText = Sm4.encrypt_CBC_Padding(key, iv, SRC_DATA); + cipherText = SM4.encrypt_CBC_Padding(key, iv, SRC_DATA); System.out.println("SM4 CBC Padding encrypt result:\n" + Arrays.toString(cipherText)); - decryptedData = Sm4.decrypt_CBC_Padding(key, iv, cipherText); + decryptedData = SM4.decrypt_CBC_Padding(key, iv, cipherText); System.out.println("SM4 CBC Padding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA)) { Assert.fail(); } - cipherText = Sm4.encrypt_CBC_NoPadding(key, iv, SRC_DATA_16B); + cipherText = SM4.encrypt_CBC_NoPadding(key, iv, SRC_DATA_16B); System.out.println("SM4 CBC NoPadding encrypt result:\n" + Arrays.toString(cipherText)); - decryptedData = Sm4.decrypt_CBC_NoPadding(key, iv, cipherText); + decryptedData = SM4.decrypt_CBC_NoPadding(key, iv, cipherText); System.out.println("SM4 CBC NoPadding decrypt result:\n" + Arrays.toString(decryptedData)); if (!Arrays.equals(decryptedData, SRC_DATA_16B)) { Assert.fail(); From 9827414ac5b0bc317710f62905ec2791a5dddd10 Mon Sep 17 00:00:00 2001 From: ghy Date: Tue, 9 Mar 2021 16:25:07 +0800 Subject: [PATCH 3/3] identity base test --- .../java/minsecurity/identity/Identity.java | 30 +++++-- .../minsecurity/identity/IdentityUtil.java | 2 +- .../minsecurity/identity/InnerIdentity.java | 4 +- .../minsecurity/identity/TestIdentity.java | 79 +++++++++++++++++++ 4 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 src/test/java/minsecurity/identity/TestIdentity.java diff --git a/src/main/java/minsecurity/identity/Identity.java b/src/main/java/minsecurity/identity/Identity.java index 572bf39..b16efd0 100644 --- a/src/main/java/minsecurity/identity/Identity.java +++ b/src/main/java/minsecurity/identity/Identity.java @@ -13,6 +13,8 @@ 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; @@ -22,6 +24,7 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.util.Arrays; import java.util.Base64; /* @@ -32,7 +35,7 @@ import java.util.Base64; * @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; @@ -108,6 +111,7 @@ public class Identity { 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); @@ -119,7 +123,7 @@ public class Identity { public static Identity load(byte[] data, String passwd) throws BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException, - InvalidKeyException, IOException, CertException { + InvalidKeyException, CertException { byte[] bytesOfIdentity = Base64.getDecoder().decode(data); byte[] plain; if(passwd != null && passwd.length() != 0){ @@ -129,7 +133,13 @@ public class Identity { plain = bytesOfIdentity; } ObjectMapper mapper = new ObjectMapper(); - InnerIdentity innerIdentity = mapper.readValue(plain, InnerIdentity.class); + 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 ??? @@ -230,6 +240,16 @@ public class Identity { 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/IdentityUtil.java b/src/main/java/minsecurity/identity/IdentityUtil.java index e9ba140..87a0814 100644 --- a/src/main/java/minsecurity/identity/IdentityUtil.java +++ b/src/main/java/minsecurity/identity/IdentityUtil.java @@ -35,7 +35,7 @@ public class IdentityUtil { innerIdentity.setPrikey(identity.getPrikey().getBytes()); } if(identity.getPubkey() != null){ - innerIdentity.setPrikey(identity.getPubkey().getBytes()); + innerIdentity.setPubkey(identity.getPubkey().getBytes()); } innerIdentity.setPasswd(identity.getPasswd()); innerIdentity.setCert(CertUtils.toPem(identity.getCert(), identity.getPasswd().getBytes(), Common.SM4CBC)); diff --git a/src/main/java/minsecurity/identity/InnerIdentity.java b/src/main/java/minsecurity/identity/InnerIdentity.java index e804b57..927f46a 100644 --- a/src/main/java/minsecurity/identity/InnerIdentity.java +++ b/src/main/java/minsecurity/identity/InnerIdentity.java @@ -85,8 +85,8 @@ public class InnerIdentity { return "InnerIdentity{" + "Name='" + Name + '\'' + ", KeyParam=" + KeyParam + - ", Prikey=" + ByteUtils.toHexString(Prikey) + - ", Pubkey=" + ByteUtils.toHexString(Pubkey) + + ", Prikey=" + (Prikey == null ? "null" : ByteUtils.toHexString(Prikey)) + + ", Pubkey=" + (Pubkey == null ? "null" : ByteUtils.toHexString(Pubkey)) + ", Passwd='" + Passwd + '\'' + ", Cert='" + Cert + '\'' + '}'; 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())); + } + + +}