RSA Public Key Encryption and Private Key Decryption using Java

In Previous Post, I have discussed about What is Cryptography, What are Types of it and How we can encrypt and decrypt data using DES Algorithm in Java

Asymmetric Cryptography :
  • Here, We share Public Key with others so they can encrypt data using Public Key
  • We can only decrypt data using Private Key associated with Public Key. Private key is secret one and we don't share with anyone.
  • Most common used algorithm is RSA ALGORITHM. named after Rivest,Shamir and Adleman
Understanding and making working example for RSA encryption and decryption using public and private key takes lots lots of time for me. Believe me, It's complex stuff :)

Steps 1 :

Let's Break down tasks which helps us to encrypt and decrypt data using RSA Algorithm.
  1. Generate Public Key and Private Key
  2. Pull out parameters for Public Key and Private Key which help us in saving Keys to File
  3. Save Public Key and Private Key to file so public key can be distributed and private key can be kept secret.
  4. Encrypt Data using Public Key (use public key from stored file as above)
  5. Decrypt Data using Private Key (use private key from stored file as above)
Now,
Procedure to encryt and decrypt data using Cipher remains similar as we have done in DES Algorithm having some differences.

Steps 2 :  Encrypt Data

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey); //pubKey stored earlier
cipher.doFinal(dataToEncrypt);

Steps 3 : Decrypt Data
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey); //privKey stored earlier
byte[] descryptedData = cipher.doFinal(data);
System.out.println("Decrypted Data: " + new String(descryptedData));

If you would like to correct any issue then let me know your views and suggestions ! You can fork on my GitHub RSA Algorithm Repository

Java Program - RSA Public Key Encryption and Private Key Decryption :

package com.anuj.security.encryption;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;

/**
 * 
 * RSA - Encrypt Data using Public Key RSA - Descypt Data using Private Key
 */
public class RSAEncryptionDescription {

 private static final String PUBLIC_KEY_FILE = "Public.key";
 private static final String PRIVATE_KEY_FILE = "Private.key";

