It is as you say indeed possible to encrypt with private and decrypt with public, the mathematical symmetry in RSA allows just swapping e/d in the keys and then calling the encrypt/decrypt functions.

This being said, I want to emphasize that I'm not a crypto expert and cannot say for certain that this doesn't compromise security.

So, you could extend the RSA-Key class with that swapped logic, use blackmagic to swap the implementation of the loaded key, and pass it to the normal functions:

from Crypto.PublicKey.RSA import RsaKey
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Math.Numbers import Integer

class SwappedRsaKey(RsaKey):
    def _encrypt(self, plaintext):
        # normally encrypt is p^e%n
        return int(pow(Integer(plaintext), self._d, self._n))
    def _decrypt(self, ciphertext):
        # normally decrypt is c^d%n
        return int(pow(Integer(ciphertext), self._e, self._n))

data = "I met aliens in UFO. Here is the map.".encode("utf-8")

# It's important to also use our swapped logic in encryption step, otherwise the lib would still use e&n (the private contains all 3 values).

private_key = RSA.import_key(open("mykey.pem").read())
private_key.__class__ = SwappedRsaKey
public_key = RSA.import_key(open("mykey.pub").read())
public_key.__class__ = SwappedRsaKey

cipher_priv = PKCS1_OAEP.new(private_key)
cipher_pub = PKCS1_OAEP.new(public_key)

enc_data = cipher_priv.encrypt(data)

# Decrypt again, just a showcase to prove we can get the value back
dec_data = cipher_pub.decrypt(enc_data)

print(dec_data.decode("utf-8"))
Answer from Tobias K. on Stack Overflow
🌐
PyPI
pypi.org › project › rsa
rsa · PyPI
Python-RSA is a pure-Python RSA implementation. It supports encryption and decryption, signing and verifying signatures, and key generation according to PKCS#1 version 1.5. It can be used as a Python library as well as on the commandline.
      » pip install rsa
    
Published   Apr 16, 2025
Version   4.9.1
🌐
Cryptography
cryptography.io › en › latest › hazmat › primitives › asymmetric › rsa
RSA — Cryptography 47.0.0.dev1 documentation
Generates a new RSA private key. key_size describes how many bits long the key should be. Larger keys provide more security; currently 1024 and below are considered breakable while 2048 or 4096 are reasonable default key sizes for new keys. The public_exponent indicates what one mathematical ...
🌐
PyCryptodome
pycryptodome.readthedocs.io › en › latest › src › public_key › rsa.html
RSA — PyCryptodome 3.23.0 documentation
RSA modulus n. Public exponent e. Private exponent d. Only required if the key is private. First factor of n (p). Optional, but the other factor q must also be present. Second factor of n (q). Optional. CRT coefficient q, that is \(p^{-1} \text{mod }q\). Optional. Keyword Arguments: consistency_check (boolean) – If True, the library will verify that the provided components fulfil the main RSA properties.
🌐
Medium
medium.com › coinmonks › rsa-encryption-and-decryption-with-pythons-pycryptodome-library-94f28a6a1816
RSA Encryption and Decryption with Python’s pycryptodome Library | by Miyoko Shimura | Coinmonks | Medium
November 9, 2024 - The pycryptodome library serves as a comprehensive Python package of low-level cryptographic primitives. To install it, run the following commands. # Step 1: Install pycryptodome package !pip install pycryptodome # Import necessary modules from pycryptodome from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP # This module converts binary data to hexadecimal from binascii import hexlify
Top answer
1 of 2
2

It is as you say indeed possible to encrypt with private and decrypt with public, the mathematical symmetry in RSA allows just swapping e/d in the keys and then calling the encrypt/decrypt functions.

This being said, I want to emphasize that I'm not a crypto expert and cannot say for certain that this doesn't compromise security.

So, you could extend the RSA-Key class with that swapped logic, use blackmagic to swap the implementation of the loaded key, and pass it to the normal functions:

from Crypto.PublicKey.RSA import RsaKey
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Math.Numbers import Integer

class SwappedRsaKey(RsaKey):
    def _encrypt(self, plaintext):
        # normally encrypt is p^e%n
        return int(pow(Integer(plaintext), self._d, self._n))
    def _decrypt(self, ciphertext):
        # normally decrypt is c^d%n
        return int(pow(Integer(ciphertext), self._e, self._n))

