Rsa Encryption and Decryption in Java Example

In this article, we will discuss about RSA(Rivest–Shamir–Adleman) cryptography encryption and decryption in java. We will be generating public and private keys using KeyPairGenerator and use these keys for asymmetric encryption and decryption.

You can use this online tool for generating RSA keys and perform RSA encryption and decryption online.

As we know, there are 2 basic types of encryption - Asymmetric and Symmetric encryption. Asymmetric encryption uses two different keys as public and private keys. Here, you can encrypt sensitive information with a public key and a matching private key is used to decrypt the same. Asymmetric encryption is mostly used when there are 2 different endpoints are involved such as VPN client and server, SSH etc.

The example shown here can be used to generate base64 encoded public keys and the same keys can be shared with javascript or Android client to encrypt all the request that has to travel through the wires to reach to the server and the server can decrypt that using the private key.

We have another encryption technique called as Symmetric encryption. This type of encryption uses a single key known as private key or secret key to encrypt and decrypt sensitive information. Here is an article where I have discussed about AES encryption in Java

Note that since asymmetric encryption doesn't share the encryption key, it's more secure than symmetric encryption. Still, it is much slower than symmetric encryption. Therefore, to improve software performance while keeping its security at the highest level, pro Java developers use asymmetric encryption just to encrypt a traditional single key used in symmetric encryption.

Generating RSA Public Private Key

We can use factory method to generate these keys using KeyPairGenerator. For the demo purpose we are using a key size of 1024. By default, the private key is generated in PKCS#8 format and the public key is generated in X.509 format. Once these keys are generated, either you can write these keys in a file and share the file containing public keys with the client. Remember, the public key is written in the text file as X.509 format. Also, we can do a base64 encode to make it readable and share the string with the client.

In the following example we will be Base64 encoding the public and private keys to ease the sharing of these keys. For this purpose, we will be using Java 8 provided Base64.

RSAKeyPairGenerator.java

          package          com.devglan.rsa;          import          java.io.File;          import          java.io.FileOutputStream;          import          java.io.IOException;          import          java.security.*;          import          java.util.Base64;          public class          RSAKeyPairGenerator {          private          PrivateKey privateKey;          private          PublicKey publicKey;          public          RSAKeyPairGenerator()          throws          NoSuchAlgorithmException {         KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");         keyGen.initialize(1024);         KeyPair pair = keyGen.generateKeyPair();          this.privateKey = pair.getPrivate();          this.publicKey = pair.getPublic();     }          public void          writeToFile(String path, byte[] key)          throws          IOException {         File f =          new          File(path);         f.getParentFile().mkdirs();          FileOutputStream fos =          new          FileOutputStream(f);         fos.write(key);         fos.flush();         fos.close();     }          public          PrivateKey getPrivateKey() {          return          privateKey;     }          public          PublicKey getPublicKey() {          return          publicKey;     }          public static void          main(String[] args)          throws          NoSuchAlgorithmException, IOException {         RSAKeyPairGenerator keyPairGenerator =          new          RSAKeyPairGenerator();         keyPairGenerator.writeToFile("RSA/publicKey", keyPairGenerator.getPublicKey().getEncoded());         keyPairGenerator.writeToFile("RSA/privateKey", keyPairGenerator.getPrivateKey().getEncoded());         System.out.println(Base64.getEncoder().encodeToString(keyPairGenerator.getPublicKey().getEncoded()));         System.out.println(Base64.getEncoder().encodeToString(keyPairGenerator.getPrivateKey().getEncoded()));     } }        

This will output the public and private keys.Following is the screenshot.

rsa-encryption-decryption-java

RSA Encryption In Java

Now We have RSAUtil.java that has methods defined for RSA encryption and decryption.Let us discuss about encryption first. As we discussed above the public key generated is in X.509 format and we use public key for encryption.Hence, we need X509EncodedKeySpec class to convert it again to RSA public key.Remember, that we have base64 encoded public keys.Hence, first let us first Base64 decode and generate the public key.

Note: - RSA/ECB/PKCS1Padding has been known to be insecure and you should use RSA/None/OAEPWithSHA1AndMGF1Padding instead.

RSAUtil.java

          public static          PublicKey getPublicKey(String base64PublicKey){         PublicKey publicKey =          null;          try{             X509EncodedKeySpec keySpec =          new          X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));             KeyFactory keyFactory = KeyFactory.getInstance("RSA");             publicKey = keyFactory.generatePublic(keySpec);          return          publicKey;         }          catch          (NoSuchAlgorithmException e) {             e.printStackTrace();         }          catch          (InvalidKeySpecException e) {             e.printStackTrace();         }          return          publicKey;     }        

Now, we have a simple method encrypt()that takes the string to be enrypted and the Base64 encoded RSA key for encryption.Here getPublicKey() is the method that we defined above.

          public static          byte[] encrypt(String data, String publicKey) throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException { 	Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 	cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));          return          cipher.doFinal(data.getBytes()); }        

RSA Decryption In Java

For decryption we will be using private key and we discussed above that the private key is generated in PKCS#8 format.Hence, following is the code to generate the private key from base64 encoded string using PKCS8EncodedKeySpec.

          public staticPrivateKey getPrivateKey(String base64PrivateKey){         PrivateKey privateKey =          null;         PKCS8EncodedKeySpec keySpec =          new          PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));         KeyFactory keyFactory =          null;          try          {             keyFactory = KeyFactory.getInstance("RSA");         }          catch          (NoSuchAlgorithmException e) {             e.printStackTrace();         }          try          {             privateKey = keyFactory.generatePrivate(keySpec);         }          catch          (InvalidKeySpecException e) {             e.printStackTrace();         }          return          privateKey;     }        

