{"id":680,"library":"pycryptodomex","title":"PyCryptodomeX","description":"PyCryptodomeX is a self-contained Python package providing low-level cryptographic primitives. It is a fork of the unmaintained PyCrypto library, offering numerous enhancements like authenticated encryption modes, Hybrid Public Key Encryption (HPKE), accelerated AES, and elliptic curve cryptography. It is actively maintained, with version 3.23.0 being the latest, and releases occur frequently. It supports Python 2.7, Python 3.7 and newer, and PyPy.","status":"active","version":"3.23.0","language":"python","source_language":"en","source_url":"https://github.com/Legrandin/pycryptodome/","tags":["cryptography","security","encryption","hashing","aes","rsa","pycrypto-alternative"],"install":[{"cmd":"pip install pycryptodomex","lang":"bash","label":"Install PyCryptodomeX"}],"dependencies":[],"imports":[{"note":"PyCryptodomeX installs its modules under the 'Cryptodome' namespace to avoid conflicts with the legacy PyCrypto or `pycryptodome` library. Importing from `Crypto` will fail or import a different library if `pycryptodome` is also installed.","wrong":"from Crypto.Cipher import AES","symbol":"AES","correct":"from Cryptodome.Cipher import AES"},{"note":"PyCryptodomeX uses the 'Cryptodome' namespace.","wrong":"from Crypto.Random import get_random_bytes","symbol":"get_random_bytes","correct":"from Cryptodome.Random import get_random_bytes"},{"note":"The `Padding` utility is located under `Cryptodome.Util`.","symbol":"PKCS7","correct":"from Cryptodome.Util.Padding import PKCS7"}],"quickstart":{"code":"from Cryptodome.Cipher import AES\nfrom Cryptodome.Random import get_random_bytes\nfrom Cryptodome.Util.Padding import pad, unpad\n\n# --- Encryption ---\n\n# Generate a random 16-byte key for AES-128\nkey = get_random_bytes(16)\n\n# Generate a random 16-byte IV for CBC mode\niv = get_random_bytes(16)\n\n# The data to encrypt must be bytes\ndata_to_encrypt = b\"My secret message that needs to be encrypted.\"\n\n# Create an AES cipher object in CBC mode\ncipher = AES.new(key, AES.MODE_CBC, iv)\n\n# Pad the data to be a multiple of the block size (16 bytes for AES)\npadded_data = pad(data_to_encrypt, AES.block_size)\n\n# Encrypt the padded data\nciphertext = cipher.encrypt(padded_data)\n\nprint(f\"Original data: {data_to_encrypt}\")\nprint(f\"Key (hex): {key.hex()}\")\nprint(f\"IV (hex): {iv.hex()}\")\nprint(f\"Ciphertext (hex): {ciphertext.hex()}\")\n\n# --- Decryption ---\n\n# In a real scenario, key, iv, and ciphertext would be transmitted\n# to the receiver. For this example, we reuse them.\n\n# Create a new AES cipher object for decryption (same key and IV)\ndecipher = AES.new(key, AES.MODE_CBC, iv)\n\n# Decrypt the ciphertext\ndecrypted_padded_data = decipher.decrypt(ciphertext)\n\n# Unpad the decrypted data to get the original plaintext\ndecrypted_data = unpad(decrypted_padded_data, AES.block_size)\n\nprint(f\"Decrypted data: {decrypted_data}\")\n\nassert decrypted_data == data_to_encrypt\nprint(\"Encryption and decryption successful!\")\n","lang":"python","description":"This quickstart demonstrates symmetric encryption and decryption using AES in CBC mode with PyCryptodomeX. It covers key and IV generation, data padding, encryption, and subsequent decryption and unpadding."},"warnings":[{"fix":"Upgrade Python to 3.7+ or pin pycryptodomex to <3.22.0.","message":"Support for Python 3.6 was removed in PyCryptodomeX version 3.22.0. Users on Python 3.6 must use an older version (<= 3.21.x) or upgrade their Python interpreter.","severity":"breaking","affected_versions":">=3.22.0"},{"fix":"Always use `from Cryptodome.<module> import <Symbol>` for `pycryptodomex` installations.","message":"PyCryptodomeX imports its modules under the `Cryptodome` namespace, not `Crypto`. Attempting to import from `Crypto` (e.g., `from Crypto.Cipher import AES`) will result in a `ModuleNotFoundError` if `pycryptodome` (which uses `Crypto`) is not installed, or can lead to subtle bugs and security issues if both `pycryptodome` and `pycryptodomex` are present, as `Crypto` might resolve to the wrong package.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always explicitly specify a secure mode of operation, such as `AES.MODE_CBC`, `AES.MODE_GCM`, or `AES.MODE_EAX`, during cipher initialization (e.g., `AES.new(key, AES.MODE_CBC, iv)`). If ECB is truly intended (rarely), use `AES.new(key, AES.MODE_ECB)`.","message":"ECB (Electronic Codebook) mode for symmetric ciphers (e.g., AES) is no longer the default and is explicitly discouraged for most uses due to its lack of semantic security. Since version 3.5.0, `AES.new(key)` will raise an error, requiring the mode to be explicitly specified.","severity":"deprecated","affected_versions":">=3.5.0"},{"fix":"Upgrade to PyCryptodomeX 3.19.1 or newer to mitigate this side-channel attack.","message":"Older versions of PyCryptodome (prior to v3.19.1) had a side-channel leakage vulnerability in OAEP decryption that could be exploited to carry out a Manger attack. This was fixed in v3.19.1.","severity":"breaking","affected_versions":"<3.19.1"},{"fix":"Ensure that the data length used with CCM ciphers is compatible with the chosen nonce length to avoid early termination. Consult documentation for specific limits.","message":"In version 3.22.0, CCM ciphers were updated to fail before encrypting or decrypting data if the data length exceeds the limit imposed by the nonce length. This prevents potential issues with integrity and confidentiality.","severity":"gotcha","affected_versions":">=3.22.0"},{"fix":"Upgrade to PyCryptodomeX 3.22.0 or newer if using RC4 with large data, or consider using a more modern stream cipher.","message":"An infinite loop issue with RC4 for data larger than 4GB was resolved in version 3.22.0. Users processing very large data with RC4 in older versions may encounter this.","severity":"gotcha","affected_versions":"<3.22.0"}],"env_vars":null,"last_verified":"2026-05-12T17:46:37.480Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"If you installed `pycryptodomex`, change your import statements to use `Cryptodome` instead of `Crypto` (e.g., `from Cryptodome.Cipher import AES`). If you intended to use the `Crypto` namespace, install `pycryptodome` instead (`pip install pycryptodome`).","cause":"You have installed the `pycryptodomex` package, but are attempting to import modules using the `Crypto` namespace, which is reserved for the `pycryptodome` package or the legacy `PyCrypto` library. `pycryptodomex` installs its modules under the `Cryptodome` namespace to prevent conflicts.","error":"ModuleNotFoundError: No module named 'Crypto'"},{"fix":"If you installed `pycryptodome`, change your import statements to use `Crypto` instead of `Cryptodome` (e.g., `from Crypto.Cipher import AES`). If you intended to use the `Cryptodome` namespace, ensure `pycryptodomex` is correctly installed (`pip install pycryptodomex`) and check for environment conflicts.","cause":"You have likely installed the `pycryptodome` package, which installs its modules under the `Crypto` namespace, but your code is trying to import from `Cryptodome`. This can also occur if `pycryptodomex` was installed, but in a conflicting environment, or if there's a typo in the import statement.","error":"ModuleNotFoundError: No module named 'Cryptodome'"},{"fix":"Install the appropriate C++ build tools for your Python version and operating system. On Windows, this typically means installing 'Build Tools for Visual Studio' (e.g., from visualstudio.microsoft.com) and selecting the C++ development workload.","cause":"This error during `pycryptodomex` installation, particularly on Windows, usually indicates that the necessary C/C++ build tools are missing. `pycryptodomex` includes C extensions that require a compiler to build if a pre-compiled wheel is not available or compatible.","error":"ERROR: Command errored out with exit status 1"},{"fix":"Ensure that encrypted data is handled as raw bytes. If you need to transmit encrypted data as a string (e.g., over HTTP), first encode the bytes using a binary-to-text encoding like Base64 (`import base64; base64.b64encode(ciphertext)`). On receipt, decode from Base64 back to bytes *before* attempting decryption (`base64.b64decode(encoded_ciphertext)`).","cause":"This error often occurs when attempting to decode raw encrypted binary data (which is not plain text) directly into a string using an encoding like UTF-8. Encrypted data should be treated as bytes until decrypted, and only then decoded if it represents a text string.","error":"'utf-8' codec can't decode byte 0x81 in position X: invalid start byte"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":"3.23.0","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.6,"disk_size":"26.3M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.6,"disk_size":"26.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.9,"import_time_s":0.04,"mem_mb":1.6,"disk_size":"27M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.6,"disk_size":"27M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":1.9,"disk_size":"29.2M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":1.9,"disk_size":"29.2M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2,"import_time_s":0.07,"mem_mb":1.9,"disk_size":"30M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":1.9,"disk_size":"30M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.9,"disk_size":"20.9M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.9,"disk_size":"20.9M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.9,"import_time_s":0.06,"mem_mb":1.9,"disk_size":"22M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":1.9,"disk_size":"22M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2,"disk_size":"20.6M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2,"disk_size":"20.5M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.9,"import_time_s":0.06,"mem_mb":1.8,"disk_size":"22M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":1.8,"disk_size":"22M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.6,"disk_size":"25.8M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.6,"disk_size":"25.8M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.3,"import_time_s":0.05,"mem_mb":1.6,"disk_size":"27M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":1.6,"disk_size":"27M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}