Generate certificate in Java -- Certificate chain

  Pi Ke        2014-07-30 08:24:52       42,061        2    

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.

import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
 
import java.util.Arrays;

import javax.security.cert.Certificate;
 

import sun.security.x509.BasicConstraintsExtension;
import sun.security.tools.keytool.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;

//Tested in jdk1.8.0_40
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;   
            
            System.out.println(Arrays.toString(chain));
        }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, (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

JAVA  CERTIFICATE CHAIN  CREATION  PURE JAVA 

       

  RELATED


  2 COMMENTS


Rohit [Reply]@ 2015-04-10 08:07:10

While running i am geeting this type of error can you help me 

CertificateChainGeneration.java:7: warning: BasicConstraintsExtension is interna
l proprietary API and may be removed in a future release
import sun.security.x509.BasicConstraintsExtension;
^
CertificateChainGeneration.java:8: error: cannot find symbol
import sun.security.x509.CertAndKeyGen;
^
symbol: class CertAndKeyGen
location: package sun.security.x509
CertificateChainGeneration.java:9: warning: CertificateExtensions is internal pr
oprietary API and may be removed in a future release
import sun.security.x509.CertificateExtensions;
^
CertificateChainGeneration.java:10: warning: CertificateIssuerName is internal p
roprietary API and may be removed in a future release
import sun.security.x509.CertificateIssuerName;
^
CertificateChainGeneration.java:11: warning: X500Name is internal proprietary AP
I and may be removed in a future release
import sun.security.x509.X500Name;
^
CertificateChainGeneration.java:12: warning: X509CertImpl is internal proprietar
y API and may be removed in a future release
import sun.security.x509.X509CertImpl;
^
CertificateChainGeneration.java:13: warning: X509CertInfo is internal proprietar
y API and may be removed in a future release
import sun.security.x509.X509CertInfo;
^
CertificateChainGeneration.java:19: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class CertificateChainGeneration
CertificateChainGeneration.java:19: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class CertificateChainGeneration
CertificateChainGeneration.java:23: warning: X500Name is internal proprietary AP
I and may be removed in a future release
X509Certificate rootCertificate = keyGen.getSelfCertificate(new X500
Name("CN=ROOT"), (long) 365 * 24 * 60 * 60);
^
CertificateChainGeneration.java:26: error: cannot find symbol
CertAndKeyGen keyGen1=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class CertificateChainGeneration
CertificateChainGeneration.java:26: error: cannot find symbol
CertAndKeyGen keyGen1=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class CertificateChainGeneration
CertificateChainGeneration.java:30: warning: X500Name is internal proprietary AP
I and may be removed in a future release
X509Certificate middleCertificate = keyGen1.getSelfCertificate(new X
500Name("CN=MIDDLE"), (long) 365 * 24 * 60 * 60);
^

CertificateChainGeneration.java:33: error: cannot find symbol
CertAndKeyGen keyGen2=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class CertificateChainGeneration
CertificateChainGeneration.java:33: error: cannot find symbol
CertAndKeyGen keyGen2=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class CertificateChainGeneration
CertificateChainGeneration.java:37: warning: X500Name is internal proprietary AP
I and may be removed in a future release
X509Certificate topCertificate = keyGen2.getSelfCertificate(new X500
Name("CN=TOP"), (long) 365 * 24 * 60 * 60);
^
CertificateChainGeneration.java:58: warning: X509CertInfo is internal proprietar
y API and may be removed in a future release
X509CertInfo info = new X509CertInfo(inCertBytes);
^
CertificateChainGeneration.java:58: warning: X509CertInfo is internal proprietar
y API and may be removed in a future release
X509CertInfo info = new X509CertInfo(inCertBytes);
^
CertificateChainGeneration.java:59: warning: X509CertInfo is internal proprietar
y API and may be removed in a future release
info.set(X509CertInfo.ISSUER, new CertificateIssuerName((X500Name) i
ssuer));
^
CertificateChainGeneration.java:59: warning: CertificateIssuerName is internal p
roprietary API and may be removed in a future release
info.set(X509CertInfo.ISSUER, new CertificateIssuerName((X500Name) i
ssuer));
^
CertificateChainGeneration.java:59: warning: X500Name is internal proprietary AP
I and may be removed in a future release
info.set(X509CertInfo.ISSUER, new CertificateIssuerName((X500Name) i
ssuer));
^
CertificateChainGeneration.java:63: warning: CertificateExtensions is internal p
roprietary API and may be removed in a future release
CertificateExtensions exts=new CertificateExtensions();
^
CertificateChainGeneration.java:63: warning: CertificateExtensions is internal p
roprietary API and may be removed in a future release
CertificateExtensions exts=new CertificateExtensions();
^
CertificateChainGeneration.java:64: warning: BasicConstraintsExtension is intern
al proprietary API and may be removed in a future release
BasicConstraintsExtension bce = new BasicConstraintsExtension(tr
ue, -1);
^
CertificateChainGeneration.java:64: warning: BasicConstraintsExtension is intern
al proprietary API and may be removed in a future release
BasicConstraintsExtension bce = new BasicConstraintsExtension(tr
ue, -1);
^
CertificateChainGeneration.java:65: warning: BasicConstraintsExtension is intern
al proprietary API and may be removed in a future release
exts.set(BasicConstraintsExtension.NAME,new BasicConstraintsExte
nsion(false, bce.getExtensionValue()));
^
CertificateChainGeneration.java:65: warning: BasicConstraintsExtension is intern
al proprietary API and may be removed in a future release
exts.set(BasicConstraintsExtension.NAME,new BasicConstraintsExte
nsion(false, bce.getExtensionValue()));
^
CertificateChainGeneration.java:66: warning: X509CertInfo is internal proprietar
y API and may be removed in a future release
info.set(X509CertInfo.EXTENSIONS, exts);
^
CertificateChainGeneration.java:69: warning: X509CertImpl is internal proprietar
y API and may be removed in a future release
X509CertImpl outCert = new X509CertImpl(info);
^
CertificateChainGeneration.java:69: warning: X509CertImpl is internal proprietar
y API and may be removed in a future release
X509CertImpl outCert = new X509CertImpl(info);
^
7 errors
23 warnings

owing error

Pi Ke [Reply]@ 2015-04-10 11:30:17

There are some new changes in the latest Java 8. Have updated the code in the post. You can use the new code now.

Please remember to compile it using :

javac -XDignore.symbol.file CertificateChainGeneration.java



  RANDOM FUN

Concurrency Programming with Ruby