In previous post, we have introduced the use of Certificate and how to generate self signed certificate using Java. In this post, we will show you how to generate a certificate chain. Sometimes we may only have a certificate request or we don't have a trusted certificate which can be used for business. Now we need to have a trusted CA to sign our certificate so that it can be used on SSL communications.
To generate a certificate chain, we may first have our own certificate(A), then we may use other certificate(B) and its associated private key to sign the certificate we have, then we will use another certificate(C) and its associated private key to sign certificate B...this process will continue until you have a trusted root certificate to sign the previous certificate. Then you have a certificate chain. This trusted root CA may be from VeriSign or other CAs.
In Java, we can use below codes to create certificate chain.
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
|
import
java.security.Principal;
import
java.security.PrivateKey;
import
java.security.cert.X509Certificate;
import
javax.security.cert.Certificate;
import
sun.security.x509.BasicConstraintsExtension;
import
sun.security.x509.CertAndKeyGen;
import
sun.security.x509.CertificateExtensions;
import
sun.security.x509.CertificateIssuerName;
import
sun.security.x509.X500Name;
import
sun.security.x509.X509CertImpl;
import
sun.security.x509.X509CertInfo;
public
class
CertificateChainGeneration {
public
static
void
main(String[] args){
try
{
//Generate ROOT certificate
CertAndKeyGen keyGen=
new
CertAndKeyGen(
"RSA"
,
"SHA1WithRSA"
,
null
);
keyGen.generate(
1024
);
PrivateKey rootPrivateKey=keyGen.getPrivateKey();
X509Certificate rootCertificate = keyGen.getSelfCertificate(
new
X500Name(
"CN=ROOT"
), (
long
)
365
*
24
*
60
*
60
);
//Generate intermediate certificate
CertAndKeyGen keyGen1=
new
CertAndKeyGen(
"RSA"
,
"SHA1WithRSA"
,
null
);
keyGen1.generate(
1024
);
PrivateKey middlePrivateKey=keyGen1.getPrivateKey();
X509Certificate middleCertificate = keyGen1.getSelfCertificate(
new
X500Name(
"CN=MIDDLE"
), (
long
)
365
*
24
*
60
*
60
);
//Generate leaf certificate
CertAndKeyGen keyGen2=
new
CertAndKeyGen(
"RSA"
,
"SHA1WithRSA"
,
null
);
keyGen2.generate(
1024
);
PrivateKey topPrivateKey=keyGen2.getPrivateKey();
X509Certificate topCertificate = keyGen2.getSelfCertificate(
new
X500Name(
"CN=TOP"
), (
long
)
365
*
24
*
60
*
60
);
rootCertificate = createSignedCertificate(rootCertificate,rootCertificate,rootPrivateKey);
middleCertificate = createSignedCertificate(middleCertificate,rootCertificate,rootPrivateKey);
topCertificate = createSignedCertificate(topCertificate,middleCertificate,middlePrivateKey);
X509Certificate[] chain =
new
X509Certificate[
3
];
chain[
0
]=topCertificate;
chain[
1
]=middleCertificate;
chain[
2
]=rootCertificate;
}
catch
(Exception ex){
ex.printStackTrace();
}
}
private
static
X509Certificate createSignedCertificate(X509Certificate cetrificate,X509Certificate issuerCertificate,PrivateKey issuerPrivateKey){
try
{
Principal issuer = issuerCertificate.getSubjectDN();
String issuerSigAlg = issuerCertificate.getSigAlgName();
byte
[] inCertBytes = cetrificate.getTBSCertificate();
X509CertInfo info =
new
X509CertInfo(inCertBytes);
info.set(X509CertInfo.ISSUER,
new
CertificateIssuerName((X500Name) issuer));
//No need to add the BasicContraint for leaf cert
if
(!cetrificate.getSubjectDN().getName().equals(
"CN=TOP"
)){
CertificateExtensions exts=
new
CertificateExtensions();
BasicConstraintsExtension bce =
new
BasicConstraintsExtension(
true
, -
1
);
exts.set(BasicConstraintsExtension.NAME,
new
BasicConstraintsExtension(
false
, bce.getExtensionValue()));
info.set(X509CertInfo.EXTENSIONS, exts);
}
X509CertImpl outCert =
new
X509CertImpl(info);
outCert.sign(issuerPrivateKey, issuerSigAlg);
return
outCert;
}
catch
(Exception ex){
ex.printStackTrace();
}
return
null
;
}
}
|
Here we first create three self signed certificates and their associated private keys. Then we use one certificate and its private key to sign another certificate.
Note that the certificate except the leaf cert in a workable certificate chain should contain an CA extension to indicate the certificate is a CA certificate. So you will see that we will add CA extension to the certificate when we sign a certificate in createSignedCertificate().
In next post, we will show you how to store the certificate and keys into different types of keystores such as JKS, PKCS12