Https证书&证书链-私钥 验证

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.util.encoders.Base64;
import sun.security.provider.X509Factory;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Https证书工具类
 */
@Slf4j
public class HttpsCertUtils {

    public static final String PKCS1_BEGIN_KEY = "-----BEGIN RSA PRIVATE KEY-----";
    public static final String PKCS1_END_KEY = "-----END RSA PRIVATE KEY-----";

    public static final String PKCS8_BEGIN_KEY = "-----BEGIN PRIVATE KEY-----";
    public static final String PKCS8_END_KEY = "-----END PRIVATE KEY-----";

    static {
        try {
            Security.addProvider(new BouncyCastleProvider());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 校验证书链, 支持正反顺序,不支持乱序,验证逻辑不是很完善
     *
     * @param orderType asc //自己-中间-根  desc://根-中间-自己
     */
    public static boolean verifyCertChain(List list, String orderType) {
        try {
            int nSize = list.size();
            if ("desc".equalsIgnoreCase(orderType)) {
                Set serialNumberSet = new HashSet();
                Principal principalLast = null;
                for (int i = 0; i < nSize; i++) {
                    X509Certificate x509Certificate = list.get(i);
                    serialNumberSet.add(x509Certificate.getSerialNumber());
                    Principal principalIssuer = x509Certificate.getIssuerDN();
                    Principal principalSubject = x509Certificate.getSubjectDN();
                    if (principalLast != null) {
                        try {
                            PublicKey publickey = list.get(i - 1).getPublicKey();
                            x509Certificate.verify(publickey);
                        } catch (Exception e) {
                            log.error("verifyCertChain() 校验证书链错误,原因:", e);
                            return false;
                        }
                    }
                    principalLast = principalSubject;
                }
            } else {
                for (int i = nSize - 1; i > 0; i--) {
                    X509Certificate x509Certificate = list.get(i);
                    try {
                        PublicKey publickey = x509Certificate.getPublicKey();
                        list.get(i - 1).verify(publickey);
                    } catch (Exception e) {
                        log.error("verifyCertChain() 校验证书链错误,原因:", e);
                        return false;
                    }
                }
            }
            return true;
        } catch (
                Exception e) {
            log.error("verify() 证书&证书链错误,原因:", e);
        }
        return false;
    }


    public static boolean checkValidityChain(List certificateList) {
        Date date = new Date();
        for (X509Certificate certificate : certificateList) {
            try {
                certificate.checkValidity(date);
            } catch (Exception e) {
                return false;
            }
        }
        return true;
    }


    public static X509Certificate conver2X509Certificate(String certStr) throws Exception {
        byte[] decoded = Base64.decode(certStr.replaceAll(X509Factory.BEGIN_CERT, "")
                .replaceAll(X509Factory.END_CERT, "")
                .replaceAll("[\n\r]", ""));
        InputStream in = new ByteArrayInputStream(decoded);
        X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(in);
        return certificate;
    }


    /**
     * 校验证书链格式
     *
     * @param certStrList
     */
    public static void verifyCertFormat(List certStrList) {
        if (CollectionUtils.isEmpty(certStrList)) {
            log.error("verifyCertFormat() 证书为空, 入参=[{}]", JSON.toJSONString(certStrList));
            throw new InputParamException("证书为空,请重新输入");
        }
        for (String certStr : certStrList) {
            certStr = StringUtils.trim(certStr);
            if (!(certStr.startsWith(X509Factory.BEGIN_CERT) || !certStr.endsWith(X509Factory.END_CERT))) {
                log.error("verifyCertFormat() 证书格式错误, 入参={}", JSON.toJSONString(certStrList));
                throw new RuntimeException("证书格式错误,请重新输入");
            }
            String certContent = "";
            certContent = StringUtils.substringBetween(certStr, X509Factory.BEGIN_CERT, X509Factory.END_CERT);
            if (StringUtils.isBlank(StringUtils.trim(certContent))) {
                log.error("getPrivateKey() 证书内容为空, 入参={}", JSON.toJSONString(certStrList));
                throw new RuntimeException("证书格式错误,请重新输入");
            }
        }
    }

    public static String getValidTime(X509Certificate cert) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startTime = cert.getNotBefore();
        Date endTime = cert.getNotAfter();
        Map map = new HashMap<>();
        map.put(sdf.format(startTime), sdf.format(endTime));
        return sdf.format(endTime);
    }

    public static PublicKey get(Certificate cert) {
        return cert.getPublicKey();
    }

    public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
        PrivateKey privateKey = null;
        try {
            privateKeyStr = StringUtils.trim(privateKeyStr);
            if (privateKeyStr == null
                    || !((privateKeyStr.startsWith(PKCS1_BEGIN_KEY) && privateKeyStr.endsWith(PKCS1_END_KEY))
                    || (privateKeyStr.startsWith(PKCS8_BEGIN_KEY) && privateKeyStr.endsWith(PKCS8_END_KEY)))) {
                log.error("getPrivateKey() 私钥格式错误, privateKey=[{}]", privateKeyStr);
                return null;
            }
            String privateKeyContent = "";
            if (privateKeyStr.startsWith(PKCS1_BEGIN_KEY)) {
                privateKeyContent = StringUtils.substringBetween(privateKeyStr, PKCS1_BEGIN_KEY, PKCS1_END_KEY);
            } else {
                privateKeyContent = StringUtils.substringBetween(privateKeyStr, PKCS8_BEGIN_KEY, PKCS8_END_KEY);
            }
            if (StringUtils.isBlank(StringUtils.trim(privateKeyContent))) {
                log.error("getPrivateKey() 私钥内容为空, privateKey=[{}]", privateKeyStr);
                return null;
            }
            privateKeyContent = privateKeyContent.replaceAll("[\n\r]", "");
            byte[] bytes = Base64.decode(privateKeyContent);
            privateKeyStr = StringUtils.trim(privateKeyStr);
            if (privateKeyStr.endsWith(PKCS1_END_KEY)) {
                // pkcs1的必须是带换行符\n的
                Reader privateKeyReader = new StringReader(privateKeyStr);
                PEMParser privatePemParser = new PEMParser(privateKeyReader);
                Object privateObject = privatePemParser.readObject();
                if (privateObject instanceof PEMKeyPair) {
                    PEMKeyPair pemKeyPair = (PEMKeyPair) privateObject;
                    JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
                    privateKey = converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo());
                    return privateKey;
                }
            } else if (privateKeyStr.endsWith(PKCS8_END_KEY)) {
                PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(bytes);
                KeyFactory kf = KeyFactory.getInstance("RSA");
                privateKey = kf.generatePrivate(privKeySpec);
            }
            return privateKey;
        } catch (Exception e) {
            log.error("getPrivateKey() 解析私钥错误,参数:{},原因:", privateKeyStr, e);
        }
        return null;
    }


    /**
     * 用私钥签名,公钥验签
     */
    public static boolean verifyKeyMatch(X509Certificate cert, PrivateKey privateKey) {
        try {
            String plainText = (RandomStringUtils.randomAlphanumeric(8) + "@ctyun-xlive");
            byte[] data = plainText.getBytes();
            Signature signature = null;
            signature = Signature.getInstance(cert.getSigAlgName());
            signature.initSign(privateKey);
            signature.update(data);
            byte[] sign = signature.sign();

            PublicKey publicKey = cert.getPublicKey();

            signature = Signature.getInstance(cert.getSigAlgName());
            signature.initVerify(publicKey);
            signature.update(data);
            return signature.verify(sign);
        } catch (Exception e) {
            log.error("verifyKeyMatch() 校验证书与私钥是否匹配异常", e);
        }
        return false;
    }
}

你可能感兴趣的:(Java)