Generate certificate in Java -- Self signed certificate

  Pi Ke        2014-07-30 07:42:18       59,078        21          English  简体中文  Tiếng Việt 

This is the first post in this series which I will show you how to generate SSL certificate in Java programmatically. Certificates are frequently used in SSL communication which requires the authentication of server to client. This is to make the client to trust that the server is actually the one it claims. Certificates are really important on the Internet. All HTTPS communications on the Internet need the server side to present their certificates signed by trusted CAs.

The basic flow of a request generation is that we first use some tool to generate the certificate request, this certificate request will be sent to the trusted CAs to sign, after signing the certificate, this certificate will be sent to the requester. The requester may install the certificate on their server thereafter.

There are lots of libraries you can use to complete these steps. For example openssl, Java keytool, iKeyman. Also in Java, you can write the code yourself to generate the certificate.

If you are using keytool, then below command can help you create a private key and its associated self signed certificate.

keytool -genkeypair -alias rsakey -keyalg rsa -storepass passphrase -keystore mytestkeys.jks -storetype JKS -dname "CN=ROOT"

In this post, we will first show the easiest way to create a usable certificate-- self signed certificate. A self signed certificate is that the issuer of the certificate is the subject of the certificate, i.e, you sign your own certificate with your own private key.

In Java, there is a class named CertAndKeyGen which can be used to generate keys and certificates. Generate a pair of keys, and provide access to them. This class is provided primarily for ease of use. This provides some simple certificate management functionality. Specifically, it allows you to create self-signed X.509 certificates as well as PKCS 10 based certificate signing requests.

Below is the code snippet to generate a self signed certificate:

import java.security.cert.X509Certificate;

import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;

public class SelfSignedCertificateGeneration {
	public static void main(String[] args){
		try{
			CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
			keyGen.generate(1024);
			
			//Generate self signed certificate
			X509Certificate[] chain=new X509Certificate[1];
			chain[0]=keyGen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600);
			
			System.out.println("Certificate : "+chain[0].toString());
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
}

Let's have a look at what the certificate data is :

Certificate : [
[
  Version: V3
  Subject: CN=ROOT
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 114391309107542773913020327258312183039826043488144930936432429784366769808118582358673188617553493179715429490538390339548553158770231498533107085203543482991384318715251748594629731873902297622858400215317090155179482056595085606008433735465924998820797111761561551868239613864908732016915661242341876829949
  public exponent: 65537
  Validity: [From: Wed Jul 30 21:06:29 SGT 2014,
               To: Thu Jul 30 21:06:29 SGT 2015]
  Issuer: CN=ROOT
  SerialNumber: [    0b000b59]

]
  Algorithm: [SHA1withRSA]
  Signature:
0000: 94 F9 DD 3D 95 4F BC 63   A6 A3 09 9E 63 EF CA 91  ...=.O.c....c...
0010: 97 55 C1 9E B2 12 52 13   7A 7B 73 B1 B8 ED A8 EF  .U....R.z.s.....
0020: F5 1C EB 27 71 F2 60 22   BC E9 0B 01 1D 70 C1 5E  ...'q.`".....p.^
0030: D6 D1 E8 AB 4D 2C CC F6   70 2B 7A D4 37 95 7A CC  ....M,..p+z.7.z.
0040: E2 A1 FE F9 3F 11 18 FD   36 CB 22 62 FB 5A E2 5D  ....?...6."b.Z.]
0050: E6 6C BF 61 C7 1F 03 BA   FE B5 85 47 DD 7F C0 CB  .l.a.......G....
0060: F3 F1 A0 79 35 0F 2A F7   79 0E 1E 79 A1 11 2E 44  ...y5.*.y..y...D
0070: 85 10 F2 B3 9F 07 F0 24   D3 1A AC 28 0C CE 4B 04  .......$...(..K.

]

From the certificate data, you can see that the Subject and Issuer is the same.

In the next post, I will show you how to create a certificate chain using Java programmatically.

JAVA  CERTIFICATE  X509 

           

  RELATED


  21 COMMENTS


Esmeralda
Jul 30, 2014 at 5:57 pm
The interesting part of learning the counter jungling whish is most of the time not taught on other guides is the ability to leave players far far behind. He knelt down to her level of eyesight, and sighed. I spared you the collar and helped develop your natural talents with the sword.
NightCat
Oct 24, 2014 at 10:57 am

Great start for developers who are working in security field

Rohit
Apr 10, 2015 at 8:20 am

While running outside eclipse i am getting following error 

SelfSignedCertificateGeneration.java:3: error: package sun.security.tools.keytoo
l does not exist
import sun.security.tools.keytool.CertAndKeyGen;
^
SelfSignedCertificateGeneration.java:4: warning: X500Name is internal proprietar
y API and may be removed in a future release
import sun.security.x509.X500Name;
^
SelfSignedCertificateGeneration.java:9: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class SelfSignedCertificateGeneration
SelfSignedCertificateGeneration.java:9: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class SelfSignedCertificateGeneration
SelfSignedCertificateGeneration.java:14: warning: X500Name is internal proprieta
ry API and may be removed in a future release
chain[0]=keyGen.getSelfCertificate(new X500Name("CN=ROOT"), (long)36
5*24*3600);
^
3 errors
2 warnings

D:\JAVA Learning\Program\Rohit>java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b26)
Java HotSpot(TM) Client VM (build 25.40-b25, mixed mode, sharing)

Pi Ke
Apr 10, 2015 at 11:17 am

In latest Java 8, there are some changes with respect to the source code structure. Now you need to use below command to compile the source code to remove the errors ad warnings:

javac -XDignore.symbol.file SelfSignedCertificateGeneration.java

When javac is compiling code it doesn't link against rt.jar by default in latest Java 8. Instead it uses special symbol file lib/ct.sym with class stubs. The option -XDignore.symbol.file is to ignore the symbol file so that it will link against rt.jar.

For this change, please refer to JDK JEP 201 : Modular Source Code.

Rohit
Apr 10, 2015 at 12:05 pm

Thanks for your reply. And its working you saved me 

One question how to compile with maven

Pi Ke
Apr 10, 2015 at 9:51 pm

Put below into your pom.xml and then mvn -X clean compile.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
                <source>1.8</source> 
                <target>1.8</target> 
                <fork>true</fork>
                <compilerArgs>
                          <arg>-XDignore.symbol.file</arg>
                     </compilerArgs>
              </configuration>
         </plugin>
     </plugins>
</build>

Note prior to maven-compiler-plugin 3.1, you should use <compilerArgument>-XDignore.symbol.file</compilerArgument> instead.

Anonymous
Aug 2, 2017 at 12:56 am

This is not working facing the same errors

C:\Users\z018653>javac -XDignore.symbol.file SelfSignedCertificateGeneration.java

d:\SelfSignedCertificate

Generation.java:5: error: package sun.security.tools.keytool does not exist

import sun.security.tools.keytool.CertAndKeyGen;