data = "I met aliens in UFO. Here is the map.".encode("utf-8")

# It's important to also use our swapped logic in encryption step, otherwise the lib would still use e&n (the private contains all 3 values).

private_key = RSA.import_key(open("mykey.pem").read())
private_key.__class__ = SwappedRsaKey
public_key = RSA.import_key(open("mykey.pub").read())
public_key.__class__ = SwappedRsaKey

cipher_priv = PKCS1_OAEP.new(private_key)
cipher_pub = PKCS1_OAEP.new(public_key)

enc_data = cipher_priv.encrypt(data)

# Decrypt again, just a showcase to prove we can get the value back
dec_data = cipher_pub.decrypt(enc_data)

print(dec_data.decode("utf-8"))
2 of 2
1

First of all, big thanks to Tobias K. for the short and clear answer. It worked flawlessly.

But when I tried to decrypt the server messages, pycryptodome kept returning sentinel instead of decrypted data. I decided to look into the library source code, and check what would .decrypt() return if I comment out this lines in .../Crypto/Cipher/PKCS1_v_1_5.py:

if  not em.startswith(b'\x00\x02') or sep < 10:
    return sentinel

And to my surprise it returned the decrypted message! Not sure that I didn't break something, but it works. I guess it was a bug? This is aleready fixed in their github repo, but the version is not released yet

🌐
CircuitPython
docs.circuitpython.org › projects › rsa › en › latest
Introduction — Adafruit RSA Library 1.0 documentation
RSA implementation based on Sybren A. Stüvel’s python-rsa pure-python RSA implementation. ... Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading the Adafruit library and driver bundle.
🌐
dr. Sybren
stuvel.eu › software › rsa
Python-RSA | dr. Sybren
Python-RSA has extensive documentation with plenty of code examples, interoperation with OpenSSL and more goodies. This software was originally written by Sybren Stüvel, Marloes de Boer, and Ivo Tamboer. It was subsequenty improved by Sybren Stüvel, Barry Mead, Yesudeep Mangalapilly, and others. According to the PyPi Stats page, at least at the moment of writing, this library ...
Find elsewhere
🌐
Stuvel
stuvel.eu › python-rsa-doc › usage.html
5. Usage — Python-RSA 4.8 documentation
The most common way to use RSA with larger files uses a block cypher like AES or DES3 to encrypt the file with a random key, then encrypt the random key with RSA. You would send the encrypted file along with the encrypted key to the recipient. The complete flow is: ... Use that key to encrypt the file with AES. ... The recipient now reverses this process to obtain the encrypted file. ... The Python-RSA module does not contain functionality to do the AES encryption for you.
🌐
GitHub
github.com › deepin-community › python-rsa
GitHub - deepin-community/python-rsa
Python-RSA is a pure-Python RSA implementation. It supports encryption and decryption, signing and verifying signatures, and key generation according to PKCS#1 version 1.5. It can be used as a Python library as well as on the commandline.
Author   deepin-community
🌐
GitHub
github.com › sybrenstuvel › python-rsa
GitHub - sybrenstuvel/python-rsa: Python-RSA is a pure-Python RSA implementation. · GitHub
April 20, 2025 - Python-RSA is a pure-Python RSA implementation. It supports encryption and decryption, signing and verifying signatures, and key generation according to PKCS#1 version 1.5. It can be used as a Python library as well as on the commandline.
Starred by 491 users
Forked by 125 users
Languages   Python 99.6% | Shell 0.4%
🌐
PyPI
pypi.org › project › rsa-python
rsa-python · PyPI
February 23, 2022 - Functions included are generate_key_pair(bits) which returns a dictionary containing p, q, phi, public, private, modulus, and the time it took to generate the key pair ("time"). encrpyt(message, encryption_key, modulus) to encrypt a message, and decrypt(cipher, decryption_key, modulus) to decrypt a cipher. To install the module, run pip install rsa_python.
      » pip install rsa-python
    
Published   Feb 23, 2022
Version   0.1.1
Top answer
1 of 7
56

