RSA Encryption Implementation in Python

Introduction

Cryptography and computer network security have always been side interests for me. While reading about the RSA encryption technique in cryptography, I thought about writing an article on this amazing algorithm. Python is one of my favorite programming languages because of its simplicity, and implementing RSA Encryption using python will be fun. Let’s dive into the concepts of RSA encryption.

What is Encryption?

Encryption means encoding information. In technical terms, encryption is converting human-readable plaintext to alternative text, also known as ciphertext. Only authorized parties can decipher a ciphertext back to plaintext and access the original information.

RSA Encryption Implementation in Python
Encryption

What is RSA Encryption in python?

RSA abbreviation is Rivest–Shamir–Adleman. This algorithm is used by many companies to encrypt and decrypt messages. It is an asymmetric cryptographic algorithm which means that there are two different keys i.e., the public key and the private key. This is also known as public-key cryptography because one of the keys can be given to anyone. Companies such as Acer, Asus, HP, Lenovo, etc., use encryption techniques in their products.

Since this is asymmetric, nobody else except the browser can decrypt the data even if a third-party user has a public key in the browser.

RSA Encryption Implementation Without Using Library in Python

How does RSA algorith work?

Let us learn the mechanism behind RSA algorithm :

  1.  How to generate Public Key for encryption:
    1. Take two prime numbers such as 17 and 11.
    2. multiply the prime numbers and assign them to a variable. n= 7*11=77
    3. Assume a small exponent e which will lie between 1 to phi(n). Let us assume e=3

Now, we are ready with our public key(n = 77 and e = 3) .

Encryption:
memod(n) = 893mod 77 = 166 = c

import math

message = int(input("Enter the message to be encrypted: ")) 

p = 11
q = 7
e = 3

n = p*q

def encrypt(me):
    en = math.pow(me,e)
    c = en % n
    print("Encrypted Message is: ", c)
    return c

print("Original Message is: ", message)
c = encrypt(message)

OUTPUT:-

Enter the message to be encrypted: 89
Original Message is:  89
Encrypted Message is:  166

As you can see from the above, we have implemented the encryption of a message without using any library function. But as we are using python, we should take some advantage out of it. By this, I mean to say that we are having libraries available for the RSA implementation. Oh! Yeah, you heard it right.

RSA Encryption Implementation Using Library in Python

There are many libraries available in python for the encryption and decryption of a message, but today we will discuss an amazing library called pycryptodome.

The RSA algorithm provides:

  • Key-pair generation: generate a random private key and public key (the size is 1024-4096 bits).
  • Encryption: It encrypts a secret message (integer in the range [0…key_length]) using the public key and decrypts it back using the secret key.
  • Digital signatures: sign messages (using the private key) and verify message signature (using the public key).
  • Key exchange: It securely transports a secret key used for encrypted communication.

Before starting to code in python do not forget to install the library.

pip install pycryptodome

Now let’s understand how the RSA algorithms work by a simple example in Python. The below code will generate a random RSA key-pair, will encrypt a short message using the RSA-OAEP padding scheme.

RSA key generation

Now, let’s write the Python code. First, generate the RSA keys (1024-bit) and print them on the console as hex numbers and the PKCS#8 PEM ASN.1 format.

pip install pycryptodome

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii

keyPair = RSA.generate(3072)

pubKey = keyPair.publickey()
print(f"Public key:  (n={hex(pubKey.n)}, e={hex(pubKey.e)})")
pubKeyPEM = pubKey.exportKey()
print(pubKeyPEM.decode('ascii'))

print(f"Private key: (n={hex(pubKey.n)}, d={hex(keyPair.d)})")
privKeyPEM = keyPair.exportKey()
print(privKeyPEM.decode('ascii'))

#encryption
msg = 'A message for encryption'
encryptor = PKCS1_OAEP.new(pubKey)
encrypted = encryptor.encrypt(msg)
print("Encrypted:", binascii.hexlify(encrypted))

OUTPUT:-

