Cryptography - RSA Decryption



In this article we have to implement decryption of RSA Cipher using different technologies. As you may know, Decryption is the process of changing the encrypted message (ciphertext) back into its original form (plaintext) with the help of the private key in asymmetric key cryptography. Or we can say decryption is the technique to find the original message of the encrypted message.

Steps for Decryption

We can decrypt the message which is encrypted using RSA encryption using the following steps −

  • Receiving the Ciphertext − The receiver gets a scrambled message (ciphertext) that was encrypted using their publicly available key.
  • Using the Private Key − The receiver uses a secret key (private key) to unscramble the ciphertext. This secret key was created alongside the public key during a special setup.
  • Performing the Decryption − To unscramble the message, the receiver uses a complex mathematical operation involving the secret key and large numbers, effectively reversing the encryption process. This results in numerical representations of the original message.
  • Converting to Plaintext − The numerical representations are then converted back into the original message content.

Implementation of Decryption in Python

RSA decryption can be created with the help of different methods like −

  • Using modular arithmetic and number theory
  • Using the RSA module
  • Using the cryptography module

To help you understand RSA decryption, Python programming and functions better, we will discuss each of these ways in depth in the sections below.

Using modular arithmetic and number theory

In this program we will use modular arithmetic and number theory to decrypt the message. In our code, the decrypt() function takes a private key and a ciphertext message as input. Decrypting the ciphertext involves raising each number in the ciphertext to the power specified by the "d" exponent. Applying a "mod n" calculation (a mathematical operation). Convert the resulting numbers back into characters using the "chr" function. Combine these characters to obtain the decrypted message (plaintext).

Example

Following is a python program to for RSA decryption using modular arithmetic and number theory −

import random

def gcd(a, b):
   while b != 0:
      a, b = b, a % b
   return a

