PyCryptodome
raw JSON → 3.23.0 verified Tue May 12 auth: no python install: verified quickstart: verified
PyCryptodome is a self-contained Python package providing low-level cryptographic primitives. It offers a comprehensive suite of algorithms for encryption, decryption, hashing, and digital signatures, acting as a maintained fork and drop-in replacement for the outdated PyCrypto library. It supports Python 2.7, Python 3.7+, and PyPy, with a consistent release cadence.
pip install pycryptodome Common errors
error ModuleNotFoundError: No module named 'Crypto' ↓
cause This error typically occurs when the `pycryptodome` library is not installed, or there is a conflict with the older `pycrypto` library, or due to case sensitivity issues on Windows where `crypto` might be installed instead of `Crypto` in the site-packages.
fix
First, uninstall any existing
pycrypto or crypto packages: pip uninstall pycrypto crypto. Then, install pycryptodome: pip install pycryptodome. Ensure your imports use from Crypto.Cipher import AES (or similar) as intended by pycryptodome. error TypeError: argument 2 must be bytes, not bytearray ↓
cause This error, often seen with `strxor`, arises when both the old `pycrypto` and `pycryptodome` packages are installed concurrently, causing module interference.
fix
Uninstall the older
pycrypto package: pip uninstall pycrypto. error ERROR: Failed building wheel for pycryptodome ↓
cause This installation error usually indicates missing system-level build tools (like C compilers), missing Python development headers, or an incompatible Python version on your system.
fix
Ensure you have necessary build tools installed (e.g.,
build-essential on Debian/Ubuntu, Xcode Command Line Tools on macOS, or Visual C++ Build Tools on Windows). Also, ensure your Python development headers are installed (e.g., python3-dev on Debian/Ubuntu). It's also recommended to upgrade pip: pip install --upgrade pip. error ValueError: Ciphertext with incorrect length ↓
cause This error during decryption typically means the provided ciphertext length does not match the expected block size or padding scheme, often due to corrupted data, incorrect key usage, or improper padding removal settings.
fix
Verify that the ciphertext has not been altered, the correct key is being used, and the padding scheme (e.g., PKCS7, none) and mode of operation (e.g., CBC, GCM) specified during decryption precisely match those used during encryption.
Warnings
breaking PyCryptodome uses the `Crypto` top-level package name. Installing `pycryptodome` in an environment that also has the unmaintained `PyCrypto` library will cause import conflicts and unexpected behavior. Always use virtual environments and ensure only one is installed. ↓
fix Always install `pycryptodome` in a dedicated virtual environment. If a project requires coexistence with `PyCrypto`, install `pycryptodomex` instead, which uses the `Cryptodome` namespace.
breaking Python 3.6 support was removed in version 3.22.0. Users on Python 3.6 will need to pin to an older version of PyCryptodome (e.g., <3.22.0). ↓
fix Upgrade to Python 3.7 or newer, or pin `pycryptodome` to a version older than 3.22.0 (e.g., `pycryptodome<3.22.0`).
breaking ECB mode is no longer the default for symmetric ciphers. Calling `AES.new(key)` will now fail. ECB is not semantically secure and should generally be avoided. ↓
fix Explicitly specify the desired mode, e.g., `AES.new(key, AES.MODE_GCM)` or `AES.new(key, AES.MODE_CBC)`. If ECB is intentionally needed, use `AES.new(key, AES.MODE_ECB)`.
breaking Several methods like `sign()`, `verify()`, `encrypt()`, `decrypt()`, `blind()`, `unblind()` were removed from public key objects (RSA, DSA, ElGamal) due to security concerns or maintenance difficulties. ↓
fix Use dedicated modules for public-key operations: `Crypto.Cipher.PKCS1_OAEP` for RSA encryption/decryption, `Crypto.Signature.pkcs1_15` or `Crypto.Signature.pss` for RSA signing, and `Crypto.Signature.DSS` for DSA signing.
gotcha A side-channel leakage vulnerability (Manger attack) in OAEP decryption was fixed. ↓
fix Upgrade to version 3.19.1 or newer to mitigate potential side-channel attacks on OAEP decryption.
gotcha An infinite loop bug affecting RC4 ciphers when processing data larger than 4GB was resolved. ↓
fix Upgrade to version 3.22.0 or newer if using RC4 with potentially large datasets. Consider migrating away from RC4 as it is generally considered insecure for modern applications.
gotcha For HashEdDSA and Ed448, the `sign()` and `verify()` methods incorrectly modified the state of the XOF (eXtendable Output Function). ↓
fix Upgrade to version 3.23.0 or newer to ensure correct state management for HashEdDSA and Ed448 operations.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.07s 26.3M
3.10 slim (glibc) - - 0.07s 27M
3.11 alpine (musl) - - 0.10s 29.2M
3.11 slim (glibc) - - 0.07s 30M
3.12 alpine (musl) - - 0.07s 20.9M
3.12 slim (glibc) - - 0.10s 22M
3.13 alpine (musl) - - 0.07s 20.5M
3.13 slim (glibc) - - 0.10s 22M
3.9 alpine (musl) - - 0.10s 25.8M
3.9 slim (glibc) - - 0.09s 27M
Imports
- AES wrong
from Cryptodome.Cipher import AEScorrectfrom Crypto.Cipher import AES - get_random_bytes
from Crypto.Random import get_random_bytes - PBKDF2
from Crypto.Protocol.KDF import PBKDF2 - RSA
from Crypto.PublicKey import RSA
Quickstart verified last tested: 2026-04-23
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Protocol.KDF import PBKDF2
import os
# Simulate a password for key derivation
password = os.environ.get('CRYPTO_PASSWORD', 'mysecretpassword').encode('utf-8')
# Generate a random salt
salt = get_random_bytes(16)
# Derive a strong key from the password and salt
# Use default iterations (or a high number like 1000000)
key = PBKDF2(password, salt, dkLen=32) # 32 bytes for AES-256
# The data to encrypt
data = b"This is a super secret message."
# Encrypt with AES GCM
# A nonce is automatically generated by AES.new() in GCM mode
cipher = AES.new(key, AES.MODE_GCM)
ciphertext, tag = cipher.encrypt_and_digest(data)
nonce = cipher.nonce
print(f"Original: {data}")
print(f"Salt: {salt.hex()}")
print(f"Nonce: {nonce.hex()}")
print(f"Ciphertext: {ciphertext.hex()}")
print(f"Tag: {tag.hex()}")
# --- Decryption ---
# Re-derive the key using the same password and salt
decryption_key = PBKDF2(password, salt, dkLen=32)
# Create a new cipher object for decryption using the received key and nonce
decrypt_cipher = AES.new(decryption_key, AES.MODE_GCM, nonce=nonce)
# Decrypt and verify
try:
plaintext = decrypt_cipher.decrypt_and_verify(ciphertext, tag)
print(f"Decrypted: {plaintext}")
except ValueError:
print("Decryption failed or message was tampered with!")