Encryption and Decryption of Strings in Java
In this tutorial, you will learn about encryption and decryption of strings in Java.
Encryption
Encryption is the process of converting a plain text into a ciphertext. A ciphertext is not readable until it is converted to plain text using a secret key.
Decryption
Decryption is the process of converting a ciphertext into a plain text using a secret key so as to make it readable.
Types of Encryption
There are two types of encryption:
- Asymmetric Encryption - Asymmetric encryption uses two keys - public key and private key. A public key is used to encrypt a plain text. A public key can be made freely available to anyone who might want to encrypt and send a text. The encrypted text can only be read using a private key. A private key must be kept secret or exchanged over the internet to people who you want to be able to read your encrypted texts. Some of the asymmetric key encryption algorithm are DSA, RSA, PKCS, ELGamal, ECC, Diffie-Hellman, etc.
- Symmetric Encryption - Symmetric encryption uses a single key for both encryption and decryption. Some of the symmetric key encryption algorithm are AES (Advanced Encryption Standard), DES (Data Encryption Standard), etc.
Asymmetric encryption is considered to be more secure than symmetric encryption because asymmetric encryption technique is relatively new compared to symmetric encryption and asymmetric encryption also uses two keys for encryption and decryption.
Java provides the Cipher class with cryptographic functions for encryption and decryption. You can simply import the Cipher class from the package javax.crypto.Cipher.
To create a Cipher object, we need to call the Cipher's getInstance() method and pass the name of the transformation to it.
A transformation is a string in the form algorithm/mode/scheme or algorithm. It includes the name of the cryptographic algorithm and may be followed by a feedback mode and padding scheme.
The following is an example of creating a Cipher object with a valid transformation:
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
Asymmetric Encryption Example
The code below shows how to generate and save public private key pair files to a specific location, load the keys from files to encrypt and decrypt a string using asymmetric encryption technique:
Note: You should create the public and private key pair once and use the same keys everytime for encryption and decryption. A text that is encrypted using a specific public private key pair cannot be decrypted using a private key of another public private key pair.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class AsymmetricEncryptionManager {
public static void main(String[] args) {
/* path to project root folder for saving public and private keys */
String path = System.getProperty("user.dir");
// Generates New public and private keys
KeyPair keyPair = generateKeys();
/* save public and private keys to files at the given location */
saveKeysToFiles(path, keyPair.getPublic(), keyPair.getPrivate());
// Algorithm to convert keys
String algorithm = "RSA";
// Read keys from files
PublicKey publicKey = loadPublicKey(path, algorithm);
PrivateKey privateKey = loadPrivateKey(path, algorithm);
// Test
String plainText = "This is a secret message";
/* Encrypting plain text to ciphertext */
String encryptedText = encrypt(publicKey, plainText);
System.out.println("Encrypted text = " + encryptedText);
/* Decrypting encrypted text back to plain text */
String decryptedText = decrypt(privateKey, encryptedText);
System.out.println("Decrypted text = " + decryptedText);
}
public static String encrypt(PublicKey publicKey, String plainText) {
if (plainText == null || plainText.isEmpty()) {
System.out.println("No data to encrypt!");
return plainText;
}
Cipher cipher = null;
String encryptedString = "";
try {
// Creating a Cipher object
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// Initializing a Cipher object with public key
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// Encrypting the plain text string
byte[] encryptedText = cipher.doFinal(plainText.getBytes());
// Encoding the encrypted text to Base64
encryptedString = Base64.getEncoder().encodeToString(encryptedText);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException ex) {
System.out.println("Exception caught while encrypting : " + ex);
}
return encryptedString;
}
public static String decrypt(PrivateKey privateKey, String cipherText) {
if (cipherText == null || cipherText.isEmpty()) {
System.out.println("No data to decrypt!");
return cipherText;
}
String decryptedString = "";
Cipher cipher = null;
try {
// Creating a Cipher object
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// Initializing a Cipher object with private key
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// Decoding from Base64
byte[] encryptedText = Base64.getDecoder().decode(cipherText.getBytes());
// Decrypting to plain text
decryptedString = new String(cipher.doFinal(encryptedText));
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException ex) {
System.out.println("Exception caught while decrypting : " + ex);
}
return decryptedString;
}
public static KeyPair generateKeys() {
KeyPair keyPair = null;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
// Initializing KeyPairGenerator
keyGen.initialize(2048, random);
// Generate keys
keyPair = keyGen.generateKeyPair();
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
e.printStackTrace();
}
return keyPair;
}
public static void saveKeysToFiles(String path, PublicKey publicKey, PrivateKey privateKey) {
FileOutputStream fos = null;
try {
File file = new File(path + "/public.key");
if (file.createNewFile()) {
fos = new FileOutputStream(file);
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec(publicKey.getEncoded());
fos.write(x509EncodedKeySpec.getEncoded());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Private Key
try {
File file = new File(path + "/private.key");
if (file.createNewFile()) {
fos = new FileOutputStream(file);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec =
new PKCS8EncodedKeySpec(privateKey.getEncoded());
fos.write(pkcs8EncodedKeySpec.getEncoded());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static PublicKey loadPublicKey(String path, String algorithm) {
FileInputStream fis = null;
PublicKey publicKey = null;
try {
File file = new File(path + "/public.key");
fis = new FileInputStream(file);
byte[] encodedPublicKey = new byte[(int) file.length()];
fis.read(encodedPublicKey);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(encodedPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return publicKey;
}
public static PrivateKey loadPrivateKey(String path, String algorithm) {
FileInputStream fis = null;
PrivateKey privateKey = null;
try {
File file = new File(path + "/private.key");
fis = new FileInputStream(file);
byte[] encodedPrivateKey = new byte[(int) file.length()];
fis.read(encodedPrivateKey);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
privateKey = keyFactory.generatePrivate(privateKeySpec);
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return privateKey;
}
}
Output:
Decrypted text = This is a secret message
Symmetric Encryption Example
Here is a Java example code with methods - encrypt() method to encrypt a string and decrypt() method to decrypt the encrypted string:
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class CryptoManager {
//Key for encryption and decryption
public static final byte[] KEY =
{118, 106, 107, 122, 76, 99, 69, 83, 101, 103, 82, 101, 116, 75, 101, 127};
public static void main(String args[]) {
String salt = "HELLO";
String encryptedString = encrypt(salt, "HelloWorld12345");
System.out.println("Encripted string is " + encryptedString);
String decryptedString = decrypt(salt, encryptedString);
System.out.println("Decrypted string is " + decryptedString);
}
public static String encrypt(String salt, String plainText) {
if (plainText == null || plainText.isEmpty()) {
System.out.println("No data to encrypt!");
return plainText;
}
Cipher cipher = null;
String encryptedString = "";
try {
// Creating a Cipher object
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// Creating a secret key from KEY byte array
final SecretKeySpec secretKey = new SecretKeySpec(KEY, "AES");
// Initializing a Cipher object
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// Encrypting the plain text string
byte[] encryptedText = cipher.doFinal(salt.concat(plainText).getBytes());
// Encoding the encrypted text to Base64
encryptedString = Base64.getEncoder().encodeToString(encryptedText);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException ex) {
System.out.println("Exception caught while encrypting : " + ex);
}
return encryptedString;
}
public static String decrypt(String salt, String cipherText) {
if (cipherText == null || cipherText.isEmpty()) {
System.out.println("No data to decrypt!");
return cipherText;
}
String decryptedString = "";
Cipher cipher = null;
try {
// Creating a Cipher object
cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
// Creating a secret key from KEY byte array
final SecretKeySpec secretKey = new SecretKeySpec(KEY, "AES");
// Initializing a Cipher object
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// Decoding from Base64
byte[] encryptedText = Base64.getDecoder().decode(cipherText.getBytes());
// Decrypting to plain text
decryptedString = new String(cipher.doFinal(encryptedText));
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException ex) {
System.out.println("Exception caught while decrypting : " + ex);
}
return decryptedString.replace(salt, "");
}
}
Output:
Decrypted string is HelloWorld12345