def extended_gcd(a, b):
   if a == 0:
      return (b, 0, 1)
   else:
      g, y, x = extended_gcd(b % a, a)
      return (g, x - (b // a) * y, y)

def mod_inverse(a, m):
   g, x, y = extended_gcd(a, m)
   if g != 1:
      raise Exception('Modular inverse does not exist')
   else:
      return x % m

def generate_keypair():
   p = random.randint(100, 1000)
   q = random.randint(100, 1000)
   n = p * q
   phi = (p - 1) * (q - 1)

   while True:
      e = random.randint(2, phi - 1)
      if gcd(e, phi) == 1:
         break
    
   d = mod_inverse(e, phi)
   return ((e, n), (d, n))

def encrypt(public_key, plaintext):
   e, n = public_key
   cipher = [pow(ord(char), e, n) for char in plaintext]
   return cipher

def decrypt(private_key, ciphertext):
   d, n = private_key
   plain = [chr(pow(char, d, n)) for char in ciphertext]
   return ''.join(plain)

# our keys
public_key, private_key = generate_keypair()
# plaintext
message = "Hello, world!"
encrypted_message = encrypt(public_key, message)
print("Encrypted message:", encrypted_message)
decrypted_message = decrypt(private_key, encrypted_message)
print("Decrypted message:", decrypted_message)

Following is the output of the above example −

Input/Output

Encrypted message: [5133, 206, 9012, 9012, 7041, 3509, 7193, 3479, 7041, 6939, 9012, 1255, 3267]
Decrypted message:  Hello, world!

Using the rsa module

The RSA algorithm can be easily and efficiently implemented using Python's rsa package. First, if you do not have already installed the rsa module then you can install it with the help of pip - pip install rsa. So first we need to generate keys and then we will decrypt the encrypted message.

Generating RSA Keys

After installing the module you can generate RSA key pairs with the help of this rsa module. Here is how −

Example
import rsa
# create a key pair with 1024 bits key length
(public_key, private_key) = rsa.newkeys(1024)

The code will generate a pair of RSA keys: one for encryption (the public key) and the other one for decryption (the private key).

Decrypting the Messages

When you have the key pair, you can use them to decrypt messages.

# Encrypting a message
message = b"Hello, world!"
encrypted_message = rsa.encrypt(message, public_key)

# Decrypting the message
decrypted_message = rsa.decrypt(encrypted_message, private_key)

print("Encrypted message:", encrypted_message)
print("Decrypted message:", decrypted_message.decode()) 

Complete code

Following is the python code for your reference. So run the code and see the output −

Example
import rsa
# create a key pair with 1024 bits key length
(public_key, private_key) = rsa.newkeys(1024)

# Encrypting a message
message = b"Hello, world!"
encrypted_message = rsa.encrypt(message, public_key)

# Decrypting the message
decrypted_message = rsa.decrypt(encrypted_message, private_key)

print("Encrypted message:", encrypted_message)
print("Decrypted message:", decrypted_message.decode())  

Following is the output of the above example −

Input/Output
Encrypted message: b'+.}a\n\xda8\x83\xf7D\x0eI\xc1\xde\x9cZ\xd7\xf2\xdd}\xb0\xd4N\x9e\x1cjm\xe3\x12\xea\x95\n8\x87a\x16Y\xb6\x7f\x9ar\xf3\xd6\xe6le\xda1\xa7{\xa1\xa4\t/q\xea\x19*q\xc5[\x87\x1b\xc0\x8f%\x83\xa1KFx\xe6m\x97\x8ef\x84\xaf\xe7\xdc\xcf\xd0\xe4\x80H!\xce\xef\x13\xc5\x93\xc3a\xc0Pv\x07tQx_\xbc\xaeQ[x:\xf3\x19\xa2\xea]\xf2\x1e\x9e9\x10\xed\xf2\x83\x15W}\xbb\x89\xd7\xf6\xee'
Decrypted message: Hello, world!

Using the cryptography module

Using the cryptography module, we can create RSA key pairs. This code creates a private RSA key and extracts its corresponding public key. The keys are converted to the PEM format and saved in different files. We can use these keys to encrypt and decrypt messages. The given code shows how the private key is used for decryption.

Example

Following is a python implementation for RSA Decryption using cryptography module −

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

# Generate an RSA private key
private_key = rsa.generate_private_key(
   public_exponent=65537,
   key_size=2048,
   backend=default_backend()
)

# Get the public key from the private key
public_key = private_key.public_key()

# Serialize the keys to PEM format
private_key_pem = private_key.private_bytes(
   encoding=serialization.Encoding.PEM,
   format=serialization.PrivateFormat.PKCS8,
   encryption_algorithm=serialization.NoEncryption()
)
public_key_pem = public_key.public_bytes(
   encoding=serialization.Encoding.PEM,
   format=serialization.PublicFormat.SubjectPublicKeyInfo
)

# Save the keys to files or use them as needed
with open('private_key.pem', 'wb') as f:
   f.write(private_key_pem)

with open('public_key.pem', 'wb') as f:
   f.write(public_key_pem)

# Encrypting a message
message = b"Hello, world!"
encrypted_message = public_key.encrypt(
   message,
   padding.OAEP(
      mgf=padding.MGF1(algorithm=hashes.SHA256()),
      algorithm=hashes.SHA256(),
      label=None
   )
)

# Decrypting the message
decrypted_message = private_key.decrypt(
   encrypted_message,
   padding.OAEP(
      mgf=padding.MGF1(algorithm=hashes.SHA256()),
      algorithm=hashes.SHA256(),
      label=None
   )
)

print("Encrypted message:", encrypted_message)
print("Decrypted message:", decrypted_message.decode())

Following is the output of the above example −

Input/Output
Encrypted message: b'\xae\xdd\xaa\x16\xd5\x9e\x06N\xf7\x96\xd6\xd6\x02\x8b\xcb\xdf\x12eds\t\x1a\xa9\xb6\xe3\xc4vZ\x05\xbe\xbf$\xef\xaa\xcfqo\xc0\x8fI\x80\xb3\xea\xb6\x04\xf8\xc6\x05\xaa\x1dH\xc1J{=\x15\xe1\xef\xcbnA\xfb\x98m.\xa7\x9c\x05\x0f\x07z\x02(\x10\xae\xaf\xccv\x8a\x8f\x97\'f-\xccFU\xf8\x188\xe7\xe5I\xcc\x88\n_\xa6w\x86\x9b\x03\xc7\x96t\xca\xdb\x102O#\x94\xd0\xbe\xba\x8d\xce\x80V*l\xb5"\xdf~\x86\xe6\xf6\x08\x18\xcf\xd8\x866\x88\xe3x\x17\xebhD\xdb\xa8\x02\xa1\xd9{\xaf~\xe4\xd7[\x9c+\xcc\t\x15\x8ej\xe2\xe5b\xdf\xeb\xd0|\x82\xea\xce,p.\xf5\xd6\x0e\x01\xb9\xcb\x17\xe6\x05\xea\xe4\xb0\xa4\xc8\x9a\xc4\x822\xd1v\x8a\xa6\x85{x\xf9\x81r\xa2S\xe1\xe7l\xccwE\x16f\x1e\xfbE\x1e\xaf|\xc3\x91\x93\x99|\x99\xba\xcf\x00\xb3D\xfaq\xc3<\x8dj\x06\\L\x06{\x10\xaf7\xfa^\xa5\x87E\xbb\x8c\x9e\xd7eU\x07\xf3lk'
Decrypted message: Hello, world!

Implementation of RSA Decryption using Java

The below Java code uses the RSA encryption algorithm to decrypt the given message. The code uses different libraries of Java to decrypt the message.

Example

The implementation of RSA decryption process using Java is as following:

import java.math.BigInteger;
import java.security.SecureRandom;

public class RSA {

   private BigInteger prKey;
   private BigInteger pubKey;
   private BigInteger mod;

   // Generate public and private keys
   public RSA(int bitLength) {
      SecureRandom random = new SecureRandom();
      BigInteger p = BigInteger.probablePrime(bitLength / 2, random);
      BigInteger q = BigInteger.probablePrime(bitLength / 2, random);
      mod = p.multiply(q);
      BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
      pubKey = BigInteger.probablePrime(bitLength / 4, random);
      while (phi.gcd(pubKey).intValue() > 1) {
         pubKey = pubKey.add(BigInteger.ONE);
      }
      prKey = pubKey.modInverse(phi);
   }

   // Encrypt plaintext
   public BigInteger encrypt(String message) {
      BigInteger plaintext = new BigInteger(message.getBytes());
      return plaintext.modPow(pubKey, mod);
   }

   // Decrypt ciphertext
   public String decrypt(BigInteger encryptedMessage) {
      BigInteger decrypted = encryptedMessage.modPow(prKey, mod);
      return new String(decrypted.toByteArray());
   }

   public static void main(String[] args) {
      RSA rsa = new RSA(1024);

      // Message to encrypt
      String plaintext = "HELLO TUTORIALSPOINT";

      // Encrypt the message
      BigInteger ciphertext = rsa.encrypt(plaintext);
      System.out.println("Encrypted Message: " + ciphertext);

      // Decrypt the ciphertext
      String decryptedMessage = rsa.decrypt(ciphertext);
      System.out.println("Decrypted Message: " + decryptedMessage);
   }
}

Following is the output of the above example −

Input/Output

Encrypted Message: 81613159022598431502618861082122488243352277400520456503112436392671015741839175478780136032663342240432362810242747991048788272007296529186453061811896882040496871941396445756607265971854347817972502178724652319503362063137755270102568091525122886513678255187855721468502781772407941859987159924896465083062
Decrypted Message: HELLO TUTORIALSPOINT

Implementation of RSA Decryption using C++

Below is a simple implementation of the RSA algorithm to decrypt the message with the help of C++. The code for decryption of the given message is as follows −

Example

#include<iostream>
#include<math.h>
using namespace std;
// find gcd
int gcd(int a, int b) {
   int t;
   while(1) {
      t= a%b;
      if(t==0)
      return b;
      a = b;
      b= t;
   }
}
int main() {
   //2 random prime numbers
   double p = 13;
   double q = 11;
   double n=p*q;//calculate n
   double track;
   double phi= (p-1)*(q-1);//calculate phi
   //public key
   //e stands for encrypt
   double e=7;
   //for checking that 1 < e < phi(n) and gcd(e, phi(n)) = 1; i.e., e and phi(n) are coprime.
   while(e<phi) {
      track = gcd(e,phi);
      if(track==1)
         break;
      else
         e++;
   }
   //private key
   //d stands for decrypt
   //choosing d such that it satisfies d*e = 1 mod phi
   double d1=1/e;
   double d=fmod(d1,phi);
   double message = 9;
   double c = pow(message,e); //encrypt the message
   double m = pow(c,d);
   c=fmod(c,n);
   m=fmod(m,n);
   cout<<"\n"<<"Encrypted message = "<<c;
   cout<<"\n"<<"Decrypted message = "<<m;
   return 0;
}

Following is the output of the above example −

Input/Output

Encrypted message = 48
Decrypted Message = 9

Summary

RSA works by creating unique public and private key pairs, establishing a secure channel for communication. These keys are utilized to encrypt and decrypt messages, guaranteeing that only authorized users can decipher the information.

In Python, RSA decryption can be implemented through various approaches. Using modular arithmetic and number theory, while the RSA module offers more specialized functionality. The cryptography module also supports RSA encryption and decryption, offering a comprehensive set of features. Developers can choose the method that best aligns with their requirements.

Also we have developed the code for RSA decryption using Java and C++.

Advertisements