Now following is the decrypt method that accepts RSA encrypted string and Base64 encoded RSA private key for decryption.

          public static String decrypt(String data, String base64PrivateKey) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {         return decrypt(Base64.getDecoder().decode(data.getBytes()), getPrivateKey(base64PrivateKey));     }        

Now, putting it all together.

RSAUtil.java

package com.devglan.rsa;  import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64;  public class RSAUtil {      private static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgFGVfrY4jQSoZQWWygZ83roKXWD4YeT2x2p41dGkPixe73rT2IW04glagN2vgoZoHuOPqa5and6kAmK2ujmCHu6D1auJhE2tXP+yLkpSiYMQucDKmCsWMnW9XlC5K7OSL77TXXcfvTvyZcjObEz6LIBRzs6+FqpFbUO9SJEfh6wIDAQAB";     private static String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKAUZV+tjiNBKhlBZbKBnzeugpdYPhh5PbHanjV0aQ+LF7vetPYhbTiCVqA3a+Chmge44+prlqd3qQCYra6OYIe7oPVq4mETa1c/7IuSlKJgxC5wMqYKxYydb1eULkrs5IvvtNddx+9O/JlyM5sTPosgFHOzr4WqkVtQ71IkR+HrAgMBAAECgYAkQLo8kteP0GAyXAcmCAkA2Tql/8wASuTX9ITD4lsws/VqDKO64hMUKyBnJGX/91kkypCDNF5oCsdxZSJgV8owViYWZPnbvEcNqLtqgs7nj1UHuX9S5yYIPGN/mHL6OJJ7sosOd6rqdpg6JRRkAKUV+tmN/7Gh0+GFXM+ug6mgwQJBAO9/+CWpCAVoGxCA+YsTMb82fTOmGYMkZOAfQsvIV2v6DC8eJrSa+c0yCOTa3tirlCkhBfB08f8U2iEPS+Gu3bECQQCrG7O0gYmFL2RX1O+37ovyyHTbst4s4xbLW4jLzbSoimL235lCdIC+fllEEP96wPAiqo6dzmdH8KsGmVozsVRbAkB0ME8AZjp/9Pt8TDXD5LHzo8mlruUdnCBcIo5TMoRG2+3hRe1dHPonNCjgbdZCoyqjsWOiPfnQ2Brigvs7J4xhAkBGRiZUKC92x7QKbqXVgN9xYuq7oIanIM0nz/wq190uq0dh5Qtow7hshC/dSK3kmIEHe8z++tpoLWvQVgM538apAkBoSNfaTkDZhFavuiVl6L8cWCoDcJBItip8wKQhXwHp0O3HLg10OEd14M58ooNfpgt+8D8/8/2OOFaR0HzA+2Dm";      public static PublicKey getPublicKey(String base64PublicKey){         PublicKey publicKey = null;         try{             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));             KeyFactory keyFactory = KeyFactory.getInstance("RSA");             publicKey = keyFactory.generatePublic(keySpec);             return publicKey;         } catch (NoSuchAlgorithmException e) {             e.printStackTrace();         } catch (InvalidKeySpecException e) {             e.printStackTrace();         }         return publicKey;     }      public static PrivateKey getPrivateKey(String base64PrivateKey){         PrivateKey privateKey = null;         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));         KeyFactory keyFactory = null;         try {             keyFactory = KeyFactory.getInstance("RSA");         } catch (NoSuchAlgorithmException e) {             e.printStackTrace();         }         try {             privateKey = keyFactory.generatePrivate(keySpec);         } catch (InvalidKeySpecException e) {             e.printStackTrace();         }         return privateKey;     }      public static byte[] encrypt(String data, String publicKey) throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {         Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");         cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));         return cipher.doFinal(data.getBytes());     }      public static String decrypt(byte[] data, PrivateKey privateKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {         Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");         cipher.init(Cipher.DECRYPT_MODE, privateKey);         return new String(cipher.doFinal(data));     }      public static String decrypt(String data, String base64PrivateKey) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {         return decrypt(Base64.getDecoder().decode(data.getBytes()), getPrivateKey(base64PrivateKey));     }      public static void main(String[] args) throws IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, BadPaddingException {         try {             String encryptedString = Base64.getEncoder().encodeToString(encrypt("Dhiraj is the author", publicKey));             System.out.println(encryptedString);             String decryptedString = RSAUtil.decrypt(encryptedString, privateKey);             System.out.println(decryptedString);         } catch (NoSuchAlgorithmException e) {             System.err.println(e.getMessage());         }      } }        

Putting RSA and AES together

With every doubling of the RSA key length, decryption is 6-7 times times slower.Hence, when there are large messages for RSA encryption, the performance degrades.In such scenarios, we first do an AES encryption of the messages and the key used for AES encryption is RSA encrypted and sent to the server. This technique can be used by the Javascript or Android client for sending sensitive payloads to the server.We have demonstrates this in another article of RSA encryption in javacript and decryption in Java.

Conclusion

In this article, we discussed about RSA encryption and decryption in java using public and private keys.The source code can be downloaded from github.

spearsgail1974.blogspot.com

Source: https://www.devglan.com/java8/rsa-encryption-decryption-java

0 Response to "Rsa Encryption and Decryption in Java Example"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel