In this article I am going to talk about creating SSL certificates in java program using bouncy castle API.
Bouncy castle is a lightweight cryptography API. It is implementation of Java Cryptography Extension(JCE) and the Java Cryptography Architecture.(JCA).
I will create very basic certificates which contains only necessary properties.You can explore the API for more operations and properties you can apply to a certificate.
Please import below dependency in your code.
I am performing below steps in the code:
Steps:
1) Creating a self signed root certificate.
2) Creating an intermediate certificate signed by root certificate created in step 1.
3) Creating an end user certificate signed by intermediate certificate created in step 2.
Code:
Here you can see, for rootCA I am using its own private key to sign the certificate. For intermedCA I am using rootCA private key for signing. For end user certificate I am using IntermedCA private key for signing.
In real life also you can see a chain of certificate similar to this. Open any certificate of HTTPS connection from browser and observe the certificate chain and properties of each certificate.
"SHA256withRSA" is a signature algorithm I am using it for signing the certificates.
In keyUsage "keyCertSign" restricts the certificate usage only for signing other certificates. While "digitalSignature" usage needed for SSL client , our web browser, for example which uses that certificate for entity authentication and data origin authentication with integrity.
The "true" flag in BasicConstraints mark the certificate as a CA certificate which can sign other certificates. "false" flag mark the certificate as end entity of the certificate chain.
As an out come of this program you will have 3 certificates in the specified file path.
Now open the rootCA first:
You can see certificate not trusted message. So lets add this certificate in trusted root certificate store
1) Click on "Install certificate" button.
2) select "Local Machine" , click next
3) select second option of "place all certificates in the following store"
4) Browse and select "Trusted Root Certification Authority"
5) Click "Next" than click "Finish".
6) Import successful.
Same thing perform for "Intermed CA" certificate , with only change in step 4: Browse and select "Intermediate Certification Authority".
Now close the certificate and reopen it.
Lets examine each certificate now:
1) RootCA
2)Intermed CA
3) End user certificate
There are other ways to create certificates and certificate chain. For e.g: java "keytool" command or using tool like "keystore explorer"....
But Many times you have situation where you have to do certificate operations from program only.
So this will be very helpful at that time.
In next article I will post more on the topic of certificates and the operations you can perform using bouncy castle from java program.
Please post your comments and doubts!!!
Bouncy castle is a lightweight cryptography API. It is implementation of Java Cryptography Extension(JCE) and the Java Cryptography Architecture.(JCA).
I will create very basic certificates which contains only necessary properties.You can explore the API for more operations and properties you can apply to a certificate.
Please import below dependency in your code.
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.55</version>
</dependency>
<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
</dependency>
I am performing below steps in the code:
Steps:
1) Creating a self signed root certificate.
2) Creating an intermediate certificate signed by root certificate created in step 1.
3) Creating an end user certificate signed by intermediate certificate created in step 2.
Code:
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.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.joda.time.DateTime;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Random;
public class App {
public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, OperatorCreationException, InvalidKeyException, NoSuchProviderException, SignatureException, UnrecoverableKeyException {
Security.addProvider(new BouncyCastleProvider());
// Create self signed Root CA certificate
KeyPair rootCAKeyPair = generateKeyPair();
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
new X500Name("CN=rootCA"), // issuer authority
BigInteger.valueOf(new Random().nextInt()), //serial number of certificate
DateTime.now().toDate(), // start of validity
new DateTime(2025, 12, 31, 0, 0, 0, 0).toDate(), //end of certificate validity
new X500Name("CN=rootCA"), // subject name of certificate
rootCAKeyPair.getPublic()); // public key of certificate
// key usage restrictions
builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign));
builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
X509Certificate rootCA = new JcaX509CertificateConverter().getCertificate(builder
.build(new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").
build(rootCAKeyPair.getPrivate()))); // private key of signing authority , here it is self signed
saveToFile(rootCA, "D:\\rootCA.cer");
//create Intermediate CA cert signed by Root CA
KeyPair intermedCAKeyPair = generateKeyPair();
builder = new JcaX509v3CertificateBuilder(
rootCA, // here rootCA is issuer authority
BigInteger.valueOf(new Random().nextInt()), DateTime.now().toDate(),
new DateTime(2025, 12, 31, 0, 0, 0, 0).toDate(),
new X500Name("CN=IntermedCA"), intermedCAKeyPair.getPublic());
builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign));
builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
X509Certificate intermedCA = new JcaX509CertificateConverter().getCertificate(builder
.build(new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").
build(rootCAKeyPair.getPrivate())));// private key of signing authority , here it is signed by rootCA
saveToFile(intermedCA, "D:\\intermedCA.cer");
//create end user cert signed by Intermediate CA
KeyPair endUserCertKeyPair = generateKeyPair();
builder = new JcaX509v3CertificateBuilder(
intermedCA, //here intermedCA is issuer authority
BigInteger.valueOf(new Random().nextInt()), DateTime.now().toDate(),
new DateTime(2025, 12, 31, 0, 0, 0, 0).toDate(),
new X500Name("CN=endUserCert"), endUserCertKeyPair.getPublic());
builder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature));
builder.addExtension(Extension.basicConstraints, false, new BasicConstraints(false));
X509Certificate endUserCert = new JcaX509CertificateConverter().getCertificate(builder
.build(new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").
build(intermedCAKeyPair.getPrivate())));// private key of signing authority , here it is signed by intermedCA
saveToFile(endUserCert, "D:\\endUserCert.cer");
}
private static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
kpGen.initialize(2048, new SecureRandom());
return kpGen.generateKeyPair();
}
private static void saveToFile(X509Certificate certificate, String filePath) throws IOException, CertificateEncodingException {
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write(certificate.getEncoded());
fileOutputStream.flush();
fileOutputStream.close();
}
}
Here you can see, for rootCA I am using its own private key to sign the certificate. For intermedCA I am using rootCA private key for signing. For end user certificate I am using IntermedCA private key for signing.
In real life also you can see a chain of certificate similar to this. Open any certificate of HTTPS connection from browser and observe the certificate chain and properties of each certificate.
"SHA256withRSA" is a signature algorithm I am using it for signing the certificates.
In keyUsage "keyCertSign" restricts the certificate usage only for signing other certificates. While "digitalSignature" usage needed for SSL client , our web browser, for example which uses that certificate for entity authentication and data origin authentication with integrity.
The "true" flag in BasicConstraints mark the certificate as a CA certificate which can sign other certificates. "false" flag mark the certificate as end entity of the certificate chain.
As an out come of this program you will have 3 certificates in the specified file path.
Now open the rootCA first:
You can see certificate not trusted message. So lets add this certificate in trusted root certificate store
1) Click on "Install certificate" button.
2) select "Local Machine" , click next
3) select second option of "place all certificates in the following store"
4) Browse and select "Trusted Root Certification Authority"
5) Click "Next" than click "Finish".
6) Import successful.
Same thing perform for "Intermed CA" certificate , with only change in step 4: Browse and select "Intermediate Certification Authority".
Now close the certificate and reopen it.
Lets examine each certificate now:
1) RootCA
2)Intermed CA
3) End user certificate
There are other ways to create certificates and certificate chain. For e.g: java "keytool" command or using tool like "keystore explorer"....
But Many times you have situation where you have to do certificate operations from program only.
So this will be very helpful at that time.
In next article I will post more on the topic of certificates and the operations you can perform using bouncy castle from java program.
Please post your comments and doubts!!!
How do i create clientKey.der file along with endusercert file
ReplyDeleteany example in c#?
ReplyDeleteif i had any money i'd donate it all to you.
ReplyDeleteThank you so much!