Public key: (n=0x9a11485bccb9569410a848fb1afdf2a81b17c1fa9f9eb546fd1deb873b49b693a4edf20e36ffc3da9953657ef8bee80c49c2c12933c8a34804a00eb4c81248e01f, e=0x10001)
 -----BEGIN PUBLIC KEY-----
 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaEUhbzLlWlBCoSPsa/fKoGxfB
 +p+etUb9HeuHO0m2k
 -----END PUBLIC KEY-----
 Private key: (n=0x9a11485bccb9569410a848fb1afdf2a81b17c1fa9f9eb546fd1deb873b49b693a4edf20eb8362c085cd5b28ba109dbad2bd257a013f57f745402e245b0cc2d553c7b2b8dbba57ebda7f84cfb32b7d9c254f03dbd0188e4b8e40c47b64c1bd2572834b936ffc3da9953657ef8bee80c49c2c12933c8a34804a00eb4c81248e01f, d=0x318ab12be3cf0d4a1b7921cead454fcc42ba070462639483394d6fb9529547827e9c8d23517b5566dd3d3e5b16ec737987337a0e497fdba4b5ad97af41c1c3cdd87542a4637d81)

 -----BEGIN RSA PRIVATE KEY-----

 MIICXAIBAAKBgQCaEUhbzLlWlBCoSPsa/fKoGxfB+p+etUb9HeuHO0m2k6Tt8g64
 NiwIXNWyi6EJ260r0legE/V/dFQC4kWwzC1VPHsrjbulfr2n+Ez7MrfZwlTwPb0B
 iOS45AxHtkwb0lcoNLk2/8PamVNlfvi+6AxJwsEpM8ijSASgDrTIEkjgHwIDAQAB
 AoGAMYqxK+PPDUobeSHOrUVPzEK6BwRiY5SDOU1vuVKVR4J+nI0jspSo4B+KEBna
 NONQ8jB3QOBqJwvvH+ZG5q0hPjG1KP3V9dA+YzwHxEdV7WIqYp156CLAlevfnMgO
 UXtVZt09PlsW7HN5hzN6Dkl/26S1rZevQcHDzdh1QqRjfYECQQDGDUIQXlOiAcGo
 d5YqAGpWe0wzJ0UypeqZcqS9MVe9OkjjopCkkYntifdN/1oG7S/1KUMtLoGHqntb
 c428zOO/AkEAxyV0cmuJbFdfM0x2XhZ+ge/7putIx76RHDOjBpM6VQXpLEFj54kB
 qGLAB7SXr7P4AFrEjfckJOp2YMI5BreboQJAb3EUZHt/WeDdJLutzpKPQ3x7oykM
 wfQkbxXYZvD16u96BkT6WO/gCb6hXs05zj32x1/hgfHyRvGCGjKKZdtwpwJBAJ74
 y0g7h+wwoxJ0S1k4Y6yeQikxUVwCSBxXLCCnjr0ohsaJPJMrz2L30YtVInFkHOlL
 i/Q4AWZmtDDxWkx+bYECQG8e6bGoszuX5xjvhEBslIws9+nMzMuYBR8HvhLo58B5
 N8dk3nIsLs3UncKLiiWubMAciU5jUxZoqWpRXXwECKE=

 -----END RSA PRIVATE KEY-----

 Encrypted: b'99b331c4e1c8f3fa227aacd57c85f38b7b7461574701b427758ee4f94b1e07d791ab70b55d672ff55dbe133ac0bea16fc23ea84636365f605a9b645e0861ee11d68a7550be8eb35e85a4bde6d73b0b956d000866425511c7920cdc8a3786a4f1cb1986a875373975e158d74e11ad751594de593a35de765fe329c0d3dfbbfedc'

Explanation of the code

  1. Installed pycryptodome.
  2. As we are using the RSA algorithm, we need to import it from Crypto.PublicKey.
  3. We are also using the OAEP-Padding scheme. We have imported PKCS1_OAEP from Crypto.cipher.
  4. To convert binary to ASCII, we have imported binascii.
  5. Generating keypair values using RSA.generate.
  6. Generating publickey value
  7. Entering a message that is needed to be encrypted.
  8. Using encrypt function to encrypt the message.

As you can see after installing a library our work became very simpler and more efficient.

Also Read | Python SHA256: Implementation and Explanation

Conclusion

In today’s detailed discussion, we have covered almost everything about RSA encryption implementation using python. Starting from the basics to encryption, we have understood about RSA algorithm. We have implemented RSA using a library and without using a library. But I recommend using the library pycryptodome as it is more efficient.

Nowadays, almost every MNC uses encryption for their information as hacking is quite easy in today’s world. However, encryption of the information makes it a difficult task for hackers to understand the data.

If you have any doubts, feel free to comment down below. Till then, keep exploring our tutorials.

Subscribe
Notify of
guest
28 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
IOS
IOS
2 years ago

Hi, there!! Thank you… Looks nice. How to use it on files in a directory? How to encrypt and decrypt the files? How to encrypt a file and send it to someone else to decrypt it? May you send me some examples, please. Regards, IOS

Pratik Kinage
Admin
2 years ago
Reply to  IOS

Yes, you can easily do that with python. First of all, ask the receiver to generate RSA keys using publicKey, privateKey = rsa.newkeys(512). Then ask him for the public key and encrypt the file data using encMessage = rsa.encrypt(message.encode(), publicKey). Nextly, send him the encoded message where he’ll use his private key to decrypt the message. decMessage = rsa.decrypt(encMessage, privateKey).decode() can be used for the same. Please, note that after the creation of the private key, it shouldn’t be shared between sender and receiver to compromise the security.

In the case of files, you can read the file contents using file.read() method and then encrypt the whole content.

Eduardo
Eduardo
2 years ago

Hi, thank you for sharing this, just what i was looking for.
I installed the lib and when running this code, i get an error at this line:
encrypted = encryptor.encrypt(msg)

