Python-RSA
Python-RSA is a pure-Python implementation of RSA public-key cryptography. It supports key generation, encryption/decryption, and signing/verifying signatures according to PKCS#1 version 1.5. Current version is 4.9.1. The project is effectively in maintenance-only mode — the original author has publicly stated they lack time to actively maintain it, and Snyk classifies its maintenance status as Inactive. Release cadence has been irregular, with no new releases since 4.9.1.
Warnings
- breaking rsa.verify() returns the hash algorithm name as a string (e.g. 'SHA-256') on success — it does NOT return True. Code checking `if rsa.verify(...) == True` or `if rsa.verify(...)` silently passes even with an unexpected return value.
- breaking rsa.bigfile (encrypt_bigfile / decrypt_bigfile) and the VARBLOCK format were removed in v4.0. These functions also had serious security flaws: no authenticated encryption, no MACs, and block reordering was possible.
- breaking PublicKey.save_pkcs1() and PrivateKey.save_pkcs1() always return bytes as of v4.0. Code that previously treated the return value as str will break with a TypeError.
- gotcha All inputs to rsa.encrypt(), rsa.decrypt(), rsa.sign(), and rsa.verify() must be bytes. Passing a Python str raises a TypeError. Encoding is the caller's responsibility.
- gotcha RSA can only encrypt messages smaller than the key modulus. A 2048-bit key can encrypt at most ~245 bytes (PKCS#1 v1.5 overhead is 11 bytes). Larger payloads raise an OverflowError.
- gotcha The library is inherently vulnerable to timing attacks because pure-Python integer arithmetic is not constant-time. This is an architectural limitation acknowledged by the maintainer and cannot be patched.
- gotcha Never log or display the stack trace of a rsa.pkcs1.VerificationError or rsa.pkcs1.DecryptionError. The traceback reveals execution path details that leak key information to an attacker.
Install
-
pip install rsa
Imports
- rsa
import rsa
- PublicKey
from rsa import PublicKey
- PrivateKey
from rsa import PrivateKey
- VerificationError
from rsa import VerificationError
- DecryptionError
from rsa import DecryptionError
Quickstart
import rsa
# Key generation — use >= 2048 bits in production; 512 shown for speed only
(pub_key, priv_key) = rsa.newkeys(2048)
# Encrypt / Decrypt — input MUST be bytes, not str
message = b'Hello, RSA!'
crypto = rsa.encrypt(message, pub_key)
decrypted = rsa.decrypt(crypto, priv_key)
assert decrypted == message
print('Decrypted:', decrypted.decode('utf-8'))
# Sign / Verify — rsa.verify() returns the hash name (str) on success, NOT True
signature = rsa.sign(message, priv_key, 'SHA-256')
try:
hash_name = rsa.verify(message, signature, pub_key)
print('Signature valid, hash method:', hash_name) # e.g. 'SHA-256'
except rsa.VerificationError:
print('Signature invalid')
# Persist keys as PEM bytes
pub_pem: bytes = pub_key.save_pkcs1() # always returns bytes (>=4.0)
priv_pem: bytes = priv_key.save_pkcs1()
# Load keys back
pub_key2 = rsa.PublicKey.load_pkcs1(pub_pem)
priv_key2 = rsa.PrivateKey.load_pkcs1(priv_pem)