 public static void main(String[] args) throws IOException {

  try {
   System.out.println("-------GENRATE PUBLIC and PRIVATE KEY-------------");
   KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
   keyPairGenerator.initialize(2048); // 1024 used for normal securities
   KeyPair keyPair = keyPairGenerator.generateKeyPair();
   PublicKey publicKey = keyPair.getPublic();
   PrivateKey privateKey = keyPair.getPrivate();
   System.out.println("Public Key - " + publicKey);
   System.out.println("Private Key - " + privateKey);

   // Pullingout parameters which makes up Key
   System.out.println("\n------- PULLING OUT PARAMETERS WHICH MAKES KEYPAIR----------\n");
   KeyFactory keyFactory = KeyFactory.getInstance("RSA");
   RSAPublicKeySpec rsaPubKeySpec = keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);
   RSAPrivateKeySpec rsaPrivKeySpec = keyFactory.getKeySpec(privateKey, RSAPrivateKeySpec.class);
   System.out.println("PubKey Modulus : " + rsaPubKeySpec.getModulus());
   System.out.println("PubKey Exponent : " + rsaPubKeySpec.getPublicExponent());
   System.out.println("PrivKey Modulus : " + rsaPrivKeySpec.getModulus());
   System.out.println("PrivKey Exponent : " + rsaPrivKeySpec.getPrivateExponent());

   // Share public key with other so they can encrypt data and decrypt thoses using
   // private key(Don't share with Other)
   System.out.println("\n--------SAVING PUBLIC KEY AND PRIVATE KEY TO FILES-------\n");
   RSAEncryptionDescription rsaObj = new RSAEncryptionDescription();
   rsaObj.saveKeys(PUBLIC_KEY_FILE, rsaPubKeySpec.getModulus(), rsaPubKeySpec.getPublicExponent());
   rsaObj.saveKeys(PRIVATE_KEY_FILE, rsaPrivKeySpec.getModulus(), rsaPrivKeySpec.getPrivateExponent());

   // Encrypt Data using Public Key
   byte[] encryptedData = rsaObj.encryptData("Anuj Patel - Classified Information !");

   // Descypt Data using Private Key
   rsaObj.decryptData(encryptedData);

  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  } catch (InvalidKeySpecException e) {
   e.printStackTrace();
  }

 }

 /**
  * Save Files
  * 
  * @param fileName
  * @param mod
  * @param exp
  * @throws IOException
  */
 private void saveKeys(String fileName, BigInteger mod, BigInteger exp) throws IOException {
  FileOutputStream fos = null;
  ObjectOutputStream oos = null;

  try {
   System.out.println("Generating " + fileName + "...");
   fos = new FileOutputStream(fileName);
   oos = new ObjectOutputStream(new BufferedOutputStream(fos));

   oos.writeObject(mod);
   oos.writeObject(exp);

   System.out.println(fileName + " generated successfully");
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if (oos != null) {
    oos.close();

    if (fos != null) {
     fos.close();
    }
   }
  }
 }

 /**
  * Encrypt Data
  * 
  * @param data
  * @throws IOException
  */
 private byte[] encryptData(String data) throws IOException {
  System.out.println("\n----------------ENCRYPTION STARTED------------");

  System.out.println("Data Before Encryption :" + data);
  byte[] dataToEncrypt = data.getBytes();
  byte[] encryptedData = null;
  try {
   PublicKey pubKey = readPublicKeyFromFile(PUBLIC_KEY_FILE);
   Cipher cipher = Cipher.getInstance("RSA");
   cipher.init(Cipher.ENCRYPT_MODE, pubKey);
   encryptedData = cipher.doFinal(dataToEncrypt);
   System.out.println("Encryted Data: " + encryptedData);

  } catch (Exception e) {
   e.printStackTrace();
  }

  System.out.println("----------------ENCRYPTION COMPLETED------------");
  return encryptedData;
 }

 /**
  * Encrypt Data
  * 
  * @param data
  * @throws IOException
  */
 private void decryptData(byte[] data) throws IOException {
  System.out.println("\n----------------DECRYPTION STARTED------------");
  byte[] descryptedData = null;

  try {
   PrivateKey privateKey = readPrivateKeyFromFile(PRIVATE_KEY_FILE);
   Cipher cipher = Cipher.getInstance("RSA");
   cipher.init(Cipher.DECRYPT_MODE, privateKey);
   descryptedData = cipher.doFinal(data);
   System.out.println("Decrypted Data: " + new String(descryptedData));

  } catch (Exception e) {
   e.printStackTrace();
  }

  System.out.println("----------------DECRYPTION COMPLETED------------");
 }

 /**
  * read Public Key From File
  * 
  * @param fileName
  * @return PublicKey
  * @throws IOException
  */
 public PublicKey readPublicKeyFromFile(String fileName) throws IOException {
  FileInputStream fis = null;
  ObjectInputStream ois = null;
  try {
   fis = new FileInputStream(new File(fileName));
   ois = new ObjectInputStream(fis);

   BigInteger modulus = (BigInteger) ois.readObject();
   BigInteger exponent = (BigInteger) ois.readObject();

   // Get Public Key
   RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, exponent);
   KeyFactory fact = KeyFactory.getInstance("RSA");
   PublicKey publicKey = fact.generatePublic(rsaPublicKeySpec);

   return publicKey;

  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if (ois != null) {
    ois.close();
    if (fis != null) {
     fis.close();
    }
   }
  }
  return null;
 }

 /**
  * read Public Key From File
  * 
  * @param fileName
  * @return
  * @throws IOException
  */
 public PrivateKey readPrivateKeyFromFile(String fileName) throws IOException {
  FileInputStream fis = null;
  ObjectInputStream ois = null;
  try {
   fis = new FileInputStream(new File(fileName));
   ois = new ObjectInputStream(fis);

   BigInteger modulus = (BigInteger) ois.readObject();
   BigInteger exponent = (BigInteger) ois.readObject();

   // Get Private Key
   RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
   KeyFactory fact = KeyFactory.getInstance("RSA");
   PrivateKey privateKey = fact.generatePrivate(rsaPrivateKeySpec);

   return privateKey;

  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if (ois != null) {
    ois.close();
    if (fis != null) {
     fis.close();
    }
   }
  }
  return null;
 }
}

