Jan 31, 2010

How to generate Self-Signed Certificates programmatically ?

The most common approach of generating a self-signed certificate is using the Java Keytool. But there may be situations where the requirement is to generate self-signed certificates programmatically.

It is possible to do this by programmatically invoking the keytool(using Runtime.exec) which is not a very promising approach. And also it is possible to use the Sun's proprietary classes used inside the Keytool to do this. But there is no documented API on these classes.

One clean approach of programmatically generating these self-signed certificates is through the Bouncy Castle API. I will walk you through the important steps of the above process.

To start with this, you need to have the Bouncy Castle jar in your classpath.(You can download it from here)

First you need to generate a key pair. We are using "RSA" public-key cryptography algorithm and a key size of 1024.

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair KPair = keyPairGenerator.generateKeyPair();

Then instantiate an X.509 cert. generator.
X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();

Now start creating the certificate. Serial number, issuer, validity period and Subject are set here.
v3CertGen.setSerialNumber(BigInteger.valueOf(new SecureRandom().nextInt()));
        v3CertGen.setIssuerDN(new X509Principal("CN=" + domainName + ", OU=None, O=None L=None, C=None"));
        v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30));
        v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 365*10)));
        v3CertGen.setSubjectDN(new X509Principal("CN=" + domainName + ", OU=None, O=None L=None, C=None"));

Then set the public key of the key pair and the signing algorithm to the cert generator.
v3CertGen.setPublicKey(KPair.getPublic());
v3CertGen.setSignatureAlgorithm("MD5WithRSAEncryption"); 

Now you can generate the certificate.
X509Certificate PKCertificate = v3CertGen.generateX509Certificate(KPair.getPrivate());

And store it in a file.
FileOutputStream fos = new FileOutputStream("/path/to/testCert.cert");
fos.write(PKCertificate.getEncoded());
fos.close();

You can view this cert using the keytool.
keytool -printcert -file /path/to/cert

Upto now we have created a key-pair and generated a X.509 certificate which contains the public key. Now we have to import the generated private key to a key store. Importing the private key to a key store is straight forward.

Load the key store to memory.

KeyStore privateKS = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("/path/to/sample-key-store.jks");
privateKS.load(fis, "keyStorePass".toCharArray());

Import the private key to the key store.

privateKS.setKeyEntry("sample.alias", KPair.getPrivate(),
                   new char[]{'e', 'n', 't', 'r', 'y', 'p', 'a', 's', 's'},
                   new java.security.cert.Certificate[]{PKCertificate});

Write the key store back to disk.

privateKS.store( new FileOutputStream(keystoreFile), "keyStorePass".toCharArray());

You can try this with different parameters like key sizes, signing algorithms, etc.

9 comments:

Kaushal Parikh said...

Great work, I am searching it from many days

ahmed said...

can u plz tell what the variable keystoreFile in last section mean as in the whole scenario you have not used this variable.

Thilina Mahesh Buddhika said...

Hi Ahmed,

It is the location of the file system to where the key store should be written. So it is a file path (as a string).

HTH.

/thilina

Vismaya said...

Hi,

Generating key pair and certificate is working fine. But i am getting "FileNotFoundException" while loading key store to memory "FileInputStream fis = new FileInputStream("/path/to/sample-key-store.jks");" ... plz let me know do i need to create ant .jks file or it should be created by code. if i need to create, how?

Thanks,
Guru

Cyrille Le Clerc said...

Hi,

Here is a sample on how to generate OpenSSL style ".pem" files from the X509 certificate and the Private key :
http://code.google.com/p/xebia-france/wiki/HowToGenerateaSelfSignedX509CertificateInJava

Hope this helps,

Cyrille

James Nirmal said...

I saw some link as same
http://www.mayrhofer.eu.org/create-x509-certs-in-java

DARAVATH NAGESH said...

Hello Mahesh.. i have one code for generating self signed certificate. but when i generat a certificate for user by signng root private key (self signed certificate)certifcate chin shows error.. can u plz send me the full code of you.. it will help full for e...my mail id: nagesh910@gmail.com

Anon said...

One thing about your snippet.

Please use SHA1 as the certificate signing algorithm because MD5 has been proven to be compromised in 2008. By that it is possible to create another certificate with same Md5 hash but different entirely.

Markus Kramer said...

I believe there is a small bug. The X509 specification says "CAs MUST force the serialNumber to be a non-negative integer" which is violated here. I'm using BigInteger.valueOf(new SecureRandom().nextInt(Integer.MAX_VALUE)) instead.

Post a Comment