                                 ^

d:\SelfSignedCertificate

Generation.java:11: error: cannot find symbol

            CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);

            ^

  symbol:   class CertAndKeyGen

  location: class SelfSignedCertificateGeneration

d:\SelfSignedCertificate

Generation.java:11: error: cannot find symbol

            CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);

                                     ^

  symbol:   class CertAndKeyGen

  location: class SelfSignedCertificateGeneration

3 errors

 

Ke Pi
Aug 2, 2017 at 11:01 am

Can you post your Java version?

Sree
Aug 2, 2017 at 11:19 pm
@Ke Pi

I tried with Java 1.7, 1.6 and also with 1.8

Ke Pi
Aug 3, 2017 at 10:00 am
@Sree

I just tried on my machine with Java 8 and it works. See below:

C:\Users\pike\workspace\TryBase\src>java -version

java version "1.8.0_60"

Java(TM) SE Runtime Environment (build 1.8.0_60-b27)

Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

C:\Users\pike\workspace\TryBase\src>javac -XDignore.symbol.file SelfSignedCertificateGeneration.java

C:\Users\pike\workspace\TryBase\src>

Can you try this version?

Rohit
Apr 10, 2015 at 10:02 pm

Thank you very much 

ekremney
May 17, 2015 at 6:35 pm

This shouldn't be that easy

aakash
Sep 1, 2015 at 7:24 am

I am using a server - client architecture, server has self signed certificate, through the eclipse i am calling REST API to the server but i am getting the error 

Exception: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

 

can you please help me.

Pi Ke
Sep 1, 2015 at 9:58 am

Well, Subject Alternative Names(SAN) allow you to specify a list of host names to be protected by a single SSL certificate. It's an X509 certificate extension. So you need to add an SAN extension in your generated certificate.

If you are in a development environment where you are doing some testing, you can implement below workaround in your code:

static {
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
        {
            public boolean verify(String hostname, SSLSession session)
            {
                // ip address of the service URL
                if (hostname.equals("<ip_address>"))
                    return true;
                return false;
            }
        });
}

This will add a default hostname verifier which you can determine which host to trust here.

Anonymous
Oct 16, 2019 at 3:18 am

Hi,

How can I compute the size of the Self Signed Certificate Generation.

Thanks

Ke Pi
Oct 16, 2019 at 8:33 am

Size? Can you be more specific?

David
Oct 17, 2019 at 10:21 am

Hello;

I will begin by thanking you for answering me. Concerning my question I would like to know how to get the size (in bit or byte) of the entire self signed certificate. I mean the following certificate:

import java.security.cert.X509Certificate;
 
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;
 
public class SelfSignedCertificateGeneration {
    public static void main(String[] args){
        try{
            CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
            keyGen.generate(1024);
             
            //Generate self signed certificate
            X509Certificate[] chain=new X509Certificate[1];
            chain[0]=keyGen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600);
             
            System.out.println("Certificate : "+chain[0].toString());
        }catch
Ke Pi
Oct 19, 2019 at 8:46 am

U just need to get its encoded data in byte array representive and get its size or save the encoded data into a certificate file and then should be using File logic to get its size.

Anonymous
Oct 7, 2020 at 6:29 am

Can anyone please provide complete code to sign a csr (which I have received from a client) and generate certificate for the client.

It's really urgent..please consider.

Anonymous
Nov 2, 2020 at 11:14 pm

Where can we find the keypair which is generated here?...where is it stored after generation??



  PROGRAMMER HUMOR

So where to go


  SUPPORT US