Registry / auth-security / rsa
library4.9.1pypypi✓ verified 27d ago

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.

pip install rsa
INSTALL
IMPORT
SIG · RSA
R
rsa
auth-securitypythonv4.9.1
Install
1.8s avg
Import
22ms
Disk
17MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v4.9.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.022s · 18.9MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.8s · import 0.022s · 19MB
17MB installed
● package 17MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

rsa
import rsa
Top-level import gives access to rsa.newkeys(), rsa.encrypt(), rsa.decrypt(), rsa.sign(), rsa.verify()
PublicKey
from rsa import PublicKey
from rsa.key import PublicKey
Public API is re-exported from the top-level rsa package; internal submodule imports are not part of the stable API
PrivateKey
from rsa import PrivateKey
from rsa.key import PrivateKey
Same as PublicKey — use the top-level package, not internal submodules
VerificationError
from rsa import VerificationError
from rsa.pkcs1 import VerificationError
Re-exported at top level; catching via internal submodule path is fragile
DecryptionError
from rsa import DecryptionError
Raised by rsa.decrypt() on tampered or invalid ciphertext; catch explicitly rather than broad Exception

Generate a key pair, encrypt a message, decrypt it, then sign and verify — the core PKCS#1 v1.5 workflow.

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)
Debug
Known issues
breakingrsa.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.
fix
Always wrap rsa.verify() in a try/except rsa.VerificationError block. Do not use its return value as a boolean.
affects: <3.x returned True; >=3.x returns str
breakingrsa.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.
fix
Use hybrid encryption: encrypt a random AES key with rsa.encrypt(), then encrypt the payload with AES (e.g. via cryptography or pycryptodome).
affects: Deprecated in 3.4, removed in 4.0
breakingPublicKey.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.
fix
Do not decode the returned value; write to files in binary mode: open('key.pem', 'wb').
affects: <4.0 could return str; >=4.0 always returns bytes
gotchaAll 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.
fix
Always encode strings before passing: message.encode('utf-8').
affects: all
gotchaRSA 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.
fix
Use hybrid encryption for arbitrary-length data: encrypt a random symmetric key with RSA and the data with AES.
affects: all
gotchaThe 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.
fix
For timing-sensitive or high-security production use, prefer cryptography (pyca) or pycryptodome, which use constant-time C extensions.
affects: all
gotchaNever 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.
fix
Catch exceptions silently or log only a generic failure message: except rsa.VerificationError: log.warning('Signature check failed') without re-raising or printing the traceback.
affects: all
Upgrade
Version history
4.9.1latest on PyPI · released Apr 16, 2025
Audit
Dependencies
pyasn1requiredRequired for ASN.1 encoding/decoding of PEM/DER key structures
Agent activity
16 hits · last 30 days
node
12
OpenAI (training)
1
Resources