Output :
-------GENRATE PUBLIC and PRIVATE KEY-------------
Public Key - Sun RSA public key, 2048 bits
modulus: 21581189033711728218884545603483534136048436157764307737563263470622465209956484999186502236746398592183132361416574917491992616495836589976123829407441678145892864499340377518038083961762657109551322980788812471344883222074336738095812428432922899347944377728829986328978579520777569602492356009886434195381263189086322743017222283576658366049322746591279563891358961018804857343098186437284431498111857540148953385584647472608550518878892606670675504722021939011562806733746871866813023994221533891973381208433651324985362129897175578902143642720519685766703550582631650738544841113850242327026858745837631433020149
public exponent: 65537
Private Key - Sun RSA private CRT key, 2048 bits
modulus: 21581189033711728218884545603483534136048436157764307737563263470622465209956484999186502236746398592183132361416574917491992616495836589976123829407441678145892864499340377518038083961762657109551322980788812471344883222074336738095812428432922899347944377728829986328978579520777569602492356009886434195381263189086322743017222283576658366049322746591279563891358961018804857343098186437284431498111857540148953385584647472608550518878892606670675504722021939011562806733746871866813023994221533891973381208433651324985362129897175578902143642720519685766703550582631650738544841113850242327026858745837631433020149
public exponent: 65537
private exponent: 16818884445379350882395107598729290416080593813537574464745772338710078438111715082067390966047001054301440184313465125210240366320168055190663664601447788444717915899473729065013582226025416358245476925153555960357354022421635853002786514216572883778571785289225804534119366907605083654230390210185843516320290211843466509006336799394129511533245623813347345392660622411996306876517607316550963240563612473897071827862623073628753325937287805770949617787789425780112692109708570540461688127920714311987581602948589935567788167325085963891768759393262829208398129726072686050759571366259756340489722725543813760017473
prime p: 169306732673760790355930286583843583805308330869543277096562778910166303721930997866328982804816821819049730113874193091618529576910909406581209778870502424642394784256694354812411284399682213039455474743549204317489176290410742719482125745160659824679134175050540597373872559990275244248263694864065118289029
prime q: 127467990746102133899249581938138767929216080178107251583999590555445542238038489740168537885259598373126437993872087614678308989656079509601390372258522297126080029882334388941627788832329332096331303686348060808722035897823890209585664124526602293844519631122458634394071272791623445251919411933626571407281
prime exponent p: 119333901496849599293704132446823728072975688967404864411271868504773060528055275408385106164501021564724723181564468948550204262420398221130137530179366136709128313306521237344549101427812082746106271950635036621111395400810892143995572494105716759714409340496355063773002962656679194311000577640962509866565
prime exponent q: 87599841848325282034397392631823732681751728567706372035518219616807479391168584759867720185760822911137855574805147536162722715185622854768100782400042506374437622501342120383019881612208077700942453678524044597159341666571405330569429887003580278506237997865700511687666143632786492373791879306019609527633
crt coefficient: 7792255011181278160725143182305151172136668404207729019083906871364836764302818205034762517433549401848970490160009739693902133369434504868735056960398036976540900479169732396057070661243627622278554530394073212878117541087837917760429802642524231978699857141434244570696796138207734744378146597148568299985

------- PULLING OUT PARAMETERS WHICH MAKES KEYPAIR----------

PubKey Modulus : 21581189033711728218884545603483534136048436157764307737563263470622465209956484999186502236746398592183132361416574917491992616495836589976123829407441678145892864499340377518038083961762657109551322980788812471344883222074336738095812428432922899347944377728829986328978579520777569602492356009886434195381263189086322743017222283576658366049322746591279563891358961018804857343098186437284431498111857540148953385584647472608550518878892606670675504722021939011562806733746871866813023994221533891973381208433651324985362129897175578902143642720519685766703550582631650738544841113850242327026858745837631433020149
PubKey Exponent : 65537
PrivKey Modulus : 21581189033711728218884545603483534136048436157764307737563263470622465209956484999186502236746398592183132361416574917491992616495836589976123829407441678145892864499340377518038083961762657109551322980788812471344883222074336738095812428432922899347944377728829986328978579520777569602492356009886434195381263189086322743017222283576658366049322746591279563891358961018804857343098186437284431498111857540148953385584647472608550518878892606670675504722021939011562806733746871866813023994221533891973381208433651324985362129897175578902143642720519685766703550582631650738544841113850242327026858745837631433020149
PrivKey Exponent : 16818884445379350882395107598729290416080593813537574464745772338710078438111715082067390966047001054301440184313465125210240366320168055190663664601447788444717915899473729065013582226025416358245476925153555960357354022421635853002786514216572883778571785289225804534119366907605083654230390210185843516320290211843466509006336799394129511533245623813347345392660622411996306876517607316550963240563612473897071827862623073628753325937287805770949617787789425780112692109708570540461688127920714311987581602948589935567788167325085963891768759393262829208398129726072686050759571366259756340489722725543813760017473

--------SAVING PUBLIC KEY AND PRIVATE KEY TO FILES-------

Generating Public.key...
Public.key generated successfully
Generating Private.key...
Private.key generated successfully

----------------ENCRYPTION STARTED------------
Data Before Encryption :Anuj Patel - Classified Information !
Encryted Data: [B@749436
----------------ENCRYPTION COMPLETED------------

----------------DECRYPTION STARTED------------
Decrypted Data: Anuj Patel - Classified Information !
----------------DECRYPTION COMPLETED------------

PLEASE NOTE that current program is for learning purpose only and one should not use it as part of production or project. Also one must check with Sun/Oracle/any other licenses if associated before using.

5 comments:

  1. Amazing tutorial. I am completely stuck with these solution for the past 4 days. I got some overlook now. But still I am facing issues to convert PEM file to pubkey.key format. Please assist me with this. Thanks

    ReplyDelete
  2. hi Anuj Patel what data contains inside the package you using above code like package com.anuj.security.encryption ....

    ReplyDelete
  3. Hi Anuj,
    The public that you have generated, can i use that is JS and do the encryption. If so, please provide some sample code.
    Thank!!!

    ReplyDelete
  4. Hi Anuj, Thank you for the amazing description. But , can you help me with doing an encryption in javascript using public key and descrypting the string in JAVA program using the private key.

    Thank you

    Regards,
    Pratyusha

    ReplyDelete
  5. how can we give our own public as the input for the encryption in coding.... send d code to my mail....

    ReplyDelete