Generate public key and private key with OpenSSL in Windows 10

How to read .pem file to get public and private keys ?

This tutorial will guide you on how to read .pem file to get public and private keys. Let’s see how to generate .pem key files using openssl commands and how to write java code to read .pem file and get public and private keys.

Generate .pem key file using OpenSSL

The following are the commands that I have used to generate .pem key files.

To generate RSA private key, 2048 bit long run the following command.

> openssl genrsa -out private.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
..........................+++++
...........+++++
e is 65537 (0x010001)

And to generate public key run the following command. This command will extract the public key from the private.pem file and output the public key in to a file named “public.pem”

> openssl rsa -in private.pem -outform PEM -pubout -out public.pem
writing RSA key

Note, you need to convert the “private.pem” private key which is in PKCS#1 format to PKCS#8 format. Therefore Java code can read PKCS#8 key format. Otherwise you will get Java Exception “java.security.spec.InvalidKeySpecException”.

You need to run the following command, which will output private key in DER format which Java code can read with the help of  “PKCS8EncodedKeySpec” interface.

> openssl pkcs8 -topk8 -inform PEM -outform DER -in private.pem -out private.der -nocrypt

Next, let’s see how to read .pem file to get public and private keys in the next section.

Read .pem file to get public and private keys

To read .pem file I have written a util class called PemFile.java which will be used to handle pem file I/O operations. This util class uses BouncyCastle library.

PemFile.java

package com.sneppets.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

public class PemFile {
	
	private PemObject pemObject;
	 
	public PemFile(String filename) throws FileNotFoundException, IOException {
		PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream(filename)));
		try {
			this.pemObject = pemReader.readPemObject();
		} finally {
			pemReader.close();
		}
	}
 
	public PemObject getPemObject() {
		return pemObject;
	}

}

Our getPublicKey() method is going to use PemFile.java util to read public key from public.pem file.

The below Java class “PemToPublicPrivateKeyExample.java” has two methods getPublicKey() and getPrivateKey() which will help you to read .pem key file to get public and private keys.

package com.sneppets.util;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.apache.commons.codec.binary.Base64;

public class PemToPublicPrivateKeyExample {
	
	public static void main (String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
		
		RSAPublicKey publicKey = (RSAPublicKey) getPublicKey("public.pem");
		System.out.println("Public Key: " + publicKey);
		
		RSAPrivateKey privateKey = (RSAPrivateKey) getPrivateKey("private.der");
		System.out.println("Private Key: " + privateKey);
	}
	
	private static PublicKey getPublicKey(String filename) throws FileNotFoundException, IOException, NoSuchAlgorithmException, InvalidKeySpecException {
		
		//If you don't want to use PemFile.java util uncomment this logic
		//String publicKeyPem = getKey(filename);		
		//publicKeyPem = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----\n", "");
		//publicKeyPem = publicKeyPem.replace("-----END PUBLIC KEY-----", "");
	    //byte[] encoded = Base64.decodeBase64(publicKeyPem);
		
		//Usage of PemFile.java util
		PemFile pemFile = new PemFile(filename);
		byte[] encoded = pemFile.getPemObject().getContent();  
		
	    X509EncodedKeySpec  keySpec = new X509EncodedKeySpec(encoded);
	    KeyFactory kf = KeyFactory.getInstance("RSA");	  
	    PublicKey publicKey = kf.generatePublic(keySpec);
	    return publicKey;
	}
	
	private static RSAPrivateKey getPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
		
		File file = new File(filename);
		FileInputStream fis = new FileInputStream(file);
        DataInputStream dis = new DataInputStream(fis);
        
        byte[] keyBytes = new byte[(int) file.length()];
        dis.readFully(keyBytes);
        dis.close();
        
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory.generatePrivate(spec);
        
        return privateKey;

	}
	

	/*private static String getKey(String filename) throws IOException {
		 // Read key from file
	    String strKeyPEM = "";
	    BufferedReader br = new BufferedReader(new FileReader(filename));
	    String line;
	    while ((line = br.readLine()) != null) {
	        strKeyPEM += line + "\n";
	    }
	    br.close();
	    return strKeyPEM;
	}*/

}

When you run the above example PemToPublicPrivateKeyExample.java class you will see the following output. This Java code will help you in reading public and private keys from PEM files.

Output

Public Key: Sun RSA public key, 2048 bits
  params: null
  modulus: 25622523552640509872674647748128418427196878805802974525582213375943292866688386280128572938417498583760725631884402047650172578686271723723912330821024381216453489466722940584464191109827782366140686281989329115496275295815310414943283528008535270516589906407988761155150211830876162901079773987287320522395702055867191390238620531771664622250346650503605006931286353348714961829467079593192943673984151097109814014569056365504907110936637707839047313988149249985540404575244379812342259482507954431540160866546667721354659887420139015654844886782367838366698828795807906696509716076522708156260850256749742657872987
  public exponent: 65537
Private Key: SunRsaSign RSA private CRT key, 2048 bits
  params: null
  modulus: 25622523552640509872674647748128418427196878805802974525582213375943292866688386280128572938417498583760725631884402047650172578686271723723912330821024381216453489466722940584464191109827782366140686281989329115496275295815310414943283528008535270516589906407988761155150211830876162901079773987287320522395702055867191390238620531771664622250346650503605006931286353348714961829467079593192943673984151097109814014569056365504907110936637707839047313988149249985540404575244379812342259482507954431540160866546667721354659887420139015654844886782367838366698828795807906696509716076522708156260850256749742657872987
  private exponent: 17586675877266705152852948405542832996789557033758566963459796821491022521968409906450151769059223626246375651907411955222968904695737689370473905996950420987529598801922548122601777754449900577934700871610326862724399219245008291429173183703983125160562182583129506126953049098803766357618924779439790333077672652416920933916743021966806362551647245303270227184263417966975663222400220534187827685721381511872771004877660769860453663015783027855746470790262266367515875656740848222390555559390660055912124446014837715667235277503335371191622760609500597616829812723390081370845708118008488655826516816751198273129617

Note, if you see in the above example code I had commented the following block/lines of code and getKey() method. If you don’t want to use BouncyCastle library then you can uncomment the following lines of code.

//If you don't want to use PemFile.java util uncomment this logic
//String publicKeyPem = getKey(filename);		
//publicKeyPem = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----\n", "");
//publicKeyPem = publicKeyPem.replace("-----END PUBLIC KEY-----", "");
//byte[] encoded = Base64.decodeBase64(publicKeyPem);

And then comment the following lines of code.

//Usage of PemFile.java util (BouncyCastle library)
PemFile pemFile = new PemFile(filename);
byte[] encoded = pemFile.getPemObject().getContent();

That’s it. Hope it helped 🙂

Also See:

References:

Leave a Reply

avatar
  Subscribe  
Notify of