mirror of
https://gitee.com/willfree/min-dev-java.git
synced 2026-10-04 19:42:01 +08:00
security部分添加注释
This commit is contained in:
1 parent
879e09e879
commit
9d370a5353
12 files changed
+396
-141
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
|
||||
@@ -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;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets;
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class HashAlgo {
|
||||
// TODO: 单元测试
|
||||
// TODO: 单元测试 基本上只需要对sm3做单元测试
|
||||
///////////////
|
||||
///// SM3 /////
|
||||
///////////////
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
+39
-1
@@ -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<Integer>[] res = new List[days + 15];
|
||||
for(int i = 0; i < days + 15; i++){
|
||||
res[i] = new ArrayList<Integer>();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user