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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package com.qianwen.license.keystore;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
 
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.jce.provider.PEMUtil;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
 
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.PemUtil;
 
public class PubKeyGenDemo {
    static String root = "d:/cert"; 
    /**
     * 自签名根证书私钥保存路径 /ca/ca-private.key
     */
    private static final String CA_PRIVATE_KEY_FILE_PATH = StrUtil.format("{}/ca/ca-private.key", root);
    /**
     * 自签名根证书公钥保存路径 /ca/ca-public.key
     */
    private static final String CA_PUBLIC_KEY_FILE_PATH = StrUtil.format("{}/ca/ca-public.key", root);
    /**
     * 自签名根证书保存路径ca/ca.cer
     */
    private static final String CA_CERTIFICATE_FILE_PATH = StrUtil.format("{}/ca/ca.cer", root);
    /**
     * 自签名证书私钥保存路径self/self-private.key
     */
    private static final String SELF_SIGNED_PRIVATE_KEY_FILE_PATH = StrUtil.format("{}/self/self-private.key", root);
    /**
     * 自签名证书公钥保存路径self/self-public.key
     */
    private static final String SELF_SIGNED_PUBLIC_KEY_FILE_PATH = StrUtil.format("{}/self/self-public.key", root);
    /**
     * 自签名证书保存路径 self/self.cer
     */
    private static final String SELF_SIGNED_CERTIFICATE_FILE_PATH = StrUtil.format("{}/self/self.cer", root);
    /**
     * pkcs12 格式证书保存路径 self/self.p12
     */
    private static final String SELF_SIGNED_PKCS12_FILE_PATH = StrUtil.format("{}/self/self.p12", root);
    
    /**
     * pkcs12 公钥库格式证书保存路径
     */
    private static final String SELF_SIGNED_PUBLIC_PKCS12_FILE_PATH = StrUtil.format("{}/self/publicself.p12", root);
    /**
     * pkcs12 格式证书密码
     */
    private static final String SELF_SIGNED_PKCS12_CERTIFICATE_PASSWORD = "a1b2c3";
 
    public static void main(String[] args) throws Throwable {
        
        //Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        
        toCaCertificate();
        
        toSelfSignedCertificate();
        
        toPrivatePkcs12Store();
 
        toPublicPkcs12Store();
    }
 
    /**
     * 生成根证书及其密钥对,保存位2个key文件和一个ca.cer,这个在后续只是一个颁发者的属性需要使用
     * @throws Throwable
     */
    public static void toCaCertificate() throws Throwable {
        //根证书主题信息
        X500Name subject = new SubjectBuilder()
                .setCn("yangys")
                .setO("My CA organization")
                .setOu("My CA organizational unit name")
                .setC("My CA country code")
                .setSt("My CA state, or province name")
                .setL("My CA locality name")
                .build();
 
        //根证书颁发者信息,即自身
        X500Name issuer = subject;
 
        //根证书有效期
        DateTime notBefore = DateUtil.yesterday();
        DateTime notAfter = DateUtil.offset(notBefore, DateField.YEAR, 10);
 
        CertificateInfo certificateInfo = new CertificateInfo();
        certificateInfo.setSerial(BigInteger.valueOf(RandomUtil.randomLong(1L, Long.MAX_VALUE)));
        certificateInfo.setIssuer(issuer);
        certificateInfo.setSubject(subject);
        certificateInfo.setNotBefore(notBefore);
        certificateInfo.setNotAfter(notAfter);
        certificateInfo.setKeyAlgorithm(X509CertificateConstants.KEY_ALGORITHM);
        certificateInfo.setSignAlgorithm(X509CertificateConstants.SIGN_ALGORITHM);
 
        //生成根证书及其密钥对
        KeyAndCertificate keyAndCertificate = CertificateUtils.generateCertificate(certificateInfo, null);
        //保存根证书及其密钥对到磁盘
        CertificateUtils.save(keyAndCertificate.getPrivateKey(), CA_PRIVATE_KEY_FILE_PATH);
        CertificateUtils.save(keyAndCertificate.getPublicKey(), CA_PUBLIC_KEY_FILE_PATH);
        CertificateUtils.save(keyAndCertificate.getCertificate(), CA_CERTIFICATE_FILE_PATH);
    }
    
    /**
     * 生成自签名证书及其密钥对
     * @throws Throwable
     */
    