The error reads:
File “…..\PKCS1_OAEP.py”, line 121, in encrypt
  db = lHash + ps + b’\x01′ + _copy_bytes(None, None, message)
TypeError: can’t concat str to bytes
Would you be able to help with this?
Best regards!

Pratik Kinage
Admin
2 years ago
Reply to  Eduardo

This error is raised when there is a problem in converting strings to bytes. When you use a file as input, you can get this error more often due to different characters. You can use bytes of data to encrypt your message. The following example will help you –


data = b'Text to encrypt'

encryptor = PKCS1_OAEP.new(pubKey) encrypted = encryptor.encrypt(data) print("Encrypted:", binascii.hexlify(encrypted))

If you are taking input from a file, make sure you use ‘rb’ as file mode.
I hope this clarifies everything. Let me know if you have any other doubt!

Regards,
Pratik

John
John
2 years ago
Reply to  Pratik Kinage

I fix it by adding .encode() after msg in the encrypt() method. When I use an online RSA decryptor to try and decrypt the encrypted message with the private key is it never able to. How can I check the correctness of the encryption?

Pratik Kinage
Admin
2 years ago
Reply to  John

Yes, .encode() also works as it converts strings to bytes. RSA has different Cipher methods (RSA/ECB/PKCS1Padding is the most used one) which may prevent proper encryption and decryption when you change systems. To check the correctness, you may have to first check the key size, and matching public and private keys. Generally, remember that a public key is used to encrypt and a private key is used to decrypt.

Hope this helps. If not, please let me know!

Regards,
Pratik

monster
monster
2 years ago
Reply to  Eduardo

encrypted = encryptor.encrypt(msg.encode())

terry
terry
2 years ago

ITS NOT WORKING, there is no module named Crypto with an upper case C

ModuleNotFoundError: No module named ‘Crypto’

Python Pool
Admin
2 years ago
Reply to  terry

pip install pycryptodome will solve the issue.

terry
terry
2 years ago
Reply to  Python Pool

if we install pycryptodome as you suggested,
will it understand

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

this Crypto with uppercase C?

Python Pool
Admin
2 years ago
Reply to  terry

Yes it does. “Crypto” is included in pycryptodome.

Last edited 2 years ago by Python Pool
terry
terry
2 years ago
Reply to  Python Pool

we are using pycharm from jetbrains, it gives errors when we try to install pycryptodome… what we do? where can we run it so that pycryptodome will be installed and be available so the rest can execute as well?

Python Pool
Admin
2 years ago
Reply to  terry

I suggest you use normal Python installation from python.org then. Make sure you select the “Add to Path” option while selecting and after installing just run “pip install pycrytodome” and run the program by using “python “.

terry
terry
2 years ago
Reply to  Python Pool

it worked as you suggested, THANK YOU!

.py
.py
2 years ago

How do you decrypt the data without using a library? and are the original numbers 7 and 11 the private key?

Python Pool
Admin
2 years ago
Reply to  .py

Using a library would be the best and safest way to do it. In cryptography don’t try to reinvent the wheel. I’ll give you errors and risks 🙂

Regards,
Pratik

BISWAJYOTI SINGH
BISWAJYOTI SINGH
2 years ago

How we can apply this on an image ?

Pratik Kinage
Admin
2 years ago

I’d suggest you read the image as a byte and then try to encrypt the byte array. You might need to change the values of a few byte characters as they need to be less than the value of Modulo.

Regards,
Pratik

cheez
cheez
2 years ago

How can we decrypt encrypted message?

Pratik Kinage
Admin
2 years ago
Reply to  cheez

You can use keyPair.decrypt(encrypted) to decrypt the message.

Regards,
Pratik

cheez
cheez
2 years ago
Reply to  Pratik Kinage

NotImplementedError: Use module Crypto.Cipher.PKCS1_OAEP instead

Pratik Kinage
Admin
2 years ago
Reply to  cheez

Try using:

decryptor = PKCS1_OAEP.new(key)
decrypted = decryptor.decrypt(ast.literal_eval(str(encrypted)))

cheez
cheez
2 years ago
Reply to  Pratik Kinage

  modBits = Crypto.Util.number.size(self._key.n)
AttributeError: ‘bytes’ object has no attribute ‘n’

Pratik Kinage
Admin
2 years ago
Reply to  cheez

Which public-key are you using? It should be the recipient’s public key.

jap
jap
2 years ago

Hi.. how we can find memory usage of this program in python.

how can we use profiler as no definition is there.. any other suggestions

Pratik Kinage
Admin
1 year ago
Reply to  jap

You can use memory_profiler to check the memory consumption of this program. More info can be found on Github.

kush
kush
1 year ago

How to encrypt the random key using cryptography instead of pycryptodome

Pratik Kinage
Admin
1 year ago
Reply to  kush

You can always generate a key in cryptography using Fernet.generate_key(). And then use the key to encrypt the message.