How to use RSA public key to decrypt ciphertext in Python?

RSA public key decryption is an unreasonable design. But now I do need it :joy:

1 Like

Can you give more details about what you’re doing? Are you using a particular cryptography library (if so, which one?), or is this a toy implementation for educational / learning purposes? What form does the ciphertext take? If it’s a string, how has it been converted from the integer or integer stream that RSA operates on (and how was the original plaintext converted to such an integer)?

Can you show us the code that you’re using to do the encryption? That would answer a lot of questions.

1 Like

Why is it unreasonable? It’s just a process, a fixed set of steps you follow, depending on the specific library you used to run it. The details depend on what type of ciphertext you have, as well as how secure your process must be against attacks. A toy project has very different requirements from software that is entrusted to handle monetary transfers, for example.

A good library will include examples of how to use it. For example, the cryptography package includes a RSA decryption example, which uses an existing private_key variable to decrypt ciphertext, given (in addition to the ciphertext) a padding configuration. The latter is necessary because there are multiple ways you can pad out encrypted data to fixed-length blocks.

1 Like

thanks @mjpieters @mdickinson
I use this library. https://pypi.org/project/rsa/
I am not very good at English. I try to use code to describe my purpose

import rsa
import base64

# Private key decryption
def fun1():
    publicKey, privateKey = rsa.newkeys(512)
    cipher = rsa.encrypt(b'Hello World!', publicKey)
    base64Text = base64.b64encode(cipher).decode()

    print(base64Text)

    text = rsa.decrypt(base64.b64decode(base64Text.encode()), privateKey)
    print(text.decode())

# Public key decryption
def fun2():
    publicKey, privateKey = rsa.newkeys(512)
    cipher = rsa.encrypt(b'Hello World!', privateKey)
    base64Text = base64.b64encode(cipher).decode()

    print(base64Text)

    text = rsa.decrypt(base64.b64decode(base64Text.encode()), publicKey) # AttributeError: 'PublicKey' object has no attribute 'blinded_decrypt'
    print(text.decode())


fun1() # success
fun2() # fail

Is there something wrong with my operation? I learned about this problem in search engine. Many people say that RSA private key encryption has some security problems. So this library does not have this API .

1 Like

Don’t try to use a public RSA key to decrypt, and by extension, don’t try to use a private RSA key to encrypt:

Is RSA encryption with a private key the same as signature generation?

RSA encryption can only be performed with an RSA public key according to the RSA standard.

bold emphasis mine.

The library you are using already has a (closed) ticket on the same attribute error: rsa.encrypt() function, can not encrypt a text with private key · Issue #92 · sybrenstuvel/python-rsa · GitHub. While technically speaking generating a signature with the public key constitutes encryption, there are enough differences in how public and private keys are used that it is not surprising that this library doesn’t support explicitly using the private key to encrypt with.

You see this in other implementations too. The cryptography library delegates encryption, decryption, signing and verification to the key instance, but only the RSA public key class can encrypt and verify, and the only private key can decrypt and sign.

And the PyCryptodome library includes a handy table to explain how to use public and private keys:

Algorithm Sender uses… Receiver uses…
Encryption Public key Private key
Signature Private key Public key

It is hugely important to keep your private key secret. The public key, on the other hand, is assumed to be public, and so doesn’t need special care. The special care RSA cryptography implementations should take to protect your private key is expensive in terms of software development time and verification that your private key is kept secure from prying eyes, so this care is often not applied to code paths that are meant to only be used with a public key. This means that using your private key where a public key is expected can lead to your private key being leaked to attackers.

2 Likes

Thank you very much for your serious answer!

1 Like

Was this intended to be “Don’t try to use a public RSA key to decrypt”?

2 Likes

Yes, or rather, don’t try to use a private RSA key to encrypt. Or both. :slight_smile: I’ve corrected the post, thanks for pointing that out!

3 Likes

@mjpieters

i got some errors in this code, could you solve it.
i am taking input from user and encrypt it with help of rsa python library and save it in a csv using pandas, when i decrypt the saved data, it shows error, this will not occur while encrypting data with same attributes.

import rsa
from base64 import b64encode, b64decode
import pandas as pd

key = int(input("\nenter an interger key value : ")) #512

option = int(input('[1] to add data \n[2] to search data : '))

publicKey, privateKey = rsa.newkeys(key)



if option == 1:

        paasword = input("\ninput : ")
          
        encpass = rsa.encrypt(paasword.encode(),publicKey)

        print("\noriginal string: ", paasword)
        print("\nencrypted string: ", encpass)

        # Encode encrypted password to base64 and produce UTF-8 conform string
        b64_enc_pass = b64encode(encpass).decode()

        print("\nencoded string: ", b64_enc_pass)

        # Save to New CSV file
        data={'Name':['Jhon'], 'Password':[b64_enc_pass], } #new dict
        df = pd.DataFrame(data) # create new pandas DataFrame

        df.to_csv('my_data.csv', index=False) # write a new csv file

if option == 2:
    
        # Extract form CSV file

        df = pd.read_csv("my_data.csv",index_col = 0) #using 0th column (Name) as index
        find_password = df['Password']['Jhon'] #column id , index of that row;

        print("\nencoded string: ", find_password)

        # Decode encrypted password from UTF-8 encoded string
        find_password = b64decode(find_password.encode())

        print("\nencrypted string: ", find_password)

        decpass = rsa.decrypt(find_password, privateKey).decode()
        print("\ndecrypted string: ", decpass)

        out_data = {'Name':['Jhon'], 'Password':[decpass]}
        df = pd.DataFrame(out_data)
        print(df)
> enter an interger key value : 519
> [1] to add data 
> [2] to search data : 2
> encoded string: JFPAypbL7voE+3x9h4R/OsHr/racq.....................
> encrypted string:  b'$S\xc0\xca\x96\xcb\xee\..................................................
> DecryptionError: Decryption failed

Here I have two conditions [1] to add data into csv file and [2] to extract it from csv, simultaneously I encrypt and decrypt data, according to need