In order to make it work you need to convert key from str to tuple before decryption(ast.literal_eval function). Here is fixed code:

import Crypto
from Crypto.PublicKey import RSA
from Crypto import Random
import ast

random_generator = Random.new().read
key = RSA.generate(1024, random_generator) #generate pub and priv key

publickey = key.publickey() # pub key export for exchange

encrypted = publickey.encrypt('encrypt this message', 32)
#message to encrypt is in the above line 'encrypt this message'

print('encrypted message:', encrypted) #ciphertext
f = open ('encryption.txt', 'w')
f.write(str(encrypted)) #write ciphertext to file
f.close()

#decrypted code below

f = open('encryption.txt', 'r')
message = f.read()


decrypted = key.decrypt(ast.literal_eval(str(encrypted)))

print('decrypted', decrypted)

f = open ('encryption.txt', 'w')
f.write(str(message))
f.write(str(decrypted))
f.close()
2 of 7
14

PKCS#1 OAEP is an asymmetric cipher based on RSA and the OAEP padding

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


def rsa_encrypt_decrypt():
    key = RSA.generate(2048)
    private_key = key.export_key('PEM')
    public_key = key.publickey().exportKey('PEM')
    message = input('plain text for RSA encryption and decryption:')
    message = str.encode(message)

    rsa_public_key = RSA.importKey(public_key)
    rsa_public_key = PKCS1_OAEP.new(rsa_public_key)
    encrypted_text = rsa_public_key.encrypt(message)
    #encrypted_text = b64encode(encrypted_text)

    print('your encrypted_text is : {}'.format(encrypted_text))


    rsa_private_key = RSA.importKey(private_key)
    rsa_private_key = PKCS1_OAEP.new(rsa_private_key)
    decrypted_text = rsa_private_key.decrypt(encrypted_text)

    print('your decrypted_text is : {}'.format(decrypted_text))
🌐
GitHub
github.com › awnonbhowmik › RSA-Python
GitHub - awnonbhowmik/RSA-Python: The RSA algorithm coded in Python · GitHub
A Python implementation of the RSA public-key cryptosystem, demonstrating key generation, encryption, and decryption from scratch using only the standard library.
Starred by 36 users
Forked by 10 users
Languages   Python
🌐
GitHub
gist.github.com › gabrielfalcao › de82a468e62e73805c59af620904c124
Using python cryptography module to generate an RSA keypair, serialize, deserialize the keys and perform encryption and decryption · GitHub
Using python cryptography module to generate an RSA keypair, serialize, deserialize the keys and perform encryption and decryption - rsa_encryption.py
🌐
Medium
medium.com › @prakritithapat › hands-on-encryption-implementing-rsa-in-pythonintroduction-a4a9c97fe94f
Hands-On Encryption: Implementing RSA in Python | by Prakriti Thapa | Medium
April 2, 2025 - Users have a pair of public and private keys and the latter are kept private. Today, different systems use RSA encryption including OpenSSL, cryptlib, wolfCrypt, and other cryptographic libraries.
🌐
Reubenbinns
reubenbinns.com › blog › self-sufficient-programming-rsa-cryptosystem-with-plain-python
Self-sufficient programming: RSA cryptosystem with plain Python | reuben binns | data, tech, policy
May 26, 2019 - RSA is not in the Python standard library, and requires various functions which I’d naturally go looking for in external libraries (e.g.
🌐
GeeksforGeeks
geeksforgeeks.org › installation guide › how-to-install-python-rsa-package-on-linux
How to Install Python RSA Package on Linux? - GeeksforGeeks
July 23, 2025 - Python-RSA is an RSA implementation written entirely in Python. According to PKCS#1 version 1.5, it provides encryption and decryption, signing and checking signatures, and key creation.
🌐
OnboardBase
onboardbase.com › blog › rsa-encryption-decryption
RSA Encryption & Decryption In Python: Key Creation, Storage, Algorithm, and Forward Secrecy
April 24, 2022 - PK_RSA = "-----BEGIN RSA PUBLIC KEY-----\n etc" SK_RSA = "-----BEGIN RSA PRIVATE KEY-----\n etc" .env variables can be referenced in your Python program using the native os library: