Introduction to RSA in Java

April 21, 2021 No comments Java RSA Security cryptography

1. Introduction

The RSA (Rivest–Shamir–Adleman) is an asymmetric cryptography algorithm based on a pair of keys: Public and Private. The public key could be shared by everyone, it is used for encrypting the data. The private key should be kept private as the name said. It is used for decrypting the data.

The acronym RSA comes from the surnames of Ron Rivest, Adi Shamir, and Leonard Adleman, who publicly described the algorithm in 1977.

In this article, we are going to present how to generate, save and use RSA keys in Java.

2. RSA Key Pair

Let's start with generating RSA keys, using pure Java.

KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);

KeyPair pair = generator.generateKeyPair();

This code will generate a pair of RSA keys with size 1024 bits in two steps:

  • first, we must create a KeyPairGenerator instance by calling the method getInstance(...) with the RSA algorithm as a parameter,
  • next, we need to initialize the KeyPairGenerator by calling the initialize() method.

To get public and private key from KeyPair we need to use the following code:

PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();

System.out.println(privateKey.getFormat());
System.out.println(publicKey.getFormat());

System.out.println(privateKey.getAlgorithm());
System.out.println(publicKey.getAlgorithm());

The output:

PKCS#8
X.509
RSA
RSA

In that output we have:

  • X.509 - means that this certificate contains information about the identity to which a certificate is issued and the identity that issued it,
  • PKCS#8 - this is the standard for storing private key information.

3. Save Private Key and Public Key in files

Actually, generated certificates are just arrays of bytes, so we could use any method available in Java to convert byte array to a file.

In the following example we used FileOutputStream to write bytes into an output file:

try (FileOutputStream fos = new FileOutputStream("/tmp/public.key")) {
    fos.write(publicKey.getEncoded());
}

try (FileOutputStream fos = new FileOutputStream("/tmp/private.key")) {
    fos.write(privateKey.getEncoded());
}

We could use an application such as KeyStore Explorer to confirm that certificates have been generated and saved in files correctly.

Private Key: Rsa private key

Public Key: Rsa public key

4. Encrypt and decrypt strings

Let's use our certificates to encrypt and decrypt a simple string.

4.1. Encrypting

In order to encrypt a string using a public key, we need to create an instance of the Cipher object.

To create a Cipher object, we must use the getInstance(...) method, and pass the name of the requested transformation to it.

In the next step, we invoke the doFinal(...) method to encrypt our string. This method takes byte array so we need to convert our string to bytes.

String str = "FrontBackend.com";

Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

byte[] secredMsg = str.getBytes(StandardCharsets.UTF_8);
byte[] encryptedMsg = encryptCipher.doFinal(secredMsg);

String encodedMessage = Base64.getEncoder().encodeToString(encryptedMsg);

Note that, doFinal(...) returns bytes array, so in order to present the result we could use Base64 responsible for converting bytes into a string.

4.2. Decrypting

Let's check if our encrypted string is correct. We will do it by decrypting it using the private.key.

String with a new Cipher instance but in this case dedicated for the private certificate:

To decrypt we also use the doFinal(...) method.

Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);

byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMsg);
String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);

System.out.println(decryptedMessage);

The output:

FrontBackend.com

The output confirms that certificates are generated correctly.

5. Encrypt and decrypt files

Encrypting and decrypting files using our private/public RSA keys are similar to encrypting/decrypting strings but in this case, the first step will be reading bytes from a file.

byte[] fileBytes = Files.readAllBytes(Paths.get("/tmp/file.to.encrypt"));

When we have byte array we could do steps like in the previous point:

Cipher encryptFileCipher = Cipher.getInstance("RSA");
encryptFileCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedFile = encryptCipher.doFinal(fileBytes);

Cipher decryptFileCipher = Cipher.getInstance("RSA");
decryptFileCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFile);

6. Conclusion

In this short tutorial, we presented how to start working on RSA keys in Java. How to create them and use them for encryption and decryption of the data.

As usual, the source code is available on our GitHub.

{{ message }}

{{ 'Comments are closed.' | trans }}