mirror of
https://gitee.com/willfree/min-dev-java.git
synced 2026-10-04 19:42:01 +08:00
Merge branch 'master' of gitee.com:willfree/min-dev-java
This commit is contained in:
commit
472f3585c6
25 files changed
+1045
-247
No files matched your search
@@ -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");
|
||||
|
||||
@@ -3,12 +3,18 @@ package minsecurity.certificate.cert;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import minsecurity.Common;
|
||||
import minsecurity.crypto.PublicKeyInterface;
|
||||
import minsecurity.crypto.PublicKeyUtils;
|
||||
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
||||
import minsecurity.crypto.*;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.util.Base64;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
@@ -21,6 +27,13 @@ public class CertUtils {
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CertUtils.class);
|
||||
public static final int VERSION1 = 1;
|
||||
|
||||
/**
|
||||
* Certificate -> InnerCertificate
|
||||
* @param certificate
|
||||
* @return InnerCertificate
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static InnerCertificate parseCertToInnerCert(Certificate certificate){
|
||||
TbsCertificate tbsCertificate = new TbsCertificate();
|
||||
tbsCertificate.setVersion(certificate.getVersion());
|
||||
@@ -43,12 +56,20 @@ public class CertUtils {
|
||||
return innerCertificate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* InnerCertificate -> Certificate
|
||||
* @param i
|
||||
* @return minsecurity.certificate.cert.Certificate
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static Certificate parseInnerCertToCert(InnerCertificate i){
|
||||
Certificate certificate = new Certificate();
|
||||
|
||||
certificate.setVersion(i.getTbsCertificate().getVersion());
|
||||
certificate.setSerialNumber(i.getTbsCertificate().getSerialNumber());
|
||||
PublicKeyInterface publicKey = PublicKeyUtils.unMarshalPublicKey(i.getTbsCertificate().getPublicKey(),i.getSignatureAlgorithm());
|
||||
PublicKeyInterface publicKey = KeyUtils.unMarshalPublicKey(i.getTbsCertificate().getPublicKey(),i.getSignatureAlgorithm());
|
||||
certificate.setPublicKey(publicKey);
|
||||
certificate.setSignature(i.getSignatureValue());
|
||||
certificate.setSignatureAlgorithm(i.getTbsCertificate().getSignatureAlgorithm());
|
||||
@@ -64,6 +85,13 @@ public class CertUtils {
|
||||
return certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查证书是否在有效期内
|
||||
* @param innerCertificate
|
||||
* @return boolean
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static boolean checkDuration(InnerCertificate innerCertificate){
|
||||
long curTime = System.currentTimeMillis();
|
||||
// logger.debug("current time: {}", curTime);
|
||||
@@ -74,26 +102,32 @@ public class CertUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
// cur = 1615018693993
|
||||
// notbefore = 1615018693858
|
||||
// notafter = 1615018694058
|
||||
|
||||
|
||||
/**
|
||||
* 使用publicKey验证签名
|
||||
* @param cert
|
||||
* @param publicKey
|
||||
* @return boolean
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static boolean checkSign(InnerCertificate cert, PublicKeyInterface publicKey) throws Exception {
|
||||
switch (cert.getTbsCertificate().getSignatureAlgorithm()){
|
||||
case Common.SM3withSM2:
|
||||
// TODO: 证书序列化方法
|
||||
byte[] bytesOfCert = serialization(cert.getTbsCertificate());
|
||||
logger.debug("验签序列化bytes: {}", ByteUtils.toHexString(bytesOfCert));
|
||||
// byte[] digest = HashAlgo.sm3(bytesOfCert);
|
||||
logger.debug("验签sign: {}", ByteUtils.toHexString(cert.getSignatureValue()));
|
||||
return publicKey.verify(bytesOfCert, cert.getSignatureValue());
|
||||
default:
|
||||
throw new Exception("未定义的签名方法");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 证书序列化方法
|
||||
/**
|
||||
* 将TbsCertificate类型实例转化为字节流
|
||||
* @param tbsCertificate
|
||||
* @return byte[]
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static byte[] serialization(TbsCertificate tbsCertificate){
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
byte[] bytesOfCertJson;
|
||||
@@ -106,6 +140,13 @@ public class CertUtils {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 将InnerCertificate类型实例转化为字节流
|
||||
* @param innerCertificate
|
||||
* @return byte[]
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static byte[] serialization(InnerCertificate innerCertificate){
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
byte[] bytesOfCertJson;
|
||||
@@ -118,17 +159,23 @@ public class CertUtils {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
// TODO: 证书反序列化
|
||||
/**
|
||||
* 根据typeOfCert可将字节流反序列化为TbsCertificate或InnerCertificate,
|
||||
* 返回Object类型, 调用者调用时需要手动强制类型转化
|
||||
* @param bytesOfCert 字节流
|
||||
* @param typeOfCert Common.TbsCertificate或Common.InnerCertificate
|
||||
* @return java.lang.Object
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static Object deserialization(byte[] bytesOfCert, int typeOfCert){
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
switch (typeOfCert) {
|
||||
case Common.TbsCertificate:
|
||||
TbsCertificate tbsCertificate = mapper.readValue(bytesOfCert, TbsCertificate.class);
|
||||
return tbsCertificate;
|
||||
return mapper.readValue(bytesOfCert, TbsCertificate.class);
|
||||
case Common.InnerCertificate:
|
||||
InnerCertificate innerCertificate = mapper.readValue(bytesOfCert, InnerCertificate.class);
|
||||
return innerCertificate;
|
||||
return mapper.readValue(bytesOfCert, InnerCertificate.class);
|
||||
default:
|
||||
throw new CertException("未知证书类型");
|
||||
}
|
||||
@@ -139,4 +186,120 @@ public class CertUtils {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 使用priv私钥给Certificate类型实例签名
|
||||
* @param certificate 未签名证书
|
||||
* @param priv 私钥
|
||||
* @return void
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static void signCert(Certificate certificate, PrivateKeyInterface priv) throws Exception {
|
||||
byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(certificate).getTbsCertificate());
|
||||
// logger.debug("签名序列化bytes: {}", ByteUtils.toHexString(bytesOfCert));
|
||||
switch (certificate.getSignatureAlgorithm()){
|
||||
case Common.SM3withSM2:
|
||||
certificate.setSignature(priv.sign(bytesOfCert));
|
||||
break;
|
||||
default:
|
||||
logger.debug("signAlgo: {}", certificate.getSignatureAlgorithm());
|
||||
throw new Exception("未定义的签名方法");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用ca的公钥对sub进行验签, 如果时根证书验签, 调用时ca与sub指向同一个实例
|
||||
* @param ca
|
||||
* @param sub
|
||||
* @return boolean
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static boolean verifyCert(Certificate ca, Certificate sub) throws Exception {
|
||||
InnerCertificate innerCertificate = CertUtils.parseCertToInnerCert(sub);
|
||||
switch (innerCertificate.getTbsCertificate().getVersion()){
|
||||
case CertUtils.VERSION1:
|
||||
boolean isValid = CertUtils.checkDuration(innerCertificate);
|
||||
// logger.debug("有效期内:{}", isValid);
|
||||
if(!isValid)
|
||||
return false;
|
||||
if(sub.isCA()){ // 根证书, 自验证
|
||||
return checkSign(innerCertificate, sub.getPublicKey());
|
||||
} else { // 使用ca验证sub
|
||||
return checkSign(innerCertificate, ca.getPublicKey());
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 证书序列化为String类型, 密码为null或为空时不对证书进行加密保存
|
||||
* @param certificate
|
||||
* @param passwd
|
||||
* @param symAlgoMode Common.SM4CBC / Common.SM4ECB
|
||||
* @return java.lang.String
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static String toPem(Certificate certificate, byte[] passwd, int symAlgoMode) throws CertException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
|
||||
if(certificate.getSignature() == null){
|
||||
throw new CertException("该证书未签名");
|
||||
}
|
||||
byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(certificate));
|
||||
byte[] ret;
|
||||
if(passwd != null && passwd.length > 0){
|
||||
// byte[] sm4Key;
|
||||
byte[] sm4Key = KeyUtils.get16bytePasswd(passwd);
|
||||
|
||||
switch (symAlgoMode){
|
||||
case Common.SM4CBC:{
|
||||
// TODO: PADDING??? IV?????
|
||||
ret = SM4.encrypt_CBC_Padding(sm4Key, new byte[16],bytesOfCert);
|
||||
break;
|
||||
}
|
||||
case Common.SM4ECB:{
|
||||
ret = SM4.encrypt_ECB_Padding(sm4Key, bytesOfCert);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new CertException("未定义的对称加密算法");
|
||||
}
|
||||
} else {
|
||||
ret = bytesOfCert;
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* String类型证书转化为Certificate对象
|
||||
* @param pemString
|
||||
* @param passwd
|
||||
* @param symAlgoMode Common.SM4CBC / Common.SM4ECB
|
||||
* @return minsecurity.certificate.cert.Certificate
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static Certificate fromPem(String pemString, byte[] passwd, int symAlgoMode) throws CertException, BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException, InvalidKeyException {
|
||||
if(pemString == null || pemString.equals("")){
|
||||
throw new CertException("pem串为空");
|
||||
}
|
||||
byte[] bytesOfPem = Base64.getDecoder().decode(pemString);
|
||||
byte[] bytesOfCert = new byte[0];
|
||||
if(passwd != null && passwd.length > 0){
|
||||
byte[] sm4Key = KeyUtils.get16bytePasswd(passwd);
|
||||
switch (symAlgoMode){
|
||||
case Common.SM4CBC:
|
||||
bytesOfCert = SM4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem);
|
||||
break;
|
||||
case Common.SM4ECB:
|
||||
bytesOfCert = SM4.decrypt_ECB_Padding(sm4Key, bytesOfPem);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bytesOfCert = bytesOfPem;
|
||||
}
|
||||
InnerCertificate innerCertificate = (InnerCertificate) deserialization(bytesOfCert, Common.InnerCertificate);
|
||||
return CertUtils.parseInnerCertToCert(innerCertificate);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,13 @@
|
||||
package minsecurity.certificate.cert;
|
||||
|
||||
import minsecurity.Common;
|
||||
import minsecurity.crypto.HashAlgo;
|
||||
import minsecurity.crypto.PrivateKeyInterface;
|
||||
import minsecurity.crypto.PublicKeyInterface;
|
||||
import minsecurity.crypto.Sm4;
|
||||
import minsecurity.crypto.sm2.Sm2PublicKey;
|
||||
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.security.*;
|
||||
import java.util.Base64;
|
||||
|
||||
import static minsecurity.certificate.cert.CertUtils.*;
|
||||
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description:
|
||||
* @Description: 证书bean类
|
||||
* @Version: 1.0.0
|
||||
* @Date: 17:05 2021/03/05
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
@@ -174,104 +159,23 @@ public class Certificate {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
|
||||
public void signCert(PrivateKeyInterface priv) throws Exception {
|
||||
byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(this).getTbsCertificate());
|
||||
logger.debug("签名序列化bytes: {}", ByteUtils.toHexString(bytesOfCert));
|
||||
switch (this.signatureAlgorithm){
|
||||
case Common.SM3withSM2:
|
||||
// byte[] digest = HashAlgo.sm3(bytesOfCert);
|
||||
this.signature = priv.sign(bytesOfCert);
|
||||
logger.debug("签名sign: {}", ByteUtils.toHexString(this.signature));
|
||||
// Sm2PublicKey sm2PublicKey = (Sm2PublicKey) this.publicKey;
|
||||
// logger.debug("临时验签: {}", sm2PublicKey.verify(bytesOfCert, signature));
|
||||
break;
|
||||
default:
|
||||
logger.debug("signAlgo: {}",this.signatureAlgorithm);
|
||||
throw new Exception("未定义的签名方法");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verifyCert(Certificate ca, Certificate sub) throws Exception {
|
||||
InnerCertificate innerCertificate = CertUtils.parseCertToInnerCert(sub);
|
||||
switch (innerCertificate.getTbsCertificate().getVersion()){
|
||||
case CertUtils.VERSION1:
|
||||
boolean isValid = CertUtils.checkDuration(innerCertificate);
|
||||
logger.debug("有效期内:{}", isValid);
|
||||
if(!isValid)
|
||||
return false;
|
||||
if(sub.isCA()){
|
||||
return checkSign(innerCertificate, sub.getPublicKey());
|
||||
} else {
|
||||
return checkSign(innerCertificate, ca.getPublicKey());
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toPem(byte[] passwd, int symAlgoMode) throws CertException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
|
||||
if(this.getSignature() == null){
|
||||
throw new CertException("该证书未签名");
|
||||
}
|
||||
byte[] bytesOfCert = serialization(CertUtils.parseCertToInnerCert(this));
|
||||
byte[] ret = new byte[0];
|
||||
if(passwd != null && passwd.length > 0){
|
||||
byte[] hashPasswd = HashAlgo.sm3(passwd);
|
||||
if( hashPasswd.length == 32){
|
||||
for(int i = 0; i < 16; i++){
|
||||
hashPasswd[i] += hashPasswd[i + 16];
|
||||
}
|
||||
}
|
||||
byte[] sm4Key = new byte[16];
|
||||
System.arraycopy(hashPasswd,0,sm4Key,0,16);
|
||||
|
||||
switch (symAlgoMode){
|
||||
case Common.SM4CBC:{
|
||||
// TODO: PADDING??? IV?????
|
||||
ret = Sm4.encrypt_CBC_Padding(sm4Key, new byte[16],bytesOfCert);
|
||||
break;
|
||||
}
|
||||
case Common.SM4ECB:{
|
||||
ret = Sm4.encrypt_ECB_Padding(sm4Key, bytesOfCert);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new CertException("未定义的对称加密算法");
|
||||
}
|
||||
} else {
|
||||
ret = bytesOfCert;
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(ret);
|
||||
}
|
||||
|
||||
public static Certificate fromPem(String pemString, byte[] passwd, int symAlgoMode) throws CertException, BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException, InvalidKeyException {
|
||||
if(pemString == null || pemString.equals("")){
|
||||
throw new CertException("pem串为空");
|
||||
}
|
||||
byte[] bytesOfPem = Base64.getDecoder().decode(pemString);
|
||||
byte[] bytesOfCert = new byte[0];
|
||||
if(passwd != null && passwd.length > 0){
|
||||
byte[] hashPasswd = HashAlgo.sm3(passwd);
|
||||
if( hashPasswd.length == 32){
|
||||
for(int i = 0; i < 16; i++){
|
||||
hashPasswd[i] += hashPasswd[i + 16];
|
||||
}
|
||||
}
|
||||
byte[] sm4Key = new byte[16];
|
||||
System.arraycopy(hashPasswd,0,sm4Key,0,16);
|
||||
|
||||
switch (symAlgoMode){
|
||||
case Common.SM4CBC:
|
||||
bytesOfCert = Sm4.decrypt_CBC_Padding(sm4Key,new byte[16], bytesOfPem);
|
||||
case Common.SM4ECB:
|
||||
bytesOfCert = Sm4.decrypt_ECB_Padding(sm4Key, bytesOfPem);
|
||||
}
|
||||
} else {
|
||||
bytesOfCert = bytesOfPem;
|
||||
}
|
||||
InnerCertificate innerCertificate = (InnerCertificate) deserialization(bytesOfCert, Common.InnerCertificate);
|
||||
return CertUtils.parseInnerCertToCert(innerCertificate);
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Certificate{" +
|
||||
"version=" + version +
|
||||
", serialNumber=" + serialNumber +
|
||||
", publicKey=" + publicKey +
|
||||
", signature=" + ByteUtils.toHexString(signature) +
|
||||
", signatureAlgorithm=" + signatureAlgorithm +
|
||||
", publicKeyAlgorithm=" + publicKeyAlgorithm +
|
||||
", issueTo='" + issueTo + '\'' +
|
||||
", issuer='" + issuer + '\'' +
|
||||
", notBefore=" + notBefore +
|
||||
", notAfter=" + notAfter +
|
||||
", keyUsage=" + keyUsage +
|
||||
", isCA=" + isCA +
|
||||
", timestamp=" + timestamp +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 /////
|
||||
///////////////
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package minsecurity.crypto;
|
||||
|
||||
import minsecurity.Common;
|
||||
import minsecurity.crypto.sm2.Sm2PublicKey;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 16:02 2021/03/06
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class PublicKeyUtils {
|
||||
public static PublicKeyInterface unMarshalPublicKey(byte[] bytesOfPublicKey, int algorithm) {
|
||||
if (bytesOfPublicKey == null || bytesOfPublicKey.length == 0) {
|
||||
return null;
|
||||
}
|
||||
switch (algorithm) {
|
||||
case Common.SM2:
|
||||
Sm2PublicKey sm2PublicKey = new Sm2PublicKey();
|
||||
sm2PublicKey.setBytes(bytesOfPublicKey);
|
||||
return sm2PublicKey;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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());
|
||||
}
|
||||
+59
-6
@@ -1,6 +1,5 @@
|
||||
package minsecurity.crypto.sm2;
|
||||
|
||||
import minsecurity.Common;
|
||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
@@ -17,7 +16,6 @@ import org.bouncycastle.math.ec.ECPoint;
|
||||
import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
@@ -32,13 +30,17 @@ import static minsecurity.Common.ALGO_NAME_EC;
|
||||
* @Date: 18:48 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Sm2Base {
|
||||
public class SM2Base {
|
||||
|
||||
static {
|
||||
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
||||
}
|
||||
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Sm2Base.class);
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SM2Base.class);
|
||||
|
||||
/*
|
||||
* 以下为SM2推荐曲线参数
|
||||
*/
|
||||
public static final SM2P256V1Curve CURVE = new SM2P256V1Curve();
|
||||
public final static BigInteger SM2_ECC_P = CURVE.getQ();
|
||||
public final static BigInteger SM2_ECC_A = CURVE.getA().toBigInteger();
|
||||
@@ -56,6 +58,14 @@ public class Sm2Base {
|
||||
private static final String PEM_STRING_PUBLIC = "PUBLIC KEY";
|
||||
private static final String PEM_STRING_ECPRIVATEKEY = "EC PRIVATE KEY";
|
||||
|
||||
|
||||
/**
|
||||
* 生成BC自定义的SM2公私钥
|
||||
* @param
|
||||
* @return org.bouncycastle.crypto.AsymmetricCipherKeyPair
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static AsymmetricCipherKeyPair generateKeyPairParameter(){
|
||||
SecureRandom random = new SecureRandom();
|
||||
ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(DOMAIN_PARAMS,
|
||||
@@ -66,12 +76,27 @@ public class Sm2Base {
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成java.security.KeyPair类型的SM2公私钥
|
||||
* @param
|
||||
* @return java.security.KeyPair
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
InvalidAlgorithmParameterException {
|
||||
SecureRandom random = new SecureRandom();
|
||||
return generateKeyPair(DOMAIN_PARAMS, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成java.security.KeyPair类型的SM2公私钥, 需自定义曲线参数
|
||||
* @param domainParameters
|
||||
* @param random
|
||||
* @return
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static KeyPair generateKeyPair(ECDomainParameters domainParameters, SecureRandom random)
|
||||
throws NoSuchProviderException, NoSuchAlgorithmException,
|
||||
InvalidAlgorithmParameterException {
|
||||
@@ -82,7 +107,13 @@ public class Sm2Base {
|
||||
return kpg.generateKeyPair();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* BC公私钥转换为java.security.KeyPair公私钥
|
||||
* @param bcKeyPair
|
||||
* @return
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static KeyPair convertBcToJceKeyPair(AsymmetricCipherKeyPair bcKeyPair) throws Exception {
|
||||
byte[] pkcs8Encoded = PrivateKeyInfoFactory.createPrivateKeyInfo(bcKeyPair.getPrivate()).getEncoded();
|
||||
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pkcs8Encoded);
|
||||
@@ -92,13 +123,27 @@ public class Sm2Base {
|
||||
return new KeyPair(keyFac.generatePublic(spkiKeySpec), keyFac.generatePrivate(pkcs8KeySpec));
|
||||
}
|
||||
|
||||
/**
|
||||
* java.security.KeyPair转换为BC类型的公私钥对
|
||||
* @param keyPair
|
||||
* @return
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static AsymmetricCipherKeyPair convertKeyPair2Bc(KeyPair keyPair) {
|
||||
ECPrivateKeyParameters priKey = convertPrivateKeyToParameters((BCECPrivateKey) keyPair.getPrivate());
|
||||
ECPublicKeyParameters pubKey = convertPublicKeyToParameters((BCECPublicKey) keyPair.getPublic());
|
||||
return new AsymmetricCipherKeyPair(priKey,pubKey);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* BCECPrivateKey类型私钥转化为ECPrivateKeyParameters类型的私钥,
|
||||
* 调用者若想将java.security.PrivateKey转化为ECPrivateKeyParameters, 调用时将其强制转换为BCECPrivateKey类型
|
||||
* @param ecPriKey
|
||||
* @return ECPrivateKeyParameters
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) {
|
||||
ECParameterSpec parameterSpec = ecPriKey.getParameters();
|
||||
ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(),
|
||||
@@ -106,6 +151,14 @@ public class Sm2Base {
|
||||
return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* BCECPublicKey类型私钥转化为ECPublicKeyParameters类型的私钥,
|
||||
* 调用者若想将java.security.PublicKey转化为ECPublicKeyParameters, 调用时将其强制转换为BCECPublicKey类型
|
||||
* @param ecPubKey
|
||||
* @return ECPrivateKeyParameters
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) {
|
||||
ECParameterSpec parameterSpec = ecPubKey.getParameters();
|
||||
ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(),
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
+24
-11
@@ -20,28 +20,41 @@ import java.security.SecureRandom;
|
||||
* @Date: 19:40 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Sm2PrivateKey implements PrivateKeyInterface {
|
||||
public class SM2PrivateKey implements PrivateKeyInterface {
|
||||
|
||||
public Sm2PrivateKey(){}
|
||||
|
||||
public Sm2PrivateKey(byte[] d) {
|
||||
public SM2PrivateKey(){}
|
||||
|
||||
/*
|
||||
* @param d
|
||||
* @return
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
|
||||
/*
|
||||
* @param d 大数
|
||||
* @return
|
||||
* @author hongyu guo
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public SM2PrivateKey(byte[] d) {
|
||||
if(d.length == 32 || d.length == 33)
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS);
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), SM2Base.DOMAIN_PARAMS);
|
||||
else {
|
||||
try {
|
||||
throw new Sm2Exception("SM2私钥中,参数d长度应为32/33");
|
||||
} catch (Sm2Exception e) {
|
||||
throw new SM2Exception("SM2私钥中,参数d长度应为32/33");
|
||||
} catch (SM2Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public Sm2PrivateKey(byte[] d, ECDomainParameters parameters){
|
||||
public SM2PrivateKey(byte[] d, ECDomainParameters parameters){
|
||||
if(d.length == 32 || d.length == 33)
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), parameters);
|
||||
else {
|
||||
try {
|
||||
throw new Sm2Exception("SM2私钥中,参数d长度应为32/33");
|
||||
} catch (Sm2Exception e) {
|
||||
throw new SM2Exception("SM2私钥中,参数d长度应为32/33");
|
||||
} catch (SM2Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -56,7 +69,7 @@ public class Sm2PrivateKey implements PrivateKeyInterface {
|
||||
public boolean setBytes(byte[] d) {
|
||||
if(d.length != 32 && d.length != 33)
|
||||
return false;
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), Sm2Base.DOMAIN_PARAMS);
|
||||
privateKey = new ECPrivateKeyParameters(new BigInteger(d), SM2Base.DOMAIN_PARAMS);
|
||||
return true;
|
||||
}
|
||||
|
||||
+28
-8
@@ -15,21 +15,32 @@ import java.security.SecureRandom;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description: 国密sm2 非对称加密公钥
|
||||
* @Description: 国密sm2 非对称加密公钥, 实现PublicKeyInterface中的方法
|
||||
* @Version: 1.0.0
|
||||
* @Date: 17:32 2021/03/03
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Sm2PublicKey implements PublicKeyInterface {
|
||||
public class SM2PublicKey implements PublicKeyInterface {
|
||||
|
||||
public Sm2PublicKey(){}
|
||||
public SM2PublicKey(){}
|
||||
|
||||
public Sm2PublicKey(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){
|
||||
public SM2PublicKey(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters){
|
||||
publicKey = createPublicKey(xBytes,yBytes,curve,domainParameters);
|
||||
}
|
||||
/**
|
||||
* 使用SM2推荐曲线参数
|
||||
* @param xBytes 曲线x参数
|
||||
* @param yBytes 曲线y参数
|
||||
* @return
|
||||
* @author ghy
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
public SM2PublicKey(byte[] xBytes, byte[] yBytes){
|
||||
this(xBytes,yBytes, SM2Base.CURVE, SM2Base.DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
public Sm2PublicKey(byte[] xBytes, byte[] yBytes){
|
||||
this(xBytes,yBytes, Sm2Base.CURVE, Sm2Base.DOMAIN_PARAMS);
|
||||
public SM2PublicKey(byte[] bytes){
|
||||
setBytes(bytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +66,12 @@ public class Sm2PublicKey implements PublicKeyInterface {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param content
|
||||
* @return byte[] 密文
|
||||
* @author ghy
|
||||
* @date 2021/3/7
|
||||
**/
|
||||
@Override
|
||||
public byte[] encrypt(byte[] content) throws InvalidCipherTextException {
|
||||
SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C2C3);
|
||||
@@ -88,7 +105,7 @@ public class Sm2PublicKey implements PublicKeyInterface {
|
||||
}
|
||||
|
||||
private static ECPublicKeyParameters createPublicKey(byte[] xBytes, byte[] yBytes){
|
||||
return createPublicKey(xBytes,yBytes,Sm2Base.CURVE,Sm2Base.DOMAIN_PARAMS);
|
||||
return createPublicKey(xBytes,yBytes, SM2Base.CURVE, SM2Base.DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
private static int getCurveLength(ECDomainParameters domainParams) {
|
||||
@@ -108,7 +125,10 @@ public class Sm2PublicKey implements PublicKeyInterface {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ECPublicKeyParameters publicKey;
|
||||
////////////////////////////////////////////// private end //////////////////////////////////////////////
|
||||
|
||||
ECPublicKeyParameters publicKey;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
package minsecurity.identity;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import minsecurity.Common;
|
||||
import minsecurity.certificate.cert.CertException;
|
||||
import minsecurity.certificate.cert.Certificate;
|
||||
import minsecurity.crypto.KeyUtils;
|
||||
import minsecurity.crypto.PrivateKeyInterface;
|
||||
import minsecurity.crypto.PublicKeyInterface;
|
||||
import minsecurity.crypto.SM4;
|
||||
import minsecurity.crypto.sm2.SM2PrivateKey;
|
||||
import minsecurity.crypto.sm2.SM2PublicKey;
|
||||
import org.bouncycastle.crypto.CryptoException;
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 20:25 2021/03/07
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class Identity {
|
||||
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Identity.class);
|
||||
private String Name;
|
||||
private KeyParam KeyParam;
|
||||
private PrivateKeyInterface Prikey;
|
||||
private byte[] PrikeyRawByte;
|
||||
private PublicKeyInterface Pubkey;
|
||||
private String Passwd;
|
||||
private Certificate Cert;
|
||||
|
||||
public Identity(String name, KeyParam keyParam,
|
||||
PrivateKeyInterface prikey, byte[] prikeyRawByte,
|
||||
PublicKeyInterface pubkey, String passwd, Certificate cert) {
|
||||
Name = name;
|
||||
KeyParam = keyParam;
|
||||
Prikey = prikey;
|
||||
PrikeyRawByte = prikeyRawByte;
|
||||
Pubkey = pubkey;
|
||||
Passwd = passwd;
|
||||
Cert = cert;
|
||||
}
|
||||
|
||||
|
||||
public Identity(){}
|
||||
|
||||
|
||||
|
||||
public byte[] sign(byte[] digest) throws CryptoException {
|
||||
if(this.Prikey == null)
|
||||
return null;
|
||||
switch (this.KeyParam.PublicKeyAlgorithm){
|
||||
case Common.SM2:
|
||||
SM2PrivateKey sm2PrivateKey = (SM2PrivateKey) this.Prikey;
|
||||
switch (this.KeyParam.SignatureAlgorithm){
|
||||
case Common.SM3withSM2:
|
||||
return sm2PrivateKey.sign(digest);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verify(byte[] msg, byte[] digest) {
|
||||
if(this.Pubkey == null)
|
||||
return false;
|
||||
switch (this.KeyParam.PublicKeyAlgorithm){
|
||||
case Common.SM2:
|
||||
SM2PublicKey sm2PublicKey = (SM2PublicKey) this.Pubkey;
|
||||
switch (this.KeyParam.SignatureAlgorithm){
|
||||
case Common.SM3withSM2:
|
||||
return sm2PublicKey.verify(msg, digest);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher) throws InvalidCipherTextException {
|
||||
if(this.Prikey == null)
|
||||
return null;
|
||||
return this.Prikey.decrypt(cipher);
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] content) throws InvalidCipherTextException {
|
||||
if(this.Pubkey == null)
|
||||
return null;
|
||||
return this.Pubkey.encrypt(content);
|
||||
}
|
||||
|
||||
public byte[] dump(String passwd) throws NoSuchPaddingException, InvalidAlgorithmParameterException, CertException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, JsonProcessingException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
InnerIdentity innerIdentity = IdentityUtil.parseIdentityToInner(this);
|
||||
byte[] bytesOfInnerIdentity = mapper.writeValueAsBytes(innerIdentity);
|
||||
// logger.debug(ByteUtils.toHexString(bytesOfInnerIdentity));
|
||||
if(passwd != null && passwd.length() != 0) {
|
||||
byte[] sm4key = KeyUtils.get16bytePasswd(passwd.getBytes());
|
||||
byte[] cipher = SM4.encrypt_CBC_Padding(sm4key, new byte[16], bytesOfInnerIdentity);
|
||||
return Base64.getEncoder().encode(cipher);
|
||||
}
|
||||
return Base64.getEncoder().encode(bytesOfInnerIdentity);
|
||||
}
|
||||
|
||||
public static Identity load(byte[] data, String passwd)
|
||||
throws BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException,
|
||||
NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchProviderException,
|
||||
InvalidKeyException, CertException {
|
||||
byte[] bytesOfIdentity = Base64.getDecoder().decode(data);
|
||||
byte[] plain;
|
||||
if(passwd != null && passwd.length() != 0){
|
||||
byte[] sm4Key = KeyUtils.get16bytePasswd(passwd.getBytes());
|
||||
plain = SM4.decrypt_CBC_Padding(sm4Key, new byte[16], bytesOfIdentity);
|
||||
} else{
|
||||
plain = bytesOfIdentity;
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
InnerIdentity innerIdentity = null;
|
||||
// logger.debug(ByteUtils.toHexString(plain));
|
||||
try {
|
||||
innerIdentity = mapper.readValue(plain, InnerIdentity.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return IdentityUtil.parseInnerToIdentity(innerIdentity);
|
||||
}
|
||||
// TODO: passwd ???
|
||||
public boolean lock(String passwd, int algo) throws IdentityException {
|
||||
switch (algo){
|
||||
case Common.SM4ECB:
|
||||
if (passwd.length() != 16){
|
||||
throw new IdentityException("密码应为16位");
|
||||
}
|
||||
PrikeyRawByte = Prikey.getBytes();
|
||||
Prikey = null;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLocked(){
|
||||
return PrikeyRawByte != null && PrikeyRawByte.length > 0;
|
||||
}
|
||||
|
||||
// TODO: passwd ???
|
||||
public boolean unLock(String passwd, int algo) throws IdentityException {
|
||||
switch (algo) {
|
||||
case Common.SM4ECB:
|
||||
if(passwd == null || passwd.length() == 0)
|
||||
return false;
|
||||
PrivateKeyInterface privateKey = KeyUtils.unMarshalPrivateKey(PrikeyRawByte, KeyParam.PublicKeyAlgorithm);
|
||||
Prikey = privateKey;
|
||||
PrikeyRawByte = null;
|
||||
return true;
|
||||
default:
|
||||
throw new IdentityException("未知对称加密算法");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPrivateKey() {
|
||||
return Prikey != null || (PrikeyRawByte != null && PrikeyRawByte.length > 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public minsecurity.identity.KeyParam getKeyParam() {
|
||||
return KeyParam;
|
||||
}
|
||||
|
||||
public void setKeyParam(minsecurity.identity.KeyParam keyParam) {
|
||||
KeyParam = keyParam;
|
||||
}
|
||||
|
||||
public PrivateKeyInterface getPrikey() {
|
||||
return Prikey;
|
||||
}
|
||||
|
||||
public void setPrikey(PrivateKeyInterface prikey) {
|
||||
Prikey = prikey;
|
||||
}
|
||||
|
||||
public byte[] getPrikeyRawByte() {
|
||||
return PrikeyRawByte;
|
||||
}
|
||||
|
||||
public void setPrikeyRawByte(byte[] prikeyRawByte) {
|
||||
PrikeyRawByte = prikeyRawByte;
|
||||
}
|
||||
|
||||
public PublicKeyInterface getPubkey() {
|
||||
return Pubkey;
|
||||
}
|
||||
|
||||
public void setPubkey(PublicKeyInterface pubkey) {
|
||||
Pubkey = pubkey;
|
||||
}
|
||||
|
||||
public String getPasswd() {
|
||||
return Passwd;
|
||||
}
|
||||
|
||||
public void setPasswd(String passwd) {
|
||||
Passwd = passwd;
|
||||
}
|
||||
|
||||
public Certificate getCert() {
|
||||
return Cert;
|
||||
}
|
||||
|
||||
public void setCert(Certificate cert) {
|
||||
Cert = cert;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Identity{" +
|
||||
"Name='" + Name + '\'' +
|
||||
", KeyParam=" + KeyParam +
|
||||
", Prikey=" + Prikey +
|
||||
", PrikeyRawByte=" + (PrikeyRawByte == null ? "null":ByteUtils.toHexString(PrikeyRawByte)) +
|
||||
", Pubkey=" + Pubkey +
|
||||
", Passwd='" + Passwd + '\'' +
|
||||
", Cert=" + Cert +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package minsecurity.identity;
|
||||
|
||||
import minsecurity.Common;
|
||||
import minsecurity.certificate.cert.CertException;
|
||||
import minsecurity.certificate.cert.CertUtils;
|
||||
import minsecurity.certificate.cert.Certificate;
|
||||
import minsecurity.crypto.KeyUtils;
|
||||
import minsecurity.crypto.PrivateKeyInterface;
|
||||
import minsecurity.crypto.PublicKeyInterface;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 10:12 2021/03/09
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class IdentityUtil {
|
||||
public static InnerIdentity parseIdentityToInner(Identity identity)
|
||||
throws NoSuchPaddingException, InvalidKeyException, CertException,
|
||||
IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException,
|
||||
NoSuchProviderException, InvalidAlgorithmParameterException {
|
||||
InnerIdentity innerIdentity = new InnerIdentity();
|
||||
innerIdentity.setName(identity.getName());
|
||||
innerIdentity.setKeyParam(identity.getKeyParam());
|
||||
if(identity.getPrikey() != null){
|
||||
innerIdentity.setPrikey(identity.getPrikey().getBytes());
|
||||
}
|
||||
if(identity.getPubkey() != null){
|
||||
innerIdentity.setPubkey(identity.getPubkey().getBytes());
|
||||
}
|
||||
innerIdentity.setPasswd(identity.getPasswd());
|
||||
innerIdentity.setCert(CertUtils.toPem(identity.getCert(), identity.getPasswd().getBytes(), Common.SM4CBC));
|
||||
return innerIdentity;
|
||||
}
|
||||
|
||||
public static Identity parseInnerToIdentity(InnerIdentity innerIdentity)
|
||||
throws BadPaddingException, InvalidKeyException, CertException,
|
||||
NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException,
|
||||
InvalidAlgorithmParameterException, IllegalBlockSizeException {
|
||||
Identity identity = new Identity();
|
||||
identity.setName(innerIdentity.getName());
|
||||
identity.setKeyParam(innerIdentity.getKeyParam());
|
||||
if(innerIdentity.getPubkey() == null || innerIdentity.getPubkey().length == 0){
|
||||
return null;
|
||||
}
|
||||
if(innerIdentity.getPrikey() == null || innerIdentity.getPrikey().length == 0){
|
||||
return null;
|
||||
}
|
||||
PublicKeyInterface pub =
|
||||
KeyUtils.unMarshalPublicKey(innerIdentity.getPubkey(), innerIdentity.getKeyParam().PublicKeyAlgorithm);
|
||||
identity.setPubkey(pub);
|
||||
PrivateKeyInterface priv =
|
||||
KeyUtils.unMarshalPrivateKey(innerIdentity.getPrikey(), innerIdentity.getKeyParam().PublicKeyAlgorithm);
|
||||
identity.setPrikey(priv);
|
||||
identity.setPasswd(innerIdentity.getPasswd());
|
||||
Certificate certificate =
|
||||
CertUtils.fromPem(innerIdentity.getCert(), innerIdentity.getPasswd().getBytes(), Common.SM4CBC);
|
||||
identity.setCert(certificate);
|
||||
return identity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package minsecurity.identity;
|
||||
|
||||
import minsecurity.certificate.cert.Certificate;
|
||||
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* @Author: hongyu guo
|
||||
* @Description:
|
||||
* @Version: 1.0.0
|
||||
* @Date: 09:41 2021/03/09
|
||||
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
|
||||
*/
|
||||
public class InnerIdentity {
|
||||
private String Name;
|
||||
private KeyParam KeyParam;
|
||||
private byte[] Prikey;
|
||||
private byte[] Pubkey;
|
||||
private String Passwd;
|
||||
private String Cert;
|
||||
|
||||
public InnerIdentity(String name, minsecurity.identity.KeyParam keyParam, byte[] prikey, byte[] pubkey, String passwd, String cert) {
|
||||
Name = name;
|
||||
KeyParam = keyParam;
|
||||
Prikey = prikey;
|
||||
Pubkey = pubkey;
|
||||
Passwd = passwd;
|
||||
Cert = cert;
|
||||
}
|
||||
|
||||
public InnerIdentity() {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public minsecurity.identity.KeyParam getKeyParam() {
|
||||
return KeyParam;
|
||||
}
|
||||
|
||||
public void setKeyParam(minsecurity.identity.KeyParam keyParam) {
|
||||
KeyParam = keyParam;
|
||||
}
|
||||
|
||||
public byte[] getPrikey() {
|
||||
return Prikey;
|
||||
}
|
||||
|
||||
public void setPrikey(byte[] prikey) {
|
||||
Prikey = prikey;
|
||||
}
|
||||
|
||||
public byte[] getPubkey() {
|
||||
return Pubkey;
|
||||
}
|
||||
|
||||
public void setPubkey(byte[] pubkey) {
|
||||
Pubkey = pubkey;
|
||||
}
|
||||
|
||||
public String getPasswd() {
|
||||
return Passwd;
|
||||
}
|
||||
|
||||
public void setPasswd(String passwd) {
|
||||
Passwd = passwd;
|
||||
}
|
||||
|
||||
public String getCert() {
|
||||
return Cert;
|
||||
}
|
||||
|
||||
public void setCert(String cert) {
|
||||
Cert = cert;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InnerIdentity{" +
|
||||
"Name='" + Name + '\'' +
|
||||
", KeyParam=" + KeyParam +
|
||||
", Prikey=" + (Prikey == null ? "null" : ByteUtils.toHexString(Prikey)) +
|
||||
", Pubkey=" + (Pubkey == null ? "null" : ByteUtils.toHexString(Pubkey)) +
|
||||
", Passwd='" + Passwd + '\'' +
|
||||
", Cert='" + Cert + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user