    public static void toSelfSignedCertificate() throws Throwable {
        //根证书私钥
        PrivateKey caPrivateKey;
        //从磁盘加载根证书私钥
        try(FileInputStream fileInputStream = new FileInputStream(CA_PRIVATE_KEY_FILE_PATH);) {
            caPrivateKey = PemUtil.readPemPrivateKey(fileInputStream);
        }
 
        //从磁盘加载根证书
        X509Certificate caCertificate;
        try(FileInputStream fileInputStream = new FileInputStream(CA_CERTIFICATE_FILE_PATH);) {
            caCertificate = (X509Certificate) KeyUtil.readX509Certificate(fileInputStream);
        }
 
        //证书颁发者信息
        X500Name issuer = new X500Name(caCertificate.getIssuerX500Principal().getName());
 
        //证书主题信息
        X500Name subject = new SubjectBuilder()
                .setCn("My common name")
                .setO("My organization")
                .setOu("My organizational unit name")
                .setC("My country code")
                .setSt("My state, or province name")
                .setL("My locality name")
                .build();
 
        //证书有效期
        DateTime notBefore = DateUtil.yesterday();
        DateTime notAfter = DateUtil.offset(notBefore, DateField.YEAR, 10);
 
        CertificateInfo certificateInfo = new CertificateInfo();
        certificateInfo.setSerial(BigInteger.valueOf(RandomUtil.randomLong(1L, Long.MAX_VALUE)));
        certificateInfo.setIssuer(issuer);
        certificateInfo.setSubject(subject);
        certificateInfo.setNotBefore(notBefore);
        certificateInfo.setNotAfter(notAfter);
        certificateInfo.setKeyAlgorithm(X509CertificateConstants.KEY_ALGORITHM);
        certificateInfo.setSignAlgorithm(X509CertificateConstants.SIGN_ALGORITHM);
 
        //生成自签名证书及其密钥对
        KeyAndCertificate keyAndCertificate = CertificateUtils.generateCertificate(certificateInfo, caPrivateKey);
        //保存自签名证书及其密钥对到磁盘
        CertificateUtils.save(keyAndCertificate.getPrivateKey(), SELF_SIGNED_PRIVATE_KEY_FILE_PATH);
        CertificateUtils.save(keyAndCertificate.getPublicKey(), SELF_SIGNED_PUBLIC_KEY_FILE_PATH);
        CertificateUtils.save(keyAndCertificate.getCertificate(), SELF_SIGNED_CERTIFICATE_FILE_PATH);
    }
   
    /**
     * 生成 pkcs12 格式证书,根据情况,可胜场公,私2中证书
     * @throws Exception
     */
    
    public static void toPrivatePkcs12Store() throws Exception {
        char[] password = SELF_SIGNED_PKCS12_CERTIFICATE_PASSWORD.toCharArray();
        //证书私钥
        PrivateKey privateKey;
        //从磁盘加载证书私钥
        try(FileInputStream fileInputStream = new FileInputStream(SELF_SIGNED_PRIVATE_KEY_FILE_PATH)) {
            privateKey = PemUtil.readPemPrivateKey(fileInputStream);
        }
        //证书
        Certificate certificate;
        //从磁盘加载证书
        try(FileInputStream fileInputStream = new FileInputStream(SELF_SIGNED_CERTIFICATE_FILE_PATH)) {
            certificate = KeyUtil.readX509Certificate(fileInputStream);
        }
        KeyStore pkcs12 = KeyStore.getInstance("pkcs12");
        pkcs12.load(null, password);
        pkcs12.setKeyEntry("myPrivate", privateKey, password, new Certificate[] {certificate});
        try(FileOutputStream fileOutputStream = new FileOutputStream(SELF_SIGNED_PKCS12_FILE_PATH)) {
            pkcs12.store(fileOutputStream, password);
        }
    }
    
    
    public static void toPublicPkcs12Store() throws Exception {
        char[] password = SELF_SIGNED_PKCS12_CERTIFICATE_PASSWORD.toCharArray();
     // 加载证书
        
        Certificate certificate;
        //从磁盘加载证书,就是用keytool从私钥导出的证书
 
        try(FileInputStream fileInputStream = new FileInputStream(SELF_SIGNED_CERTIFICATE_FILE_PATH)) {
            certificate = KeyUtil.readX509Certificate(fileInputStream);
        }
 
        KeyStore pkcs12 = KeyStore.getInstance("pkcs12");//自己改的, "BC"
        pkcs12.load(null, password);
        
        String alias = "myPublicKey";
        pkcs12.setCertificateEntry(alias, certificate);
        //pkcs12.setKeyEntry("myPublicKey", publicKey, password, new Certificate[] {certificate});
        try(FileOutputStream fileOutputStream = new FileOutputStream(SELF_SIGNED_PUBLIC_PKCS12_FILE_PATH)) {
            pkcs12.store(fileOutputStream, password);
        }
    }
}