yangys
2025-05-26 2ba2c339acf41fd7bb2a49f0ce186fd664a80cb5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package com.qianwen.license.keystore;
 
import java.io.FileWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Objects;
 
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import cn.hutool.core.io.FileUtil;
 
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
 
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 
public class CertificateUtils {
    /**
     * 生成密钥对及证书
     * @param certificateInfo 证书信息
     * @param caPrivateKey 根证书私钥,用于给证书签名
     * @return
     * @throws Throwable
     */
    public static KeyAndCertificate generateCertificate(CertificateInfo certificateInfo, PrivateKey caPrivateKey) throws Throwable {
        // 生成证书所需密钥对,RSA 算法,密钥长度 2048 字节
 
       // KeyPair keyPair_old = KeyUtil.generateKeyPair(certificateInfo.getKeyAlgorithm(), 2048);
        
        //下面3行自己的
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(certificateInfo.getKeyAlgorithm());
        //keyGen.initialize(2048);
        keyGen.initialize(1024);
        KeyPair keyPair = keyGen.genKeyPair();
        
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        //证书颁发者信息
        X500Name issuer = certificateInfo.getIssuer();
        //证书主题信息
        X500Name subject = certificateInfo.getSubject();
        SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
        X509v3CertificateBuilder x509v3CertificateBuilder = new X509v3CertificateBuilder(
                issuer,
                certificateInfo.getSerial(),
                certificateInfo.getNotBefore(),
                certificateInfo.getNotAfter(),
                subject,
                subjectPublicKeyInfo
        );
        JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(certificateInfo.getSignAlgorithm());
        //如果没有根证书私钥,自己给自己签名,在生成根证书时会有这种情况
        if(Objects.isNull(caPrivateKey)) {
            caPrivateKey = privateKey;
        }
        //签名者
        ContentSigner contentSigner = jcaContentSignerBuilder.build(caPrivateKey);
        //生成证书
        X509CertificateHolder x509CertificateHolder = x509v3CertificateBuilder.build(contentSigner);
        //X509CertificateHolder 转 X509Certificate
        JcaX509CertificateConverter jcaX509CertificateConverter = new JcaX509CertificateConverter();
        //转换成 X509Certificate 证书对象
        X509Certificate x509Certificate = jcaX509CertificateConverter.getCertificate(x509CertificateHolder);
        return new KeyAndCertificate(privateKey, publicKey, x509Certificate);
    }
 
    /**
     * 保存私钥到磁盘
     * @param privateKey
     * @param filePath
     * @throws Throwable
     */
    public static void save(PrivateKey privateKey, String filePath) throws Throwable {
        save(privateKey.getEncoded(), X509CertificateConstants.PRIVATE_KEY_TYPE, filePath);
    }
 
    /**
     * 保存公钥到磁盘
     * @param publicKey
     * @param filePath
     * @throws Throwable
     */
    public static void save(PublicKey publicKey, String filePath) throws Throwable {
        save(publicKey.getEncoded(), X509CertificateConstants.PUBLIC_KEY_TYPE, filePath);
    }
 
    /**
     * 保存证书到磁盘
     * @param certificate
     * @param filePath
     * @throws Throwable
     */
    public static void save(Certificate certificate, String filePath) throws Throwable {
        save(certificate.getEncoded(), X509CertificateConstants.CERTIFICATE_TYPE, filePath);
    }
 
    /**
     * 以 PEM 格式保存密钥、证书到磁盘
     * @param encodedBytes
     * @param type
     * @param filePath
     * @throws Throwable
     */
    public static void save(byte[]  encodedBytes, String type, String filePath) throws Throwable {
        FileUtil.mkParentDirs(filePath);
        
        PemObject pemObject = new PemObject(type, encodedBytes);
        try(FileWriter fileWriter = new FileWriter(filePath); PemWriter pemWriter = new PemWriter(fileWriter)) {
            pemWriter.writeObject(pemObject);
        }
    }
}