Table of Contents
Introduction
RSA is a short form for Rivest, Shamir, and Adleman, are the people who first publicly described it in 1977.
It is an algorithm for asymmetric cryptography which involves the use of two keys.
- A public key, which can be known to anybody and can be used to encrypt messages, and verify signatures.
- A private key, known only to the intended user, is used to decrypt messages and create signatures.
RSA is asymmetric because those who encrypt messages or verify signatures cannot decrypt messages or create signatures.
RSA algorithm involves three steps which include key generation, encryption, and decryption.
Generate RSA key pair
To generate an RSA key pair, use the getInstance()
static method of the KeyPairGenerator
class and pass the RSA parameter as the encryption algorithm to be used.
The generator will create a public and private key pair that can be used with the RSA algorithm and associate algorithm-specific parameters with each generated key.
1 2 3 |
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); |
The KeyPairGenerator
class has a concept of key size and a source of randomness that you can initialize using the initialize()
method of the class.
Note that if you do not explicitly initialize the KeyPairGenerator
, the provider will supply a default initialization.
The defaults may change in future versions, so it is recommended to explicitly initialize the KeyPairGenerator
instead of relying on the provider defaults.
The RSA implementations of the Java platform are required to support 1024
, 2048
, and 4096
key sizes.
The source of randomness will come from SecureRandom
, which will be the second argument of the initialize
method.
If the key size is not supported by the KeyPairGenerator
object, the method throws an InvalidParameterException
.
1 2 3 4 5 6 |
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(); keyPairGenerator.initialize(2048,secureRandom); KeyPair pair = keyPairGenerator.generateKeyPair(); |
The generateKeyPair()
method will generate a new KeyPair
every time it is called, and we can use the getPublic()
and getPrivate()
methods of the KeyPair
class to retrieve the public key and private key respectively.
To see the generated keys call getEncoded()
on each of the methods, which return the key in its primary encoding format or null if the key does not support encoding.
Convert the keys to string using encodeToString()
method of the Base64.Encoder
class and log to the console to view the contents.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package com.encryption; import java.security.*; import java.util.Base64; public class RSAEncryption{ public static void main(String[] args) throws NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(); keyPairGenerator.initialize(2048,secureRandom); KeyPair pair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = pair.getPublic(); String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded()); System.out.println("public key = "+ publicKeyString); PrivateKey privateKey = pair.getPrivate(); String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded()); System.out.println("private key = "+ privateKeyString); } } |
Output:
private key = MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCP4XfoslIuZcZAUY04fCKe7YKb01OelIT9j5JcLD
Further reading:
Encrypt a random text
Create a Cipher
object using the static method getInstance()
and pass RSA as the transformation. The Cipher will provide the functionality of a cryptographic cipher for encryption and decryption.
The transformation describes the operation to be performed on the given input to produce some output. The name of the cryptographic algorithm form the transformation and may be accompanied by a feedback mode and a padding scheme.
The Cipher's init()
method initializes the cipher with a key for encryption, decryption, key wrapping, or key unwrapping depending on the value of opmode
.
The opmode
stands for the operation mode of the cipher, and since we want to encrypt a text, we will use ENCRYPT_MODE
as our operation mode in this case.
The Cipher's init()
method will also use the private key generated by the KeyPairGenerator
when encrypting the text, so it must be passed as the second argument.
The doFinal()
method performs the encryption operation depending on how the cipher was initialized and resets once it finishes allowing encrypting more data.
Note that if an exception is thrown by this method, the cipher may need to be reset before it can be used again, and the exceptions that might be thrown include
IllegalStateException
,IllegalBlockSizeException
,BadPaddingException
, andAEADBadTagException
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
package com.encryption; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.security.*; import java.util.Base64; public class RSAEncryption{ public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(); keyPairGenerator.initialize(2048,secureRandom); KeyPair pair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = pair.getPublic(); String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded()); System.out.println("public key = "+ publicKeyString); PrivateKey privateKey = pair.getPrivate(); String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded()); System.out.println("private key = "+ privateKeyString); //Encrypt Hello world message Cipher encryptionCipher = Cipher.getInstance("RSA"); encryptionCipher.init(Cipher.ENCRYPT_MODE,privateKey); String message = "Hello world"; byte[] encryptedMessage = encryptionCipher.doFinal(message.getBytes()); String encryption = Base64.getEncoder().encodeToString(encryptedMessage); System.out.println("encrypted message = "+encryption); } } |
Output
private key = MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCP4XfoslIuZcZAUY04fCKe7YKb01OelIT9j5JcLD
encrypted message = VBnz7eObiVnkdlQxDh1rpeJUCLlH42hcZFB1mY9kfKyRuD9nVh1wKEkZ9Q/EqhkZFC4utkFijxl7N0q
Decrypt the random text
The decryption process is the same as the encryption but only the init()
method of the cipher is modified to support DECRYPT_MODE
.
Create a Cipher
object using RSA transformation and pass the DECRYPT_MODE
as the first parameter and public key generated by KeyPairGenerator
as the second parameter of the init()
method.
The doFinal()
method performs both encryption and decryption when the right mode is initialized, and we only need to pass our encrypted message to it so that it can be decrypted.
The method returns an array of bites which is simply our message, and we can convert it to a string and log it to the console to verify our text is similar to the decrypted text.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package com.encryption; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.security.*; import java.util.Base64; public class RSAEncryption{ public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(); keyPairGenerator.initialize(2048,secureRandom); KeyPair pair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = pair.getPublic(); String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded()); System.out.println("public key = "+ publicKeyString); PrivateKey privateKey = pair.getPrivate(); String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded()); System.out.println("private key = "+ privateKeyString); //Encrypt Hello world message Cipher encryptionCipher = Cipher.getInstance("RSA"); encryptionCipher.init(Cipher.ENCRYPT_MODE,privateKey); String message = "Hello world"; byte[] encryptedMessage = encryptionCipher.doFinal(message.getBytes()); String encryption = Base64.getEncoder().encodeToString(encryptedMessage); System.out.println("encrypted message = "+encryption); //Decrypt Hello world message Cipher decryptionCipher = Cipher.getInstance("RSA"); decryptionCipher.init(Cipher.DECRYPT_MODE,publicKey); byte[] decryptedMessage = decryptionCipher.doFinal(encryptedMessage); String decryption = new String(decryptedMessage); System.out.println("decrypted message = "+decryption); } } |
Output
private key = MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCP4XfoslIuZcZAUY04fCKe7YKb01OelIT9j5JcLD
encrypted message = VBnz7eObiVnkdlQxDh1rpeJUCLlH42hcZFB1mY9kfKyRuD9nVh1wKEkZ9Q/EqhkZFC4utkFijxl7N0q
decrypted message = Hello world
Conclusion
In this tutorial, You have learned how to encrypt and decrypt a random text by leveraging RSA asymmetric encryption algorithm by generating a private key and public key using java KeyPairGenerator
and a Cipher
class that provided encryption and decryption functionalities. In the next tutorial, you will learn how to encrypt and decrypt using Java AES
and Java AES 256
.
That’s all about RSA Encryption and Decryption in Java.