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
|
/*
* This file is part of cert-signer
* Copyright (c) 2024 Paolo Lulli.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.lulli.certsigner.ca;
import net.lulli.certsigner.Settings;
import net.lulli.certsigner.util.ValidityUtil;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
public class CertificateIssue {
private CertificateIssue(){}
public static X509Certificate rootCertificate(
PublicKey publicKey,
PrivateKey privateKey,
String subject)
throws Exception {
BigInteger rootSerialNum = new BigInteger(Long.toString(new SecureRandom().nextLong()));
X500Name rootCertIssuer = new X500Name(subject);
X500Name rootCertSubject = rootCertIssuer;
ContentSigner rootCertContentSigner = new JcaContentSignerBuilder(Settings.SIGNATURE_ALGORITHM).setProvider(Settings.BC_PROVIDER).build(privateKey);
X509v3CertificateBuilder rootCertBuilder =
new JcaX509v3CertificateBuilder(rootCertIssuer, rootSerialNum, ValidityUtil.yesterday(), ValidityUtil.plusYears(1), rootCertSubject, publicKey);
JcaX509ExtensionUtils rootCertExtUtils = new JcaX509ExtensionUtils();
rootCertBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(true));
rootCertBuilder.addExtension(Extension.subjectKeyIdentifier, false, rootCertExtUtils.createSubjectKeyIdentifier(publicKey));
X509CertificateHolder rootCertHolder = rootCertBuilder.build(rootCertContentSigner);
return new JcaX509CertificateConverter().setProvider(Settings.BC_PROVIDER).getCertificate(rootCertHolder);
}
public static X509Certificate clientCertificate(
PrivateKey privateKey,
String certificateSubject,
X509Certificate rootCert,
PKCS10CertificationRequest csr
) {
try {
X500Name issuedCertSubject = new X500Name(certificateSubject);
BigInteger issuedCertSerialNum = new BigInteger(Long.toString(new SecureRandom().nextLong()));
//PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(issuedCertSubject, issuedCertKeyPair.getPublic());
JcaContentSignerBuilder csrBuilder = new JcaContentSignerBuilder(Settings.SIGNATURE_ALGORITHM).setProvider(Settings.BC_PROVIDER);
ContentSigner csrContentSigner = csrBuilder.build(privateKey);
X509v3CertificateBuilder issuedCertBuilder = new X509v3CertificateBuilder(new X500Name("CN=root-cert"), issuedCertSerialNum, ValidityUtil.yesterday(), ValidityUtil.plusYears(1), csr.getSubject(), csr.getSubjectPublicKeyInfo());
JcaX509ExtensionUtils issuedCertExtUtils = new JcaX509ExtensionUtils();
issuedCertBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false));
issuedCertBuilder.addExtension(Extension.authorityKeyIdentifier, false, issuedCertExtUtils.createAuthorityKeyIdentifier(rootCert));
issuedCertBuilder.addExtension(Extension.subjectKeyIdentifier, false, issuedCertExtUtils.createSubjectKeyIdentifier(csr.getSubjectPublicKeyInfo()));
issuedCertBuilder.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.keyEncipherment));
// Add DNS name is cert is to used for SSL
/*
issuedCertBuilder.addExtension(Extension.subjectAlternativeName, false, new DERSequence(new ASN1Encodable[]{
new GeneralName(GeneralName.dNSName, "mydomain.local"),
new GeneralName(GeneralName.iPAddress, "127.0.0.1")
}));
*/
X509CertificateHolder issuedCertHolder = issuedCertBuilder.build(csrContentSigner);
return new JcaX509CertificateConverter().setProvider(Settings.BC_PROVIDER).getCertificate(issuedCertHolder);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage());
}
}
}
|