pycryptodome - Man Page
Name
pycryptodome — PyCryptodome Documentation .SH PYCRYPTODOME
PyCryptodome is a self-contained Python package of low-level cryptographic primitives.
It supports Python 2.7, Python 3.6 and newer, and PyPy.
The installation procedure depends on the package you want the library to be in. PyCryptodome can be used as:
an almost drop-in replacement for the old PyCrypto library. You install it with:
pip install pycryptodome
In this case, all modules are installed under the Crypto package.
One must avoid having both PyCrypto and PyCryptodome installed at the same time, as they will interfere with each other.
This option is therefore recommended only when you are sure that the whole application is deployed in a virtualenv.
a library independent of the old PyCrypto. You install it with:
pip install pycryptodomex
In this case, all modules are installed under the Cryptodome package. PyCrypto and PyCryptodome can coexist.
For faster public key operations in Unix, you should install GMP in your system.
PyCryptodome is a fork of PyCrypto. It brings the following enhancements with respect to the last official version of PyCrypto (2.6.1):
- Authenticated encryption modes (GCM, CCM, EAX, SIV, OCB)
- Accelerated AES on Intel platforms via AES-NI
- First class support for PyPy
- Elliptic curves cryptography (NIST P-curves; Ed25519, Ed448, Curve25519, Curve448)
- Better and more compact API (nonce and iv attributes for ciphers, automatic generation of random nonces and IVs, simplified CTR cipher mode, and more)
SHA-3 hash algorithms (FIPS 202) and derived functions (NIST SP-800 185):
- SHAKE128 and SHA256 XOFs
- cSHAKE128 and cSHAKE256 XOFs
- KMAC128 and KMAC256
- TupleHash128 and TupleHash256
- KangarooTwelve, TurboSHAKE128, and TurboSHAKE256 XOFs
- Truncated hash algorithms SHA-512/224 and SHA-512/256 (FIPS 180-4)
- BLAKE2b and BLAKE2s hash algorithms
- Salsa20 and ChaCha20/XChaCha20 stream ciphers
- Poly1305 MAC
- ChaCha20-Poly1305 and XChaCha20-Poly1305 authenticated ciphers
- scrypt, bcrypt, HKDF, and NIST SP 800 108r1 Counter Mode key derivation functions
- Deterministic (EC)Dsa and EdDSA
- Password-protected Pkcs#8 key containers
- Shamir's Secret Sharing scheme
- Random numbers get sourced directly from the OS (and not from a CSPRNG in userspace)
- Simplified install process, including better support for Windows
- Cleaner Rsa and Dsa key generation (largely based on FIPS 186-4)
- Major clean ups and simplification of the code base
PyCryptodome is not a wrapper to a separate C library like OpenSSL. To the largest possible extent, algorithms are implemented in pure Python. Only the pieces that are extremely critical to performance (e.g. block ciphers) are implemented as C extensions.
For more information, see the homepage.
For security issues, please send an email to security@pycryptodome.org.
All the code can be downloaded from GitHub.
Features
This page lists the low-level primitives that PyCryptodome provides.
You are expected to have a solid understanding of cryptography and security engineering to successfully use them.
You must also be able to recognize that some primitives are obsolete (e.g. TDES) or even unsecure (RC4). They are provided only to enable backward compatibility where required by the applications.
A list of useful resources in that area can be found on Matthew Green's blog.
Symmetric ciphers:
- AES
- Single and Triple DES (legacy)
- CAST-128 (legacy)
- RC2 (legacy)
Traditional modes of operations for symmetric ciphers:
- ECB
- CBC
- CFB
- OFB
- CTR
- OpenPGP (a variant of CFB, RFC4880)
Authenticated Encryption:
- CCM (AES only)
- EAX
- GCM (AES only)
- SIV (AES only)
- OCB (AES only)
- ChaCha20-Poly1305
Stream ciphers:
- Salsa20
- ChaCha20
- RC4 (legacy)
Cryptographic hashes:
- SHA-1
- SHA-2 hashes (224, 256, 384, 512, 512/224, 512/256)
- SHA-3 hashes (224, 256, 384, 512) and XOFs (SHAKE128, SHAKE256)
- Functions derived from SHA-3 (cSHAKE128, cSHAKE256, TupleHash128, TupleHash256)
- KangarooTwelve, TurboSHAKE128, TurboSHAKE256 (XOF)
- Keccak (original submission to SHA-3)
- BLAKE2b and BLAKE2s
- RIPE-MD160 (legacy)
- MD5 (legacy)
Message Authentication Codes (MAC):
- HMAC
- CMAC
- KMAC128 and KMAC256
- Poly1305
Asymmetric key generation:
Export and import format for asymmetric keys:
Asymmetric ciphers:
PKCS#1 (Rsa)
- RSAES-PKCS1-v1_5
- RSAES-OAEP
Asymmetric digital signatures:
Key derivation:
Other cryptographic protocols:
- Shamir Secret Sharing
Padding
- PKCS#7
- ISO-7816
- X.923
Installation
The installation procedure depends on the package you want the library to be in. PyCryptodome can be used as:
An almost drop-in replacement for the old PyCrypto library. You install it with:
pip install pycryptodome
In this case, all modules are installed under the Crypto package. You can test everything is right with:
pip install pycryptodome-test-vectors python -m Crypto.SelfTest
One must avoid having both PyCrypto and PyCryptodome installed at the same time, as they will interfere with each other. This option is therefore recommended only when you are sure that the whole application is deployed in a virtualenv.
A library independent of the old PyCrypto. You install it with:
pip install pycryptodomex
You can test everything is right with:
pip install pycryptodome-test-vectors python -m Cryptodome.SelfTest
In this case, all modules are installed under the Cryptodome package. The old PyCrypto and PyCryptodome can coexist.
- NOTE:
If you intend to run PyCryptodome with Python 2.7 under Windows, you must first install the Microsoft Visual C++ 2015 Redistributable. That is not necessary if you use Python 3.
The procedures below go a bit more in detail, by explaining how to setup the environment for compiling the C extensions for each OS, and how to install the GMP library.
Compiling in Linux Ubuntu
- NOTE:
If you want to install under the Crypto package, replace below pycryptodomex with pycryptodome.
For Python 2.x:
$ sudo apt-get install build-essential python-dev $ pip install pycryptodomex $ pip install pycryptodome-test-vectors $ python -m Cryptodome.SelfTest
For Python 3.x:
$ sudo apt-get install build-essential python3-dev $ pip install pycryptodomex $ pip install pycryptodome-test-vectors $ python3 -m Cryptodome.SelfTest
For PyPy:
$ sudo apt-get install build-essential pypy-dev $ pip install pycryptodomex $ pip install pycryptodome-test-vectors $ pypy -m Cryptodome.SelfTest
Compiling in Linux Fedora
- NOTE:
If you want to install under the Crypto package, replace below pycryptodomex with pycryptodome.
For Python 2.x:
$ sudo yum install gcc gmp python-devel $ pip install pycryptodomex $ pip install pycryptodome-test-vectors $ python -m Cryptodome.SelfTest
For Python 3.x:
$ sudo yum install gcc gmp python3-devel $ pip install pycryptodomex $ pip install pycryptodome-test-vectors $ python3 -m Cryptodome.SelfTest
For PyPy:
$ sudo yum install gcc gmp pypy-devel $ pip install pycryptodomex $ pip install pycryptodome-test-vectors $ pypy -m Cryptodome.SelfTest
Windows (from sources)
- NOTE:
If you want to install under the Crypto package, replace below pycryptodomex with pycryptodome. That being the case and if you want to run the test, instead of Cryptodome.SelfTest, run Crypto.SelfTest.
Windows does not come with a C compiler like most Unix systems. The simplest way to compile the PyCryptodome extensions from source code is to install the minimum set of Visual Studio components freely made available by Microsoft.
- [Once only] Download Build Tools for Visual Studio 2019. In the installer, select the C++ build tools, the Windows 10 SDK, and the latest version of MSVC v142 x64/x86 build tools.
Compile and install PyCryptodome:
> pip install pycryptodomex --no-binary :all:
To make sure everything work fine, run the test suite:
> pip install pycryptodome-test-vectors > python -m Cryptodome.SelfTest
Documentation
Project documentation is written in reStructuredText and it is stored under Doc/src. To publish it as HTML files, you need to install sphinx and use:
> make -C Doc/ html
It will then be available under Doc/_build/html/.
PGP verification
All source packages and wheels on PyPI are cryptographically signed. They can be verified with the following PGP key:
-----BEGIN PGP PUBLIC KEY BLOCK----- mQINBFTXjPgBEADc3j7vnma9MXRshBPPXXenVpthQD6lrF/3XaBT2RptSf/viOD+ tz85du5XVp+r0SYYGeMNJCQ9NsztxblN/lnKgkfWRmSrB+V6QGS+e3bR5d9OIxzN 7haPxBnyRj//hCT/kKis6fa7N9wtwKBBjbaSX+9vpt7Rrt203sKfcChA4iR3EG89 TNQoc/kGGmwk/gyjfU38726v0NOhMKJp2154iQQVZ76hTDk6GkOYHTcPxdkAj4jS Dd74M9sOtoOlyDLHOLcWNnlWGgZjtz0z0qSyFXRSuOfggTxrepWQgKWXXzgVB4Jo 0bhmXPAV8vkX5BoG6zGkYb47NGGvknax6jCvFYTCp1sOmVtf5UTVKPplFm077tQg 0KZNAvEQrdWRIiQ1cCGCoF2Alex3VmVdefHOhNmyY7xAlzpP0c8z1DsgZgMnytNn GPusWeqQVijRxenl+lyhbkb9ZLDq7mOkCRXSze9J2+5aLTJbJu3+Wx6BEyNIHP/f K3E77nXvC0oKaYTbTwEQSBAggAXP+7oQaA0ea2SLO176xJdNfC5lkQEtMMSZI4gN iSqjUxXW2N5qEHHex1atmTtk4W9tQEw030a0UCxzDJMhD0aWFKq7wOxoCQ1q821R vxBH4cfGWdL/1FUcuCMSUlc6fhTM9pvMXgjdEXcoiLSTdaHuVLuqmF/E0wARAQAB tB9MZWdyYW5kaW4gPGhlbGRlcmlqc0BnbWFpbC5jb20+iQI4BBMBAgAiBQJU14z4 AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDabO+N4RaZEn7IEACpApha vRwPB+Dv87aEyVmjZ96Nb3mxHdeP2uSmUxAODzoB5oJJ1QL6HRxEVlU8idjdf73H DX39ZC7izD+oYIve9sNwTbKqJCZaTxlTDdgSF1N57eJOlELAy+SqpHtaMJPk7SfJ l/iYoUYxByPLZU1wDwZEDNzt9RCGy3bd/vF/AxWjdUJJPh3E4j5hswvIGSf8/Tp3 MDROU1BaNBOd0CLvBHok8/xavwO6Dk/fE4hJhd5uZcEPtd1GJcPq51z2yr7PGUcb oERsKZyG8cgfd7j8qoTd6jMIW6fBVHdxiMxW6/Z45X/vVciQSzzEl/yjPUW42kyr Ib6M16YmnDzp8bl4NNFvvR9uWvOdUkep2Bi8s8kBMJ7G9rHHJcdVy/tP1ECS9Bse hN4v5oJJ4v5mM/MiWRGKykZULWklonpiq6CewYkmXQDMRnjGXhjCWrB6LuSIkIXd gKvDNpJ8yEhAfmpvA4I3laMoof/tSZ7ZuyLSZGLKl6hoNIB13HCn4dnjNBeaXCWX pThgeOWxV6u1fhz4CeC1Hc8WOYr8S7G8P10Ji6owOcj/a1QuCW8XDB2omCTXlhFj zpC9dX8HgmUVnbPNiMjphihbKXoOcunRx4ZvqIa8mnTbI4tHtR0K0tI4MmbpcVOZ 8IFJ0nZJXuZiL57ijLREisPYmHfBHAgmh1j/W7kCDQRU14z4ARAA3QATRgvOSYFh nJOnIz6PO3G9kXWjJ8wvp3yE1/PwwTc3NbVUSNCW14xgM2Ryhn9NVh8iEGtPGmUP 4vu7rvuLC2rBs1joBTyqf0mDghlZrb5ZjXv5LcG9SA6FdAXRU6T+b1G2ychKkhEh d/ulLw/TKLds9zHhE+hkAagLQ5jqjcQN0iX5EYaOukiPUGmnd9fOEGi9YMYtRdrH +3bZxUpsRStLBWJ6auY7Bla8NJOhaWpr5p/ls+mnDWoqf+tXCCps1Da/pfHKYDFc 2VVdyM/VfNny9eaczYpnj5hvIAACWChgGDBwxPh2DGdUfiQi/QqrK96+F7ulqz6V 2exX4CL0cPv5fUpQqSU/0R5WApM9bl2+wljFhoCXlydU9HNn+0GatGzEoo3yrV/m PXv7d6NdZxyOqgxu/ai/z++F2pWUXSBxZN3Gv28boFKQhmtthTcFudNUtQOchhn8 Pf/ipVISqrsZorTx9Qx4fPScEWjwbh84Uz20bx0sQs1oYcek2YG5RhEdzqJ6W78R S/dbzlNYMXGdkxB6C63m8oiGvw0hdN/iGVqpNAoldFmjnFqSgKpyPwfLmmdstJ6f xFZdGPnKexCpHbKr9fg50jZRenIGai79qPIiEtCZHIdpeemSrc7TKRPV3H2aMNfG L5HTqcyaM2+QrMtHPMoOFzcjkigLimMAEQEAAYkCHwQYAQIACQUCVNeM+AIbDAAK CRDabO+N4RaZEo7lD/45J6z2wbL8aIudGEL0aY3hfmW3qrUyoHgaw35KsOY9vZwb cZuJe0RlYptOreH/NrbR5SXODfhd2sxYyyvXBOuZh9i7OOBsrAd5UE01GCvToPwh 7IpMV3GSSAB4P8XyJh20tZqiZOYKhmbf29gUDzqAI6GzUa0U8xidUKpW2zqYGZjp wk3RI1fS7tyi/0N8B9tIZF48kbvpFDAjF8w7NSCrgRquAL7zJZIG5o5zXJM/ffF3 67Dnz278MbifdM/HJ+Tj0R0Uvvki9Z61nT653SoUgvILQyC72XI+x0+3GQwsE38a 5aJNZ1NBD3/v+gERQxRfhM5iLFLXK0Xe4K2XFM1g0yN4L4bQPbhSCq88g9Dhmygk XPbBsrK0NKPVnyGyUXM0VpgRbot11hxx02jC3HxS1nlLF+oQdkKFzJAMOU7UbpX/ oO+286J1FmpG+fihIbvp1Quq48immtnzTeLZbYCsG4mrM+ySYd0Er0G8TBdAOTiN 3zMbGX0QOO2fOsJ1d980cVjHn5CbAo8C0A/4/R2cXAfpacbvTiNq5BVk9NKa2dNb kmnTStP2qILWmm5ASXlWhOjWNmptvsUcK+8T+uQboLioEv19Ob4j5Irs/OpOuP0K v4woCi9+03HMS42qGSe/igClFO3+gUMZg9PJnTJhuaTbytXhUBgBRUPsS+lQAQ== =DpoI -----END PGP PUBLIC KEY BLOCK-----
Compatibility with Pycrypto
PyCryptodome exposes almost the same API as the old PyCrypto so that most applications will run unmodified. However, a very few breaks in compatibility had to be introduced for those parts of the API that represented a security hazard or that were too hard to maintain.
Specifically, for public key cryptography:
The following methods from public key objects (Rsa, Dsa, ElGamal) have been removed:
- sign()
- verify()
- encrypt()
- decrypt()
- blind()
- unblind()
Applications should be updated to use instead:
- Method: generate() for public key modules does not accept the progress_func parameter anymore.
- Ambiguous method size from Rsa, Dsa and ElGamal key objects have been removed. Instead, use methods size_in_bytes() and size_in_bits() and check the documentation.
- The 3 public key object types (Rsa, Dsa, ElGamal) are now unpickable. You must use the export_key() method of each key object and select a good output format: for private keys that means a good password-based encryption scheme.
- Removed attribute Crypto.PublicKey.Rsa.algorithmIdentifier.
- Removed Crypto.PublicKey.Rsa.RSAImplementation (which should have been private in the first place). Same for Crypto.PublicKey.Dsa.DSAImplementation.
For symmetric key cryptography:
- Symmetric ciphers do not have ECB as default mode anymore. ECB is not semantically secure and it exposes correlation across blocks. An expression like AES.new(key) will now fail. If ECB is the desired mode, one has to explicitly use AES.new(key, AES.MODE_ECB).
- Crypto.Cipher.DES3 does not allow keys that degenerate to Single DES.
- Parameter segment_size cannot be 0 for the CFB mode.
- Parameters disabled_shortcut and overflow cannot be passed anymore to Crypto.Util.Counter.new. Parameter allow_wraparound is ignored (counter block wraparound will always be checked).
- The counter parameter of a CTR mode cipher must be generated via Crypto.Util.Counter. It cannot be a generic callable anymore.
- Keys for Crypto.Cipher.ARC2, Crypto.Cipher.ARC4 and Crypto.Cipher.Blowfish must be at least 40 bits long (still very weak).
The following packages, modules and functions have been removed:
- Crypto.Random.OSRNG, Crypto.Util.winrandom and Crypto.Random.randpool. You should use Crypto.Random only.
- Crypto.Cipher.XOR. If you just want to XOR data, use Crypto.Util.strxor.
- Crypto.Hash.new. Use Crypto.Hash.<algorithm>.new() instead.
- Crypto.Protocol.AllOrNothing
- Crypto.Protocol.Chaffing
- Crypto.Util.number.getRandomNumber
- Crypto.pct_warnings
Others:
- Support for any Python version older than 2.6 is dropped.
API Documentation
Crypto.Cipher package
Introduction
The Crypto.Cipher package contains algorithms for protecting the confidentiality of data.
There are three types of encryption algorithms:
- Symmetric ciphers: all parties use the same key, for both decrypting and encrypting data. Symmetric ciphers are typically very fast and can process very large amount of data.
- Asymmetric ciphers: senders and receivers use different keys. Senders encrypt with public keys (non-secret) whereas receivers decrypt with private keys (secret). Asymmetric ciphers are typically very slow and can process only very small payloads. Example: PKCS#1 OAEP (Rsa).
- Hybrid ciphers: the two types of ciphers above can be combined in a construction that inherits the benefits of both. An asymmetric cipher is used to protect a short-lived symmetric key, and a symmetric cipher (under that key) encrypts the actual message.
API principles
[image] Generic state diagram for a cipher object.UNINDENT
The base API of a cipher is fairly simple:
- You instantiate a cipher object by calling the new() function from the relevant cipher module (e.g. Crypto.Cipher.AES.new()). The first parameter is always the cryptographic key; its length depends on the particular cipher. You can (and sometimes must) pass additional cipher- or mode-specific parameters to new() (such as a nonce or a mode of operation).
For encrypting data, you call the encrypt() method of the cipher object with the plaintext. The method returns the piece of ciphertext. Alternatively, with the output parameter you can specify a pre-allocated buffer for the result.
For most algorithms, you may call encrypt() multiple times (i.e. once for each piece of plaintext).
For decrypting data, you call the decrypt() method of the cipher object with the ciphertext. The method returns the piece of plaintext. The output parameter can be passed here too.
For most algorithms, you may call decrypt() multiple times (i.e. once for each piece of ciphertext).
- NOTE:
Plaintexts and ciphertexts (input/output) can only be bytes, bytearray or memoryview. In Python 3, you cannot pass strings. In Python 2, you cannot pass Unicode strings.
Often, the sender has to deliver to the receiver other data in addition to ciphertext alone (e.g. initialization vectors or nonces, MAC tags, etc).
This is a basic example:
>>> from Crypto.Cipher import Salsa20 >>> >>> key = b'0123456789012345' >>> cipher = Salsa20.new(key) >>> ciphertext = cipher.encrypt(b'The secret I want to send.') >>> ciphertext += cipher.encrypt(b'The second part of the secret.') >>> print cipher.nonce # A byte string you must send to the receiver too
Symmetric ciphers
There are two types of symmetric ciphers:
- Stream ciphers: the most natural kind of ciphers: they encrypt data one byte at a time. See ChaCha20 and XChaCha20 and Salsa20.
Block ciphers: ciphers that can only operate on a fixed amount of data. The most important block cipher is AES, which has a block size of 128 bits (16 bytes).
In general, a block cipher is mostly useful only together with a mode of operation, which allows one to encrypt a variable amount of data. Some modes (like CTR) effectively turn a block cipher into a stream cipher.
The widespread consensus is that ciphers that provide only confidentiality, without any form of authentication, are undesirable. Instead, primitives have been defined to integrate symmetric encryption and authentication (MAC). For instance:
- Modern modes of operation for block ciphers (like GCM).
- Stream ciphers paired with a MAC function, like ChaCha20-Poly1305 and XChaCha20-Poly1305.
Classic modes of operation for symmetric block ciphers
A block cipher uses a symmetric key to encrypt data of fixed and very short length (the block size), such as 16 bytes for AES. In order to cope with data of arbitrary length, the cipher must be combined with a mode of operation.
You create a cipher object with the new() function in the relevant module under Crypto.Cipher:
- the first parameter is always the cryptographic key (a byte string)
- the second parameter is always the constant that selects the desired mode of operation
Constants for each mode of operation are defined at the module level for each algorithm. Their name starts with MODE_, for instance Crypto.Cipher.AES.MODE_CBC. Note that not all ciphers support all modes.
For instance:
>>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_CBC) >>> >>> # You can now use use cipher to encrypt or decrypt...
The state machine for a cipher configured with a classic mode is:
[image] Generic state diagram for a cipher object.UNINDENT
What follows is a list of classic modes of operation: they all provide confidentiality but not data integrity (unlike modern AEAD modes, which are described in another section).
ECB mode
Electronic CodeBook. The most basic but also the weakest mode of operation. Each block of plaintext is encrypted independently of any other block.
WARNING:
The ECB mode should not be used because it is semantically insecure. For one, it exposes correlation between blocks.
The new() function at the module level under Crypto.Cipher instantiates a new ECB cipher object for the relevant base algorithm. In the following definition, <algorithm> could be AES:
- Crypto.Cipher.<algorithm>.new(key, mode)
Create a new ECB object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_ECB
- Returns
an ECB cipher object
The method encrypt() (and likewise decrypt()) of an ECB cipher object expects data to have length multiple of the block size (e.g. 16 bytes for AES). You might need to use Crypto.Util.Padding to align the plaintext to the right boundary.
CBC mode
Ciphertext Block Chaining, defined in NIST SP 800-38A, section 6.2. It is a mode of operation where each plaintext block gets XOR-ed with the previous ciphertext block prior to encryption.
The new() function at the module level under Crypto.Cipher instantiates a new CBC cipher object for the relevant base algorithm. In the following definition, <algorithm> could be AES:
- Crypto.Cipher.<algorithm>.new(key, mode, *, iv=None)
Create a new CBC object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_CBC
- iv (bytes) -- the Initialization Vector. A piece of data unpredictable to adversaries. It is as long as the block size (e.g. 16 bytes for AES). If not present, the library creates a random IV value.
- Returns
a CBC cipher object
The method encrypt() (and likewise decrypt()) of a CBC cipher object expects data to have length multiple of the block size (e.g. 16 bytes for AES). You might need to use Crypto.Util.Padding to align the plaintext to the right boundary.
A CBC cipher object has a read-only attribute iv, holding the Initialization Vector (bytes).
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Util.Padding import pad >>> from Crypto.Random import get_random_bytes >>> >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_CBC) >>> ct_bytes = cipher.encrypt(pad(data, AES.block_size)) >>> iv = b64encode(cipher.iv).decode('utf-8') >>> ct = b64encode(ct_bytes).decode('utf-8') >>> result = json.dumps({'iv':iv, 'ciphertext':ct}) >>> print(result) '{"iv": "bWRHdzkzVDFJbWNBY0EwSmQ1UXFuQT09", "ciphertext": "VDdxQVo3TFFCbXIzcGpYa1lJbFFZQT09"}'
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> from Crypto.Util.Padding import unpad >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> iv = b64decode(b64['iv']) >>> ct = b64decode(b64['ciphertext']) >>> cipher = AES.new(key, AES.MODE_CBC, iv) >>> pt = unpad(cipher.decrypt(ct), AES.block_size) >>> print("The message was: ", pt) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
CTR mode
CounTeR mode, defined in NIST SP 800-38A, section 6.5 and Appendix B. This mode turns the block cipher into a stream cipher. Each byte of plaintext is XOR-ed with a byte taken from a keystream: the result is the ciphertext. The keystream is generated by encrypting a sequence of counter blocks with ECB.
[image]
A counter block is exactly as long as the cipher block size (e.g. 16 bytes for AES). It consists of the concatenation of two pieces:
- a fixed nonce, set at initialization.
- a variable counter, which gets increased by 1 for any subsequent counter block. The counter is big endian encoded.
The new() function at the module level under Crypto.Cipher instantiates a new CTR cipher object for the relevant base algorithm. In the following definition, <algorithm> could be AES:
- Crypto.Cipher.<algorithm>.new(key, mode, *, nonce=None, initial_value=None, counter=None)
Create a new CTR object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_CTR
- nonce (bytes) -- the value of the fixed nonce. It must be unique for the combination message/key. Its length varies from 0 to the block size minus 1. If not present, the library creates a random nonce of length equal to block size/2.
- initial_value (integer or bytes) -- the value of the counter for the first counter block. It can be either an integer or bytes (which is the same integer, just big endian encoded). If not specified, the counter starts at 0.
- counter -- a custom counter object created with Crypto.Util.Counter.new(). This allows the definition of a more complex counter block.
- Returns
a CTR cipher object
The methods encrypt() and decrypt() of a CTR cipher object accept data of any length (i.e. padding is not needed). Both raise an OverflowError exception as soon as the counter wraps around to repeat the original value.
The CTR cipher object has a read-only attribute nonce (bytes).
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_CTR) >>> ct_bytes = cipher.encrypt(data) >>> nonce = b64encode(cipher.nonce).decode('utf-8') >>> ct = b64encode(ct_bytes).decode('utf-8') >>> result = json.dumps({'nonce':nonce, 'ciphertext':ct}) >>> print(result) {"nonce": "XqP8WbylRt0=", "ciphertext": "Mie5lqje"}
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> nonce = b64decode(b64['nonce']) >>> ct = b64decode(b64['ciphertext']) >>> cipher = AES.new(key, AES.MODE_CTR, nonce=nonce) >>> pt = cipher.decrypt(ct) >>> print("The message was: ", pt) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
CFB mode
Cipher FeedBack, defined in NIST SP 800-38A, section 6.3. It is a mode of operation which turns the block cipher into a stream cipher. Each byte of plaintext is XOR-ed with a byte taken from a keystream: the result is the ciphertext.
The keystream is obtained on a per-segment basis: the plaintext is broken up in segments (from 1 byte up to the size of a block). Then, for each segment, the keystream is obtained by encrypting with the block cipher the last piece of ciphertext produced so far - possibly backfilled with the Initialization Vector, if not enough ciphertext is available yet.
The new() function at the module level under Crypto.Cipher instantiates a new CFB cipher object for the relevant base algorithm. In the following definition, <algorithm> could be AES:
- Crypto.Cipher.<algorithm>.new(key, mode, *, iv=None, segment_size=8)
Create a new CFB object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_CFB
- iv (bytes) -- the Initialization Vector. It must be unique for the combination message/key. It is as long as the block size (e.g. 16 bytes for AES). If not present, the library creates a random IV.
- segment_size (integer) -- the number of bits (not bytes!) the plaintext and the ciphertext are segmented in (default if not specified: 8 bits = 1 byte).
- Returns
a CFB cipher object
The methods encrypt() and decrypt() of a CFB cipher object accept data of any length (i.e. padding is not needed).
The CFB cipher object has a read-only attribute iv (bytes), holding the Initialization Vector.
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_CFB) >>> ct_bytes = cipher.encrypt(data) >>> iv = b64encode(cipher.iv).decode('utf-8') >>> ct = b64encode(ct_bytes).decode('utf-8') >>> result = json.dumps({'iv':iv, 'ciphertext':ct}) >>> print(result) {"iv": "VoamO23kFSOZcK1O2WiCDQ==", "ciphertext": "f8jciJ8/"}
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> iv = b64decode(b64['iv']) >>> ct = b64decode(b64['ciphertext']) >>> cipher = AES.new(key, AES.MODE_CFB, iv=iv) >>> pt = cipher.decrypt(ct) >>> print("The message was: ", pt) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
OFB mode
Output FeedBack, defined in NIST SP 800-38A, section 6.4. It is another mode that leads to a stream cipher. Each byte of plaintext is XOR-ed with a byte taken from a keystream: the result is the ciphertext. The keystream is obtained by recursively encrypting the Initialization Vector.
The new() function at the module level under Crypto.Cipher instantiates a new OFB cipher object for the relevant base algorithm. In the following definition, <algorithm> could be AES:
- Crypto.Cipher.<algorithm>.new(key, mode, *, iv=None)
Create a new OFB object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_OFB
- iv (bytes) -- the Initialization Vector. It must be unique for the combination message/key. It is as long as the block size (e.g. 16 bytes for AES). If not present, the library creates a random IV.
- Returns
an OFB cipher object
The methods encrypt() and decrypt() of an OFB cipher object accept data of any length (i.e. padding is not needed).
The OFB cipher object has a read-only attribute iv (bytes), holding the Initialization Vector.
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_OFB) >>> ct_bytes = cipher.encrypt(data) >>> iv = b64encode(cipher.iv).decode('utf-8') >>> ct = b64encode(ct_bytes).decode('utf-8') >>> result = json.dumps({'iv':iv, 'ciphertext':ct}) >>> print(result) {"iv": "NUuRJbL0UMp8+UMCk2/vQA==", "ciphertext": "XGVGc1Gw"}
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> iv = b64decode(b64['iv']) >>> ct = b64decode(b64['ciphertext']) >>> cipher = AES.new(key, AES.MODE_OFB, iv=iv) >>> pt = cipher.decrypt(ct) >>> print("The message was: ", pt) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
OpenPGP mode
Constant: Crypto.Cipher.<cipher>.MODE_OPENPGP.
OpenPGP (defined in RFC4880). A variant of CFB, with two differences:
- The first invocation to the encrypt() method returns the encrypted IV concatenated to the first chunk of ciphertext (as opposed to the ciphertext only). The encrypted IV is as long as the block size plus 2 more bytes.
- When the cipher object is intended for decryption, the parameter iv to new() is the encrypted IV (and not the IV, which is still the case for encryption).
Like for CTR, an OpenPGP cipher object has a read-only attribute iv.
Modern modes of operation for symmetric block ciphers
Classic modes of operation such as CBC only provide guarantees over the confidentiality of the message but not over its integrity. In other words, they don't allow the receiver to establish if the ciphertext was modified in transit or if it really originates from a certain source.
For that reason, classic modes of operation have been often paired with a MAC primitive (such as Crypto.Hash.HMAC), but the combination is not always straightforward, efficient or secure.
Recently, new modes of operations (AEAD, for Authenticated Encryption with Associated Data) have been designed to combine encryption and authentication into a single, efficient primitive. Optionally, some part of the message can also be left in the clear (non-confidential associated data, such as headers), while the whole message remains fully authenticated.
In addition to the ciphertext and a nonce (or IV - Initialization Vector), AEAD modes require the additional delivery of a MAC tag.
This is the state machine for a cipher object:
[image] Generic state diagram for a AEAD cipher mode.UNINDENT
Beside the usual encrypt() and decrypt() already available for classic modes of operation, several other methods are present:
- update(data)
Authenticate those parts of the message that get delivered as is, without any encryption (like headers). It is similar to the update() method of a MAC object. Note that all data passed to encrypt() and decrypt() get automatically authenticated already.
- Parameters
data (bytes) -- the extra data to authenticate
- digest()
Create the final authentication tag (MAC tag) for a message.
- Return bytes
the MAC tag
- hexdigest()
Equivalent to digest(), with the output encoded in hexadecimal.
- Return str
the MAC tag as a hexadecimal string
- verify(mac_tag)
Check if the provided authentication tag (MAC tag) is valid, that is, if the message has been decrypted using the right key and if no modification has taken place in transit.
- Parameters
mac_tag (bytes) -- the MAC tag
- Raises
ValueError -- if the MAC tag is not valid, that is, if the entire message should not be trusted.
- hexverify(mac_tag_hex)
Same as verify() but accepts the MAC tag encoded as an hexadecimal string.
- Parameters
mac_tag_hex (str) -- the MAC tag as a hexadecimal string
- Raises
ValueError -- if the MAC tag is not valid, that is, if the entire message should not be trusted.
- encrypt_and_digest(plaintext, output=None)
Perform encrypt() and digest() in one go.
- Parameters
plaintext (bytes) -- the last piece of plaintext to encrypt
- Keyword Arguments
output (bytes/bytearray/memoryview) -- the pre-allocated buffer where the ciphertext must be stored (as opposed to being returned).
- Returns
a tuple with two items
- the ciphertext, as bytes
- the MAC tag, as bytes
The first item becomes None when the output parameter specified a location for the result.
- decrypt_and_verify(ciphertext, mac_tag, output=None)
Perform decrypt() and verify() in one go.
- Parameters
ciphertext (bytes) -- the last piece of ciphertext to decrypt
- Keyword Arguments
output (bytes/bytearray/memoryview) -- the pre-allocated buffer where the plaintext must be stored (as opposed to being returned).
- Raises
ValueError -- if the MAC tag is not valid, that is, if the entire message should not be trusted.
CCM mode
Counter with CBC-MAC, defined in RFC3610 or NIST SP 800-38C. It only works with ciphers having block size 128 bits (like AES).
The new() function at the module level under Crypto.Cipher instantiates a new CCM cipher object for the relevant base algorithm. In the following definition, <algorithm> can only be AES today:
- Crypto.Cipher.<algorithm>.new(key, mode, *, nonce=None, mac_len=None, msg_len=None, assoc_len=None)
Create a new CCM object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_CCM
- nonce (bytes) -- the value of the fixed nonce. It must be unique for the combination message/key. For AES, its length varies from 7 to 13 bytes. The longer the nonce, the smaller the allowed message size (with a nonce of 13 bytes, the message cannot exceed 64KB). If not present, the library creates a 11 bytes random nonce (the maximum message size is 8GB).
- mac_len (integer) -- the desired length of the MAC tag (default if not present: 16 bytes).
- msg_len (integer) -- pre-declaration of the length of the message to encipher. If not specified, encrypt() and decrypt() can only be called once.
- assoc_len (integer) -- pre-declaration of the length of the associated data. If not specified, some extra buffering will take place internally.
- Returns
a CTR cipher object
The cipher object has a read-only attribute nonce.
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> header = b"header" >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_CCM) >>> cipher.update(header) >>> ciphertext, tag = cipher.encrypt_and_digest(data) >>> >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> json_v = [ b64encode(x).decode('utf-8') for x in (cipher.nonce, header, ciphertext, tag) ] >>> result = json.dumps(dict(zip(json_k, json_v))) >>> print(result) {"nonce": "p6ffzcKw+6xopVQ=", "header": "aGVhZGVy", "ciphertext": "860kZo/G", "tag": "Ck5YpVCM6fdWnFkFxw8K6A=="}
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> jv = {k:b64decode(b64[k]) for k in json_k} >>> >>> cipher = AES.new(key, AES.MODE_CCM, nonce=jv['nonce']) >>> cipher.update(jv['header']) >>> plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag']) >>> print("The message was: " + plaintext.decode('utf-8')) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
EAX mode
An AEAD mode designed for NIST by Bellare, Rogaway, and Wagner in 2003.
The new() function at the module level under Crypto.Cipher instantiates a new EAX cipher object for the relevant base algorithm.
- Crypto.Cipher.<algorithm>.new(key, mode, *, nonce=None, mac_len=None)
Create a new EAX object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_EAX
- nonce (bytes) -- the value of the fixed nonce. It must be unique for the combination message/key. If not present, the library creates a random nonce (16 bytes long for AES).
- mac_len (integer) -- the length of the MAC tag, in bytes. At least 2, and not larger than the cipher's block size (default), which is 16 bytes for AES.
- Returns
an EAX cipher object
The cipher object has a read-only attribute nonce.
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> header = b"header" >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_EAX) >>> cipher.update(header) >>> ciphertext, tag = cipher.encrypt_and_digest(data) >>> >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> json_v = [ b64encode(x).decode('utf-8') for x in (cipher.nonce, header, ciphertext, tag) ] >>> result = json.dumps(dict(zip(json_k, json_v))) >>> print(result) {"nonce": "CSIJ+e8KP7HJo+hC4RXIyQ==", "header": "aGVhZGVy", "ciphertext": "9YYjuAn6", "tag": "kXHrs9ZwYmjDkmfEJx7Clg=="}
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> jv = {k:b64decode(b64[k]) for k in json_k} >>> >>> cipher = AES.new(key, AES.MODE_EAX, nonce=jv['nonce']) >>> cipher.update(jv['header']) >>> plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag']) >>> print("The message was: " + plaintext.decode('utf-8')) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
GCM mode
Galois/Counter Mode, defined in NIST SP 800-38D. It only works in combination with a 128 bits cipher like AES.
The new() function at the module level under Crypto.Cipher instantiates a new GCM cipher object for the relevant base algorithm.
- Crypto.Cipher.<algorithm>.new(key, mode, *, nonce=None, mac_len=None)
Create a new GCM object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_GCM
- nonce (bytes) -- the value of the fixed nonce. It must be unique for the combination message/key. If not present, the library creates a random nonce (16 bytes long for AES).
- mac_len (integer) -- the desired length of the MAC tag, from 4 to 16 bytes (default: 16).
- Returns
a GCM cipher object
The cipher object has a read-only attribute nonce.
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> header = b"header" >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_GCM) >>> cipher.update(header) >>> ciphertext, tag = cipher.encrypt_and_digest(data) >>> >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> json_v = [ b64encode(x).decode('utf-8') for x in (cipher.nonce, header, ciphertext, tag) ] >>> result = json.dumps(dict(zip(json_k, json_v))) >>> print(result) {"nonce": "DpOK8NIOuSOQlTq+BphKWw==", "header": "aGVhZGVy", "ciphertext": "CZVqyacc", "tag": "B2tBgICbyw+Wji9KpLVa8w=="}
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> jv = {k:b64decode(b64[k]) for k in json_k} >>> >>> cipher = AES.new(key, AES.MODE_GCM, nonce=jv['nonce']) >>> cipher.update(jv['header']) >>> plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag']) >>> print("The message was: " + plaintext.decode('utf-8')) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
- NOTE:
GCM is most commonly used with 96-bit (12-byte) nonces, which is also the length recommended by NIST SP 800-38D.
If interoperability is important, one should take into account that the library default of a 128-bit random nonce may not be (easily) supported by other implementations. A 96-bit nonce can be explicitly generated for a new encryption cipher:
>>> key = get_random_bytes(16) >>> nonce = get_random_bytes(12) >>> cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
SIV mode
Synthetic Initialization Vector (SIV), defined in RFC5297. It only works with ciphers with a block size of 128 bits (like AES).
Although less efficient than other modes, SIV is nonce misuse-resistant: accidental reuse of the nonce does not jeopardize the security as it happens with CCM or GCM. As a matter of fact, operating without a nonce is not an error per se: the cipher simply becomes deterministic. In other words, a message gets always encrypted into the same ciphertext.
The new() function at the module level under Crypto.Cipher instantiates a new SIV cipher object for the relevant base algorithm.
- Crypto.Cipher.<algorithm>.new(key, mode, *, nonce=None)
Create a new SIV object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key; it must be twice the size of the key required by the underlying cipher (e.g. 32 bytes for AES-128).
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_SIV
- nonce (bytes) -- the value of the fixed nonce. It must be unique for the combination message/key. If not present, the encryption will be deterministic.
- Returns
a SIV cipher object
If the nonce parameter was provided to new(), the resulting cipher object has a read-only attribute nonce.
Example (encryption):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> header = b"header" >>> data = b"secret" >>> key = get_random_bytes(16 * 2) >>> nonce = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_SIV, nonce=nonce) # Without nonce, the encryption >>> # becomes deterministic >>> cipher.update(header) >>> ciphertext, tag = cipher.encrypt_and_digest(data) >>> >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> json_v = [ b64encode(x).decode('utf-8') for x in (nonce, header, ciphertext, tag) ] >>> result = json.dumps(dict(zip(json_k, json_v))) >>> print(result) {"nonce": "zMiifAVvDpMS8hnGK/z+iw==", "header": "aGVhZGVy", "ciphertext": "Q7lReEAF", "tag": "KgdnBVbCee6B/wGmMf/wQA=="}
Example (decryption):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> jv = {k:b64decode(b64[k]) for k in json_k} >>> >>> cipher = AES.new(key, AES.MODE_SIV, nonce=jv['nonce']) >>> cipher.update(jv['header']) >>> plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag']) >>> print("The message was: " + plaintext.decode('utf-8')) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
One side-effect is that encryption (or decryption) must take place in one go with the method encrypt_and_digest() (or decrypt_and_verify()). You cannot use encrypt() or decrypt(). The state diagram is therefore:
[image] State diagram for the SIV cipher mode.UNINDENT
The length of the key passed to new() must be twice as required by the underlying block cipher (e.g. 32 bytes for AES-128).
Each call to the method update() consumes an full piece of associated data. That is, the sequence:
>>> siv_cipher.update(b"builtin") >>> siv_cipher.update(b"securely")
is not equivalent to:
>>> siv_cipher.update(b"built") >>> siv_cipher.update(b"insecurely")
OCB mode
Offset CodeBook mode, a cipher designed by Rogaway and specified in RFC7253 (more specifically, this module implements the last variant, OCB3). It only works in combination with a 128 bits cipher like AES.
OCB was patented in USA but the author eventually abandoned the patents.
The new() function at the module level under Crypto.Cipher instantiates a new OCB cipher object for the relevant base algorithm.
NOTE:
The OCB state machine is slightly different compared to other modes: if you encrypt (or decrypt) multiple chunks, at the end you MUST call the method encrypt (or decrypt) with no parameters. This last call will return any piece of internally cached ciphertext (or plaintext).
[image] State diagram for the OCB mode.UNINDENT
- Crypto.Cipher.<algorithm>.new(key, mode, *, nonce=None, mac_len=None)
Create a new OCB object, using <algorithm> as the base block cipher.
- Parameters
- key (bytes) -- the cryptographic key
- mode -- the constant Crypto.Cipher.<algorithm>.MODE_OCB
- nonce (bytes) -- the value of the fixed nonce, with length between 1 and 15 bytes. It must be unique for the combination message/key. If not present, the library creates a 15 bytes random nonce.
- mac_len (integer) -- the desired length of the MAC tag (default if not present: 16 bytes).
- Returns
an OCB cipher object
The cipher object has two read-only attributes: nonce and block_size.
Example (encryption as a once-off operation):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> header = b"header" >>> data = b"secret" >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_OCB) >>> cipher.update(header) >>> ciphertext, tag = cipher.encrypt_and_digest(data) >>> >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> json_v = [ b64encode(x).decode('utf-8') for x in (cipher.nonce, header, ciphertext, tag) ] >>> result = json.dumps(dict(zip(json_k, json_v))) >>> print(result) {"nonce": "I7E6PKxHNYo2i9sz8W98", "header": "aGVhZGVy", "ciphertext": "nYJnJ8jC", "tag": "0UbFcmO9lqGknCIDWRLALA=="}
Example (decryption as a once-off operation):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> jv = {k:b64decode(b64[k]) for k in json_k} >>> >>> cipher = AES.new(key, AES.MODE_OCB, nonce=jv['nonce']) >>> cipher.update(jv['header']) >>> plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag']) >>> print("The message was: " + plaintext.decode('utf-8')) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
Example (encryption with multiple chunks):
>>> import json >>> from base64 import b64encode >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> header = b'header' >>> data = [b'chunk1', b'chunk2', b'chunk3'] >>> key = get_random_bytes(16) >>> cipher = AES.new(key, AES.MODE_OCB) >>> cipher.update(header) >>> ciphertext = b'' >>> for chunk in data: >>> ciphertext += cipher.encrypt(chunk) >>> ciphertext += cipher.encrypt() >>> tag = cipher.digest() >>> >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> json_v = [ b64encode(x).decode('utf-8') for x in (cipher.nonce, header, ciphertext, tag) ] >>> result = json.dumps(dict(zip(json_k, json_v))) >>> print(result) {"nonce": "IABQ/ww8vGsu7F4sbHXK", "header": "aGVhZGVy", "ciphertext": "7Amm2DoiMHVkYC8dY7NEX86M", "tag": "qOPnjAxF63MOAx6xjwRvJQ=="}
Example (decryption with multiple chunks):
>>> import json >>> from base64 import b64decode >>> from Crypto.Cipher import AES >>> >>> # We assume that the key was securely shared beforehand >>> try: >>> b64 = json.loads(json_input) >>> json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] >>> jv = {k:b64decode(b64[k]) for k in json_k} >>> >>> cipher = AES.new(key, AES.MODE_OCB, nonce=jv['nonce']) >>> cipher.update(jv['header']) >>> ciphertext = jv['ciphertext'] >>> >>> # Split into small chunks, just for demo purposes >>> chunks = [ ciphertext[i:i+2] for i in range(0, len(ciphertext), 2) ] >>> >>> plaintext = b'' >>> for chunk in chunks: >>> plaintext += cipher.decrypt(chunk) >>> plaintext += cipher.decrypt() >>> cipher.verify(jv['tag']) >>> >>> print("The message was: " + plaintext.decode('utf-8')) >>> except (ValueError, KeyError): >>> print("Incorrect decryption")
Legacy ciphers
A number of ciphers are implemented in this library purely for backward compatibility purposes. They are deprecated or even fully broken and should not be used in new designs.
- Single DES and Triple DES (block ciphers)
- RC2 (block cipher)
- ARC4 (stream cipher)
- Blowfish (block cipher)
- CAST-128 (block cipher)
- PKCS#1 v1.5 encryption (Rsa) (asymmetric cipher)
Crypto.Signature package
The Crypto.Signature package contains algorithms for performing digital signatures, used to guarantee integrity and non-repudiation.
Digital signatures are based on public key cryptography: the party that signs a message holds the private key, the one that verifies the signature holds the public key.
Signing a message
- Instantiate a new signer object for the desired algorithm, for instance with Crypto.Signature.pkcs1_15.new(). The first parameter is the key object (private key) obtained via the Crypto.PublicKey module.
- Instantiate a cryptographic hash object, for instance with Crypto.Hash.SHA384.new(). Then, process the message with its update() method.
- Invoke the sign() method on the signer with the hash object as parameter. The output is the signature of the message (a byte string).
Verifying a signature
- Instantiate a new verifier object for the desired algorithm, for instance with Crypto.Signature.pkcs1_15.new(). The first parameter is the key object (public key) obtained via the Crypto.PublicKey module.
- Instantiate a cryptographic hash object, for instance with Crypto.Hash.SHA384.new(). Then, process the message with its update() method.
- Invoke the verify() method on the verifier, with the hash object and the incoming signature as parameters. If the message is not authentic, an ValueError is raised.
Available mechanisms
Crypto.Hash package
Cryptographic hash functions take arbitrary binary strings as input, and produce a random-like fixed-length output (called digest or hash value).
It is practically infeasible to derive the original input data from the digest. In other words, the cryptographic hash function is one-way (pre-image resistance).
Given the digest of one message, it is also practically infeasible to find another message (second pre-image) with the same digest (weak collision resistance).
Finally, it is infeasible to find two arbitrary messages with the same digest (strong collision resistance).
Regardless of the hash algorithm, an n bits long digest is at most as secure as a symmetric encryption algorithm keyed with n/2 bits (birthday attack).
Hash functions can be simply used as integrity checks. In combination with a public-key algorithm, you can implement a digital signature.
API principles
[image] Generic state diagram for a hash object.UNINDENT
Every time you want to hash a message, you have to create a new hash object with the new() function in the relevant algorithm module (e.g. Crypto.Hash.SHA256.new()).
A first piece of message to hash can be passed to new() with the data parameter:
>> from Crypto.Hash import SHA256 >> >> hash_object = SHA256.new(data=b'First')
- NOTE:
You can only hash byte strings or byte arrays (no Python 2 Unicode strings or Python 3 strings).
Afterwards, the method update() can be invoked any number of times as necessary, with other pieces of message:
>>> hash_object.update(b'Second') >>> hash_object.update(b'Third')
The two steps above are equivalent to:
>>> hash_object.update(b'SecondThird')
At the end, the digest can be retrieved with the methods digest() or hexdigest():
>>> print(hash_object.digest()) b'}\x96\xfd@\xb2$?O\xca\xc1a\x10\x15\x8c\x94\xe4\xb4\x085"\xd5"\xa8\xa4C\x9e+\x00\x859\xc7A' >>> print(hash_object.hexdigest()) 7d96fd40b2243f4fcac16110158c94e4b4083522d522a8a4439e2b008539c741
Attributes of hash objects
Every hash object has the following attributes:
Attribute | Description |
digest_size | Size of the digest in bytes, that is, the output of the digest() method. It does not exist for hash functions with variable digest output (such as Crypto.Hash.SHAKE128). This is also a module attribute. |
block_size | The size of the message block in bytes, input to the compression function. Only applicable for algorithms based on the Merkle-Damgard construction (e.g. Crypto.Hash.SHA256). This is also a module attribute. |
oid | A string with the dotted representation of the ASN.1 OID assigned to the hash algorithm. |
Modern hash algorithms
SHA-2 family (FIPS 180-4)
- SHA-224
- SHA-256
- SHA-384
- SHA-512, SHA-512/224, SHA-512/256
SHA-3 family (FIPS 202)
- SHA3-224
- SHA3-256
- SHA3-384
- SHA3-512
- TupleHash128
- TupleHash256
- BLAKE2
- BLAKE2s
- BLAKE2b
Extensible-Output Functions (XOF)
A XOF is similar to a conventional cryptographic hash: it is a one-way function that maps a piece of data of arbitrary size to a random-like output. It provides some guarantees over collision resistance, pre-image resistance, and second pre-image resistance.
Unlike a conventional hash, an application using a XOF can choose the length of the output. For this reason, a XOF does not have a digest() method. Instead, it has a read(N) method to extract the next N bytes of the output.
[image] Generic state diagram for a XOF object.UNINDENT
SHA-3 family (FIPS 202)
- SHAKE128
- SHAKE256
SHA-3 derived functions (NIST SP 800-185)
- cSHAKE128
- cSHAKE256
- KangarooTwelve
- TurboSHAKE128 and TurboSHAKE256
Message Authentication Code (MAC) algorithms
- HMAC
- CMAC
- Poly1305
SHA-3 derived functions (NIST SP 800-185)
- KMAC128
- KMAC256
Historic hash algorithms
The following algorithms should not be used in new designs:
- SHA-1
- MD2
- MD5
- RIPEMD-160
- Keccak
Crypto.PublicKey package
In a public key cryptography system, senders and receivers do not use the same key. Instead, the system defines a key pair, with one of the keys being confidential (private) and the other not (public).
Algorithm | Sender uses.. | Receiver uses... |
Encryption | Public key | Private key |
Signature | Private key | Public key |
Unlike keys meant for symmetric cipher algorithms (typically just random bit strings), keys for public key algorithms have very specific properties. This module collects all methods to generate, validate, store and retrieve public keys.
API principles
Asymmetric keys are represented by Python objects. Each object can be either a private key or a public key (the method has_private() can be used to distinguish them).
A key object can be created in four ways:
- generate() at the module level (e.g. Crypto.PublicKey.Rsa.generate()). The key is randomly created each time.
- import_key() at the module level (e.g. Crypto.PublicKey.Rsa.import_key()). The key is loaded from memory.
- construct() at the module level (e.g. Crypto.PublicKey.Rsa.construct()). The key will be built from a set of sub-components.
- publickey() at the object level (e.g. Crypto.PublicKey.Rsa.RsaKey.publickey()). The key will be the public key matching the given object.
A key object can be serialized via its export_key() method.
Keys objects can be compared via the usual operators == and != (note that the two halves of the same key, private and public, are considered as two different keys).
Available key types
Rsa
RSA is one of the most widespread and public key algorithms. Its security is based on the difficulty of factoring large integers. The algorithm has withstood attacks for more than 30 years, and it is therefore considered reasonably secure.
However, for new designs, it is recommended to use Ecc, because keys are smaller and private key operations are faster.
The RSA algorithm can be used for both confidentiality (encryption) and authentication (digital signature). Signing and decryption are significantly slower than verification and encryption.
The cryptographic strength is primarily linked to the length of the RSA modulus n. In 2023, a sufficient length is deemed to be 3072 bits. For more information, see the most recent NIST report. Both RSA ciphertexts and RSA signatures are as large as the RSA modulus n (384 bytes if n is 3072 bit long).
With this module you can generate new RSA keys:
>>> from Crypto.PublicKey import RSA >>> >>> mykey = RSA.generate(3072)
export an RSA private key and protect it with a password, so that it is resistant to brute force attacks:
>>> pwd = b'secret' >>> with open("myprivatekey.pem", "wb") as f: >>> data = mykey.export_key(passphrase=pwd, pkcs=8, protection='PBKDF2WithHMAC-SHA512AndAES256-CBC', prot_params={'iteration_count':131072}) >>> f.write(data)
and reimport it later:
>>> pwd = b'secret' >>> with open("myprivatekey.pem", "rb") as f: >>> data = f.read() >>> mykey = RSA.import_key(data, pwd)
You can also export the public key, which is not sensitive:
>>> with open("mypublickey.pem", "wb") as f: >>> data = mykey.public_key().export_key()
For signing data with RSA, use a higher level module such as PKCS#1 PSS (RSA).
For encrypting data with RSA, use PKCS#1 OAEP (RSA).
- class Crypto.PublicKey.RSA.RsaKey(**kwargs)
Class defining an RSA key, private or public. Do not instantiate directly. Use generate(), construct() or import_key() instead.
- Variables
- n (integer) -- RSA modulus
- e (integer) -- RSA public exponent
- d (integer) -- RSA private exponent
- p (integer) -- First factor of the RSA modulus
- q (integer) -- Second factor of the RSA modulus
- invp (integer) -- Chinese remainder component (p^{-1} \text{mod } q)
- invq (integer) -- Chinese remainder component (q^{-1} \text{mod } p)
- u (integer) -- Same as invp
- export_key(format='PEM', passphrase=None, pkcs=1, protection=None, randfunc=None, prot_params=None)
Export this RSA key.
- Keyword Arguments
format (string) --
The desired output format:
- 'Pem'. (default) Text output, according to RFC1421/RFC1423.
- 'DER'. Binary output.
- 'OpenSSH'. Text output, according to the OpenSSH specification. Only suitable for public keys (not private keys).
Note that Pem contains a DER structure.
- passphrase (bytes or string) -- (Private keys only) The passphrase to protect the private key.
pkcs (integer) --
(Private keys only) The standard to use for serializing the key: PKCS#1 or Pkcs#8.
With pkcs=1 (default), the private key is encoded with a simple PKCS#1 structure (RSAPrivateKey). The key cannot be securely encrypted.
With pkcs=8, the private key is encoded with a PKCS#8 structure (PrivateKeyInfo). Pkcs#8 offers the best ways to securely encrypt the key.
NOTE:
This parameter is ignored for a public key. For DER and Pem, the output is always an ASN.1 DER SubjectPublicKeyInfo structure.
protection (string) --
(For private keys only) The encryption scheme to use for protecting the private key using the passphrase.
You can only specify a value if pkcs=8. For all possible protection schemes, refer to the encryption parameters of Pkcs#8. The recommended value is 'PBKDF2WithHMAC-SHA512AndAES256-CBC'.
If None (default), the behavior depends on format:
prot_params (dict) --
(For private keys only)
The parameters to use to derive the encryption key from the passphrase. 'protection' must be also specified. For all possible values, refer to the encryption parameters of Pkcs#8. The recommendation is to use {'iteration_count':21000} for PBKDF2, and {'iteration_count':131072} for scrypt.
- randfunc (callable) -- A function that provides random bytes. Only used for Pem encoding. The default is Crypto.Random.get_random_bytes().
- Returns
the encoded key
- Return type
bytes
- Raises
ValueError -- when the format is unknown or when you try to encrypt a private
key with DER format and PKCS#1.- WARNING:
If you don't provide a pass phrase, the private key will be exported in the clear!
- has_private()
Whether this is an RSA private key
- public_key()
A matching RSA public key.
- Returns
a new RsaKey object
- size_in_bits()
Size of the RSA modulus in bits
- size_in_bytes()
The minimal amount of bytes that can hold the RSA modulus
- Crypto.PublicKey.RSA.construct(rsa_components, consistency_check=True)
Construct an RSA key from a tuple of valid RSA components.
The modulus n must be the product of two primes. The public exponent e must be odd and larger than 1.
In case of a private key, the following equations must apply:
\begin{align}
p*q &= n \\ e*d &\equiv 1 ( \text{mod lcm} [(p-1)(q-1)]) \\ p*u &\equiv 1 ( \text{mod } q) \end{align}
- Parameters
rsa_components (tuple) --
A tuple of integers, with at least 2 and no more than 6 items. The items come in the following order:
- 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.
- Raises
ValueError -- when the key being imported fails the most basic RSA validity checks.
Returns: An RSA key object (RsaKey).
- Crypto.PublicKey.RSA.generate(bits, randfunc=None, e=65537)
Create a new RSA key pair.
The algorithm closely follows NIST FIPS 186-4 in its sections B.3.1 and B.3.3. The modulus is the product of two non-strong probable primes. Each prime passes a suitable number of Miller-Rabin tests with random bases and a single Lucas test.
- Parameters
bits (integer) -- Key length, or size (in bits) of the RSA modulus. It must be at least 1024, but 2048 is recommended. The FIPS standard only defines 1024, 2048 and 3072.
- Keyword Arguments
- randfunc (callable) -- Function that returns random bytes. The default is Crypto.Random.get_random_bytes().
- e (integer) -- Public RSA exponent. It must be an odd positive integer. It is typically a small number with very few ones in its binary representation. The FIPS standard requires the public exponent to be at least 65537 (the default).
Returns: an RSA key object (RsaKey, with private key).
- Crypto.PublicKey.RSA.import_key(extern_key, passphrase=None)
Import an RSA key (public or private).
- Parameters
extern_key (string or byte string) --
The RSA key to import.
The following formats are supported for an RSA public key:
- X.509 certificate (binary or Pem format)
- X.509 subjectPublicKeyInfo DER SEQUENCE (binary or Pem encoding)
- PKCS#1 RSAPublicKey DER SEQUENCE (binary or Pem encoding)
- An OpenSSH line (e.g. the content of ~/.ssh/id_ecdsa, ASCII)
The following formats are supported for an RSA private key:
- PKCS#1 RSAPrivateKey DER SEQUENCE (binary or Pem encoding)
- PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo DER SEQUENCE (binary or Pem encoding)
- OpenSSH (text format, introduced in OpenSSH 6.5)
- passphrase (string or byte string) -- For private keys only, the pass phrase that encrypts the key.
Returns: An RSA key object (RsaKey).
- Raises
ValueError/IndexError/TypeError -- When the given key cannot be parsed (possibly because the pass
phrase is wrong).
- Crypto.PublicKey.RSA.oid = '1.2.840.113549.1.1.1'
Object ID for the RSA encryption algorithm. This OID often indicates a generic RSA key, even when such key will be actually used for digital signatures.
Ecc
ECC (Elliptic Curve Cryptography) is a modern and efficient type of public key cryptography. Its security is based on the difficulty to solve discrete logarithms on the field defined by specific equations computed over a curve.
ECC can be used to create digital signatures or to perform a key exchange.
Compared to traditional algorithms like Rsa, an ECC key is significantly smaller at the same security level. For instance, a 3072-bit Rsa key takes 768 bytes whereas the equally strong NIST P-256 private key only takes 32 bytes (that is, 256 bits).
With this module you can generate new ECC keys:
>>> from Crypto.PublicKey import ECC >>> >>> mykey = ECC.generate(curve='p256')
export an ECC private key and protect it with a password, so that it is resistant to brute force attacks:
>>> pwd = b'secret' >>> with open("myprivatekey.pem", "wt") as f: >>> data = mykey.export_key(format='PEM' passphrase=pwd, protection='PBKDF2WithHMAC-SHA512AndAES256-CBC', prot_params={'iteration_count':131072}) >>> f.write(data)
and reimport it later:
>>> pwd = b'secret' >>> with open("myprivatekey.pem", "rt") as f: >>> data = f.read() >>> mykey = ECC.import_key(data, pwd)
You can also export the public key, which is not sensitive:
>>> with open("mypublickey.pem", "wbt") as f: >>> data = mykey.public_key().export_key()
Curve | Canonical name | Aliases |
NIST P-192 | 'NIST P-192' | 'p192', 'P-192', 'prime192v1', 'secp192r1' |
NIST P-224 | 'NIST P-224' | 'p224', 'P-224', 'prime224v1', 'secp224r1' |
NIST P-256 | 'NIST P-256' | 'p256', 'P-256', 'prime256v1', 'secp256r1' |
NIST P-384 | 'NIST P-384' | 'p384', 'P-384', 'prime384v1', 'secp384r1' |
NIST P-521 | 'NIST P-521' | 'p521', 'P-521', 'prime521v1', 'secp521r1' |
Ed25519 | 'Ed25519' | 'ed25519' |
Ed448 | 'Ed448' | 'ed448' |
Curve25519 | 'Curve25519' | 'curve25519' |
Curve448 | 'Curve448' | 'curve448' |
For more information about each NIST curve see FIPS 186-4, Section D.1.2.
Curves Ed25519 and Ed448 are defined in RFC8032.
Curves Curve25519 and Curve448 are defined in RFC7748.
The ECC keys can be used to perform or verify signatures, using the modules Crypto.Signature.DSS (ECDSA; NIST curves only) or Crypto.Signature.eddsa (EdDSA; Ed25519 and Ed448 curve only).
- class Crypto.PublicKey.ECC.EccKey(**kwargs)
Class defining an ECC key. Do not instantiate directly. Use generate(), construct() or import_key() instead.
- Variables
- curve (string) -- The canonical name of the curve as defined in the ECC table.
- pointQ (EccPoint or EccXPoint) -- an ECC point representating the public component.
- d (integer) -- A scalar that represents the private component in NIST P curves. It is smaller than the order of the generator point.
- seed (bytes) -- A seed that representats the private component in Ed22519 (32 bytes), Curve25519 (32 bytes), Curve448 (56 bytes), Ed448 (57 bytes).
- export_key(**kwargs)
Export this ECC key.
- Parameters
format (string) --
The output format:
- 'DER'. The key will be encoded in ASN.1 DER format (binary). For a public key, the ASN.1 subjectPublicKeyInfo structure defined in RFC5480 will be used. For a private key, the ASN.1 ECPrivateKey structure defined in RFC5915 is used instead (possibly within a Pkcs#8 envelope, see the use_pkcs8 flag below).
- 'Pem'. The key will be encoded in a PEM envelope (ASCII).
- 'OpenSSH'. The key will be encoded in the OpenSSH format (ASCII, public keys only).
- 'SEC1'. The public key (i.e., the EC point) will be encoded into bytes according to Section 2.3.3 of SEC1 (which is a subset of the older X9.62 ITU standard). Only for NIST P-curves.
'raw'. The public key will be encoded as bytes, without any metadata.
- passphrase (bytes or string) -- (Private keys only) The passphrase to protect the private key.
use_pkcs8 (boolean) --
(Private keys only) If True (default and recommended), the PKCS#8 representation will be used. It must be True for Ed25519, Ed448, Curve25519, and Curve448.
If False and a passphrase is present, the obsolete Pem encryption will be used.
- protection (string) -- When a private key is exported with password-protection and Pkcs#8 (both DER and Pem formats), this parameter MUST be present, For all possible protection schemes, refer to the encryption parameters of Pkcs#8. It is recommended to use 'PBKDF2WithHMAC-SHA512AndAES128-CBC'.
compress (boolean) --
If True, the method returns a more compact representation of the public key, with the X-coordinate only.
If False (default), the method returns the full public key.
This parameter is ignored for Ed25519/Ed448/Curve25519/Curve448, as compression is mandatory.
- prot_params (dict) -- When a private key is exported with password-protection and Pkcs#8 (both DER and Pem formats), this dictionary contains the parameters to use to derive the encryption key from the passphrase. For all possible values, refer to the encryption parameters of Pkcs#8. The recommendation is to use {'iteration_count':21000} for PBKDF2, and {'iteration_count':131072} for scrypt.
- WARNING:
If you don't provide a passphrase, the private key will be exported in the clear!
- has_private()
True if this key can be used for making signatures or decrypting data.
- public_key()
A matching ECC public key.
- Returns
a new EccKey object
exception Crypto.PublicKey.ECC.UnsupportedEccFeature
- Crypto.PublicKey.ECC.construct(**kwargs)
Build a new ECC key (private or public) starting from some base components.
In most cases, you will already have an existing key which you can read in with import_key() instead of this function.
- Parameters
- curve (string) -- Mandatory. The name of the elliptic curve, as defined in the ECC table.
- d (integer) -- Mandatory for a private key and a NIST P-curve (e.g., P-256). It must be an integer in the range [1..order-1].
- seed (bytes) -- Mandatory for a private key and curves Ed25519 (32 bytes), Curve25519 (32 bytes), Curve448 (56 bytes) and Ed448 (57 bytes).
- point_x (integer) -- The X coordinate (affine) of the ECC point. Mandatory for a public key.
- point_y (integer) -- The Y coordinate (affine) of the ECC point. Mandatory for a public key, except for Curve25519 and Curve448.
- Returns
a new ECC key object
- Return type
EccKey
- Crypto.PublicKey.ECC.generate(**kwargs)
Generate a new private key on the given curve.
- Parameters
- curve (string) -- Mandatory. It must be a curve name defined in the ECC table.
- randfunc (callable) -- Optional. The RNG to read randomness from. If None, Crypto.Random.get_random_bytes() is used.
- Crypto.PublicKey.ECC.import_key(encoded, passphrase=None, curve_name=None)
Import an ECC key (public or private).
- Parameters
encoded (bytes or multi-line string) --
The ECC key to import. The function will try to automatically detect the right format.
Supported formats for an ECC public key:
- X.509 certificate: binary (DER) or ASCII (Pem).
- X.509 subjectPublicKeyInfo: binary (DER) or ASCII (Pem).
- SEC1 (or X9.62), as bytes. NIST P curves only. You must also provide the curve_name (with a value from the ECC table)
- OpenSSH line, defined in RFC5656 and RFC8709 (ASCII). This is normally the content of files like ~/.ssh/id_ecdsa.pub.
Supported formats for an ECC private key:
- A binary ECPrivateKey structure, as defined in RFC5915 (DER). NIST P curves only.
- A PKCS#8 structure (or the more recent Asymmetric Key Package, RFC5958): binary (DER) or ASCII (Pem).
- OpenSSH 6.5 and newer versions (ASCII).
Private keys can be in the clear or password-protected.
- passphrase (byte string) -- The passphrase to use for decrypting a private key. Encryption may be applied protected at the Pem level (not recommended) or at the Pkcs#8 level (recommended). This parameter is ignored if the key in input is not encrypted.
- curve_name (string) -- For a SEC1 encoding only. This is the name of the curve, as defined in the ECC table.
- NOTE:
To import EdDSA private and public keys, when encoded as raw bytes, use:
- Crypto.Signature.eddsa.import_public_key(), or
- Crypto.Signature.eddsa.import_private_key().
- NOTE:
To import X25519/X448 private and public keys, when encoded as raw bytes, use:
- Crypto.Protocol.DH.import_x25519_public_key()
- Crypto.Protocol.DH.import_x25519_private_key()
- Crypto.Protocol.DH.import_x448_public_key()
- Crypto.Protocol.DH.import_x448_private_key()
- Returns
a new ECC key object
- Return type
EccKey
- Raises
ValueError -- when the given key cannot be parsed (possibly because
the pass phrase is wrong).
Dsa
DSA is a widespread public key signature algorithm. Its security is based on the discrete logarithm problem (DLP). Given a cyclic group, a generator g, and an element h, it is hard to find an integer x such that g^x = h. The problem is believed to be difficult, and it has been proved such (and therefore secure) for more than 30 years.
The group is actually a sub-group over the integers modulo p, with p prime. The sub-group order is q, which is prime too; it always holds that (p-1) is a multiple of q. The cryptographic strength is linked to the magnitude of p and q. The signer holds a value x (0<x<q-1) as private key, and its public key (y where y=g^x \text{ mod } p) is distributed.
In 2017, a sufficient size is deemed to be 2048 bits for p and 256 bits for q. For more information, see the most recent ECRYPT report.
The algorithm can only be used for authentication (digital signature). DSA cannot be used for confidentiality (encryption).
The values (p,q,g) are called domain parameters; they are not sensitive but must be shared by both parties (the signer and the verifier). Different signers can share the same domain parameters with no security concerns.
The DSA signature is twice as big as the size of q (64 bytes if q is 256 bit long).
This module provides facilities for generating new DSA keys and for constructing them from known components.
As an example, this is how you generate a new DSA key pair, save the public key in a file called public_key.pem, sign a message (with Crypto.Signature.DSS), and verify it:
>>> from Crypto.PublicKey import DSA >>> from Crypto.Signature import DSS >>> from Crypto.Hash import SHA256 >>> >>> # Create a new DSA key >>> key = DSA.generate(2048) >>> f = open("public_key.pem", "w") >>> f.write(key.publickey().export_key()) >>> f.close() >>> >>> # Sign a message >>> message = b"Hello" >>> hash_obj = SHA256.new(message) >>> signer = DSS.new(key, 'fips-186-3') >>> signature = signer.sign(hash_obj) >>> >>> # Load the public key >>> f = open("public_key.pem", "r") >>> hash_obj = SHA256.new(message) >>> pub_key = DSA.import_key(f.read()) >>> verifier = DSS.new(pub_key, 'fips-186-3') >>> >>> # Verify the authenticity of the message >>> try: >>> verifier.verify(hash_obj, signature) >>> print "The message is authentic." >>> except ValueError: >>> print "The message is not authentic."
- class Crypto.PublicKey.DSA.DsaKey(key_dict)
Class defining an actual DSA key. Do not instantiate directly. Use generate(), construct() or import_key() instead.
- Variables
- p (integer) -- DSA modulus
- q (integer) -- Order of the subgroup
- g (integer) -- Generator
- y (integer) -- Public key
- x (integer) -- Private key
- Undocumented
exportKey, publickey
- domain()
The DSA domain parameters.
- Returns
tuple : (p,q,g)
- exportKey(format='PEM', pkcs8=None, passphrase=None, protection=None, randfunc=None)
Export this DSA key.
- Parameters
format (string) --
The encoding for the output:
- passphrase (string) -- Private keys only. The pass phrase to protect the output.
- pkcs8 (boolean) -- Private keys only. If True (default), the key is encoded with PKCS#8. If False, it is encoded in the custom OpenSSL/OpenSSH container.
protection (string) --
Only in combination with a pass phrase. The encryption scheme to use to protect the output.
If pkcs8 takes value True, this is the Pkcs#8 algorithm to use for deriving the secret and encrypting the private DSA key. For a complete list of algorithms, see Crypto.IO.PKCS8. The default is PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC.
If pkcs8 is False, the obsolete Pem encryption scheme is used. It is based on MD5 for key derivation, and Triple DES for encryption. Parameter protection is then ignored.
The combination format='DER' and pkcs8=False is not allowed if a passphrase is present.
- randfunc (callable) -- A function that returns random bytes. By default it is Crypto.Random.get_random_bytes().
- Returns
the encoded key
- Return type
byte string
- Raises
ValueError -- when the format is unknown or when you try to encrypt a private
key with DER format and OpenSSL/OpenSSH.- WARNING:
If you don't provide a pass phrase, the private key will be exported in the clear!
- export_key(format='PEM', pkcs8=None, passphrase=None, protection=None, randfunc=None)
Export this DSA key.
- Parameters
format (string) --
The encoding for the output:
- passphrase (string) -- Private keys only. The pass phrase to protect the output.
- pkcs8 (boolean) -- Private keys only. If True (default), the key is encoded with PKCS#8. If False, it is encoded in the custom OpenSSL/OpenSSH container.
protection (string) --
Only in combination with a pass phrase. The encryption scheme to use to protect the output.
If pkcs8 takes value True, this is the Pkcs#8 algorithm to use for deriving the secret and encrypting the private DSA key. For a complete list of algorithms, see Crypto.IO.PKCS8. The default is PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC.
If pkcs8 is False, the obsolete Pem encryption scheme is used. It is based on MD5 for key derivation, and Triple DES for encryption. Parameter protection is then ignored.
The combination format='DER' and pkcs8=False is not allowed if a passphrase is present.
- randfunc (callable) -- A function that returns random bytes. By default it is Crypto.Random.get_random_bytes().
- Returns
the encoded key
- Return type
byte string
- Raises
ValueError -- when the format is unknown or when you try to encrypt a private
key with DER format and OpenSSL/OpenSSH.- WARNING:
If you don't provide a pass phrase, the private key will be exported in the clear!
- has_private()
Whether this is a DSA private key
- public_key()
A matching DSA public key.
- Returns
a new DsaKey object
- publickey()
A matching DSA public key.
- Returns
a new DsaKey object
- Crypto.PublicKey.DSA.construct(tup, consistency_check=True)
Construct a DSA key from a tuple of valid DSA components.
- Parameters
tup (tuple) --
A tuple of long integers, with 4 or 5 items in the following order:
- Public key (y).
- Sub-group generator (g).
- Modulus, finite field order (p).
- Sub-group order (q).
- Private key (x). Optional.
- consistency_check (boolean) -- If True, the library will verify that the provided components fulfil the main DSA properties.
- Raises
ValueError -- when the key being imported fails the most basic DSA validity checks.
- Returns
a DSA key object
- Return type
DsaKey
- Crypto.PublicKey.DSA.generate(bits, randfunc=None, domain=None)
Generate a new DSA key pair.
The algorithm follows Appendix A.1/A.2 and B.1 of FIPS 186-4, respectively for domain generation and key pair generation.
- Parameters
- bits (integer) -- Key length, or size (in bits) of the DSA modulus p. It must be 1024, 2048 or 3072.
- randfunc (callable) -- Random number generation function; it accepts a single integer N and return a string of random data N bytes long. If not specified, Crypto.Random.get_random_bytes() is used.
- domain (tuple) -- The DSA domain parameters p, q and g as a list of 3 integers. Size of p and q must comply to FIPS 186-4. If not specified, the parameters are created anew.
- Returns
a new DSA key object
- Return type
DsaKey
- Raises
ValueError -- when bits is too little, too big, or not a multiple of 64.
- Crypto.PublicKey.DSA.import_key(extern_key, passphrase=None)
Import a DSA key.
- Parameters
extern_key (string or byte string) --
The DSA key to import.
The following formats are supported for a DSA public key:
- X.509 certificate (binary DER or Pem)
- X.509 subjectPublicKeyInfo (binary DER or Pem)
- OpenSSH (ASCII one-liner, see RFC4253)
The following formats are supported for a DSA private key:
passphrase (string) --
In case of an encrypted private key, this is the pass phrase from which the decryption key is derived.
Encryption may be applied either at the PKCS#8 or at the Pem level.
- Returns
a DSA key object
- Return type
DsaKey
- Raises
ValueError -- when the given key cannot be parsed (possibly because
the pass phrase is wrong).
- Rsa keys
- Elliptic Curve keys
- DSA keys (obsolete)
Obsolete key type
El Gamal
- WARNING:
Even though ElGamal algorithms are in theory reasonably secure, in practice there are no real good reasons to prefer them to Rsa instead.
Signature algorithm
The security of the ElGamal signature scheme is based (like Dsa) on the discrete logarithm problem (DLP). Given a cyclic group, a generator g, and an element h, it is hard to find an integer x such that g^x = h.
The group is the largest multiplicative sub-group of the integers modulo p, with p prime. The signer holds a value x (0<x<p-1) as private key, and its public key (y where y=g^x \text{ mod } p) is distributed.
The ElGamal signature is twice as big as p.
Encryption algorithm
The security of the ElGamal encryption scheme is based on the computational Diffie-Hellman problem (CDH). Given a cyclic group, a generator g, and two integers a and b, it is difficult to find the element g^{ab} when only g^a and g^b are known, and not a and b.
As before, the group is the largest multiplicative sub-group of the integers modulo p, with p prime. The receiver holds a value a (0<a<p-1) as private key, and its public key (b where b=g^a) is given to the sender.
The ElGamal ciphertext is twice as big as p.
Domain parameters
For both signature and encryption schemes, the values (p,g) are called domain parameters. They are not sensitive but must be distributed to all parties (senders and receivers). Different signers can share the same domain parameters, as can different recipients of encrypted messages.
Security
Both DLP and CDH problem are believed to be difficult, and they have been proved such (and therefore secure) for more than 30 years.
The cryptographic strength is linked to the magnitude of p. In 2017, a sufficient size for p is deemed to be 2048 bits. For more information, see the most recent ECRYPT report.
The signature is four times larger than the equivalent Dsa, and the ciphertext is two times larger than the equivalent Rsa.
Functionality
This module provides facilities for generating new ElGamal keys and constructing them from known components.
- class Crypto.PublicKey.ElGamal.ElGamalKey(randfunc=None)
Class defining an ElGamal key. Do not instantiate directly. Use generate() or construct() instead.
- Variables
- p -- Modulus
- g -- Generator
- y (integer) -- Public key component
- x (integer) -- Private key component
- has_private()
Whether this is an ElGamal private key
- publickey()
A matching ElGamal public key.
- Returns
a new ElGamalKey object
- Crypto.PublicKey.ElGamal.construct(tup)
Construct an ElGamal key from a tuple of valid ElGamal components.
The modulus p must be a prime. The following conditions must apply:
\begin{align}
&1 < g < p-1 \\ &g^{p-1} = 1 \text{ mod } 1 \\ &1 < x < p-1 \\ &g^x = y \text{ mod } p \end{align}
- Parameters
tup (tuple) --
A tuple with either 3 or 4 integers, in the following order:
- Modulus (p).
- Generator (g).
- Public key (y).
- Private key (x). Optional.
- Raises
ValueError -- when the key being imported fails the most basic ElGamal validity checks.
- Returns
an ElGamalKey object
- Crypto.PublicKey.ElGamal.generate(bits, randfunc)
Randomly generate a fresh, new ElGamal key.
The key will be safe for use for both encryption and signature (although it should be used for only one purpose).
- Parameters
- bits (int) -- Key length, or size (in bits) of the modulus p. The recommended value is 2048.
- randfunc (callable) -- Random number generation function; it should accept a single integer N and return a string of random N random bytes.
- Returns
an ElGamalKey object
- ElGamal keys
Crypto.Protocol package
Key Derivation Functions
This module contains a collection of standard key derivation functions.
A key derivation function derives one or more secondary secret keys from one primary secret (a master key or a pass phrase).
This is typically done to insulate the secondary keys from each other, to avoid that leakage of a secondary key compromises the security of the master key, or to thwart attacks on pass phrases (e.g. via rainbow tables).
PBKDF2
PBKDF2 is the most widespread algorithm for deriving keys from a password, originally defined in version 2.0 of the PKCS#5 standard or in RFC2898.
It is computationally expensive (a property that can be tuned via the count parameter) so as to thwart dictionary and rainbow tables attacks. However, it uses a very limited amount of RAM which makes it insufficiently protected against advanced and motivated adversaries that can leverage GPUs.
New applications and protocols should use scrypt or bcrypt instead.
For example, if you need to derive two AES256 keys:
from Crypto.Protocol.KDF import PBKDF2 from Crypto.Hash import SHA512 from Crypto.Random import get_random_bytes password = b'my super secret' salt = get_random_bytes(16) keys = PBKDF2(password, salt, 64, count=1000000, hmac_hash_module=SHA512) key1 = keys[:32] key2 = keys[32:]
- Crypto.Protocol.KDF.PBKDF2(password, salt, dkLen=16, count=1000, prf=None, hmac_hash_module=None)
Derive one or more keys from a password (or passphrase).
This function performs key derivation according to the PKCS#5 standard (v2.0).
- Parameters
password (string or byte string) --
The secret password to generate the key from.
Strings will be encoded as ISO 8859-1 (also known as Latin-1), which does not allow any characters with codepoints > 255.
salt (string or byte string) --
A (byte) string to use for better protection from dictionary attacks. This value does not need to be kept secret, but it should be randomly chosen for each derivation. It is recommended to use at least 16 bytes.
Strings will be encoded as ISO 8859-1 (also known as Latin-1), which does not allow any characters with codepoints > 255.
dkLen (integer) --
The cumulative length of the keys to produce.
Due to a flaw in the PBKDF2 design, you should not request more bytes than the prf can output. For instance, dkLen should not exceed 20 bytes in combination with HMAC-SHA1.
count (integer) --
The number of iterations to carry out. The higher the value, the slower and the more secure the function becomes.
You should find the maximum number of iterations that keeps the key derivation still acceptable on the slowest hardware you must support.
Although the default value is 1000, it is recommended to use at least 1000000 (1 million) iterations.
- prf (callable) -- A pseudorandom function. It must be a function that returns a pseudorandom byte string from two parameters: a secret and a salt. The slower the algorithm, the more secure the derivation function. If not specified, HMAC-SHA1 is used.
- hmac_hash_module (module) -- A module from Crypto.Hash implementing a Merkle-Damgard cryptographic hash, which PBKDF2 must use in combination with HMAC. This parameter is mutually exclusive with prf.
- Returns
A byte string of length dkLen that can be used as key material. If you want multiple keys, just break up this string into segments of the desired length.
scrypt
scrypt is a password-based key derivation function created by Colin Percival, described in his paper "Stronger key derivation via sequential memory-hard functions" and in RFC7914.
In addition to being computationally expensive, it is also memory intensive and therefore more secure against the risk of custom ASICs.
Example:
from Crypto.Protocol.KDF import scrypt from Crypto.Random import get_random_bytes password = b'my super secret' salt = get_random_bytes(16) key = scrypt(password, salt, 16, N=2**14, r=8, p=1)
- Crypto.Protocol.KDF.scrypt(password, salt, key_len, N, r, p, num_keys=1)
Derive one or more keys from a passphrase.
- Parameters
- password (string) -- The secret pass phrase to generate the keys from.
- salt (string) -- A string to use for better protection from dictionary attacks. This value does not need to be kept secret, but it should be randomly chosen for each derivation. It is recommended to be at least 16 bytes long.
- key_len (integer) -- The length in bytes of each derived key.
- N (integer) -- CPU/Memory cost parameter. It must be a power of 2 and less than 2^{32}.
- r (integer) -- Block size parameter.
- p (integer) -- Parallelization parameter. It must be no greater than (2^{32}-1)/(4r).
- num_keys (integer) -- The number of keys to derive. Every key is key_len bytes long. By default, only 1 key is generated. The maximum cumulative length of all keys is (2^{32}-1)*32 (that is, 128TB).
A good choice of parameters (N, r , p) was suggested by Colin Percival in his presentation in 2009:
- ( 2¹⁴, 8, 1 ) for interactive logins (≤100ms)
- ( 2²⁰, 8, 1 ) for file encryption (≤5s)
- Returns
A byte string or a tuple of byte strings.
bcrypt
bcrypt is a password hashing function designed by Niels Provos and David Mazières.
In addition to being computationally expensive, it is also memory intensive and therefore more secure against the risk of custom ASICs.
This implementation only supports bcrypt hashes with prefix $2a.
By design, bcrypt only accepts passwords up to 72 byte long. If you want to hash passwords with no restrictions on their length, it is common practice to apply a cryptographic hash and then BASE64-encode For instance:
from base64 import b64encode from Crypto.Hash import SHA256 from Crypto.Protocol.KDF import bcrypt password = b"test" b64pwd = b64encode(SHA256.new(password).digest()) bcrypt_hash = bcrypt(b64pwd, 12)
and to check them:
from base64 import b64encode from Crypto.Hash import SHA256 from Crypto.Protocol.KDF import bcrypt password_to_test = b"test" try: b64pwd = b64encode(SHA256.new(password).digest()) bcrypt_check(b64pwd, bcrypt_hash) except ValueError: print("Incorrect password")
- Crypto.Protocol.KDF.bcrypt(password, cost, salt=None)
Hash a password into a key, using the OpenBSD bcrypt protocol.
- Parameters
- password (byte string or string) -- The secret password or pass phrase. It must be at most 72 bytes long. It must not contain the zero byte. Unicode strings will be encoded as UTF-8.
- cost (integer) -- The exponential factor that makes it slower to compute the hash. It must be in the range 4 to 31. A value of at least 12 is recommended.
- salt (byte string) -- Optional. Random byte string to thwarts dictionary and rainbow table attacks. It must be 16 bytes long. If not passed, a random value is generated.
- Return (byte string):
The bcrypt hash
- Raises
ValueError -- if password is longer than 72 bytes or if it contains the zero byte
- Crypto.Protocol.KDF.bcrypt_check(password, bcrypt_hash)
Verify if the provided password matches the given bcrypt hash.
- Parameters
- password (byte string or string) -- The secret password or pass phrase to test. It must be at most 72 bytes long. It must not contain the zero byte. Unicode strings will be encoded as UTF-8.
- bcrypt_hash (byte string, bytearray) -- The reference bcrypt hash the password needs to be checked against.
- Raises
ValueError -- if the password does not match
HKDF
The HMAC-based Extract-and-Expand key derivation function (HKDF) was designed by Hugo Krawczyk. It is standardized in RFC 5869 and in NIST SP-800 56C.
This KDF is not suitable for deriving keys from a password or for key stretching.
Example, for deriving two AES256 keys:
from Crypto.Protocol.KDF import HKDF from Crypto.Hash import SHA512 from Crypto.Random import get_random_bytes salt = get_random_bytes(16) key1, key2 = HKDF(master_secret, 32, salt, SHA512, 2)
- Crypto.Protocol.KDF.HKDF(master, key_len, salt, hashmod, num_keys=1, context=None)
Derive one or more keys from a master secret using the HMAC-based KDF defined in RFC5869.
- Parameters
- master (byte string) -- The unguessable value used by the KDF to generate the other keys. It must be a high-entropy secret, though not necessarily uniform. It must not be a password.
- key_len (integer) -- The length in bytes of every derived key.
- salt (byte string) -- A non-secret, reusable value that strengthens the randomness extraction step. Ideally, it is as long as the digest size of the chosen hash. If empty, a string of zeroes in used.
- hashmod (module) -- A cryptographic hash algorithm from Crypto.Hash. Crypto.Hash.SHA512 is a good choice.
- num_keys (integer) -- The number of keys to derive. Every key is key_len bytes long. The maximum cumulative length of all keys is 255 times the digest size.
- context (byte string) -- Optional identifier describing what the keys are used for.
- Returns
A byte string or a tuple of byte strings.
SP 800-180 Counter Mode
A KDF can be generically constructed with a pseudorandom function (PRF). If the PRF has a fixed-length output, you can evaluate the PRF multiple times and concatenate the results until you collect enough derived keying material.
This function implements such type of KDF, where a counter contributes to each invokation of the PRF, as defined in NIST SP 800-108 Rev 1. The NIST standard only allows the use of HMAC (recommended) and CMAC (not recommended) as PRF.
This KDF is not suitable for deriving keys from a password.
Example 1 (HMAC as PRF, one AES128 key to derive):
>> from Crypto.Hash import SHA256, HMAC >> >> def prf(s, x): >> return HMAC.new(s, x, SHA256).digest() >> >> key_derived = SP800_108_Counter(secret, 16, prf, label=b'Key A')
Example 2 (HMAC as PRF, two AES128 keys to derive):
>> from Crypto.Hash import SHA256, HMAC >> >> def prf(s, x): >> return HMAC.new(s, x, SHA256).digest() >> >> key_A, key_B = SP800_108_Counter(secret, 16, prf, num_keys=2, label=b'Key AB')
Example 3 (CMAC as PRF, two AES256 keys to derive):
>> from Crypto.Cipher import AES >> from Crypto.Hash import SHA256, CMAC >> >> def prf(s, x): >> return CMAC.new(s, x, AES).digest() >> >> key_A, key_B = SP800_108_Counter(secret, 32, prf, num_keys=2, label=b'Key AB')
- Crypto.Protocol.KDF.SP800_108_Counter(master, key_len, prf, num_keys=None, label=b'', context=b'')
Derive one or more keys from a master secret using a pseudorandom function in Counter Mode, as specified in NIST SP 800-108r1.
- Parameters
- master (byte string) -- The secret value used by the KDF to derive the other keys. It must not be a password. The length on the secret must be consistent with the input expected by the prf function.
- key_len (integer) -- The length in bytes of each derived key.
- prf (function) -- A pseudorandom function that takes two byte strings as parameters: the secret and an input. It returns another byte string.
- num_keys (integer) -- The number of keys to derive. Every key is key_len bytes long. By default, only 1 key is derived.
- label (byte string) -- Optional description of the purpose of the derived keys. It must not contain zero bytes.
- context (byte string) -- Optional information pertaining to the protocol that uses the keys, such as the identity of the participants, nonces, session IDs, etc. It must not contain zero bytes.
- Returns
- a byte string (if num_keys is not specified), or
- a tuple of byte strings (if num_key is specified).
PBKDF1
PBKDF1 is an old key derivation function defined in version 2.0 of the PKCS#5 standard (v1.5) or in RFC2898.
- WARNING:
Newer applications should use the more secure and versatile scrypt instead.
- Crypto.Protocol.KDF.PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None)
Derive one key from a password (or passphrase).
This function performs key derivation according to an old version of the PKCS#5 standard (v1.5) or RFC2898.
- Parameters
- password (string) -- The secret password to generate the key from.
- salt (byte string) -- An 8 byte string to use for better protection from dictionary attacks. This value does not need to be kept secret, but it should be randomly chosen for each derivation.
- dkLen (integer) -- The length of the desired key. The default is 16 bytes, suitable for instance for Crypto.Cipher.AES.
- count (integer) -- The number of iterations to carry out. The recommendation is 1000 or more.
- hashAlgo (module) -- The hash algorithm to use, as a module or an object from the Crypto.Hash package. The digest length must be no shorter than dkLen. The default algorithm is Crypto.Hash.SHA1.
- Returns
A byte string of length dkLen that can be used as key.
Secret Sharing Schemes
This module implements the Shamir's secret sharing protocol described in the paper "How to share a secret".
The secret can be split into an arbitrary number of shares (n), such that it is sufficient to collect just k of them to reconstruct it (k < n). For instance, one may want to grant 16 people the ability to access a system with a pass code, at the condition that at least 3 of them are present at the same time. As they join their shares, the pass code is revealed. In that case, n=16 and k=3.
In the Shamir's secret sharing scheme, the n shares are created by first defining a polynomial of degree k-1:
q(x) = a_0 + a_1 x + a_2 x^2 + \ldots + a_{k-1} x^{k-1}
The coefficient a_0 is fixed with the secret value. The coefficients a_1 \ldots a_{k-1} are random and they are discarded as soon as the shares are created.
Each share is a pair (x_i, y_i), where x_i is an arbitrary but unique number assigned to the share's recipient and y_i=q(x_i).
This implementation has the following properties:
- The secret is a byte string of 16 bytes (e.g. an AES 128 key).
- Each share is a byte string of 16 bytes.
- The recipients of the shares are assigned an integer starting from 1 (share number x_i).
- The polynomial q(x) is defined over the field GF(2^{128}) with the same irriducible polynomial as used in AES-GCM: 1 + x + x^2 + x^7 + x^{128}.
It can be compatible with the popular ssss tool when used with the 128 bit security level and no dispersion: the command line arguments must include -s 128 -D. Note that ssss uses a slightly different polynomial:
r(x) = a_0 + a_1 x + a_2 x^2 + \ldots + a_{k-1} x^{k-1} + x^k
which requires you to specify ssss=True when calling split() and combine().
Each recipient needs to hold both the share number (x_i, which is not confidential) and the secret (which needs to be protected securely).
As an example, the following code shows how to protect a file meant for 5 people, in such a way that any 2 of them are sufficient to reassemble it:
>>> from binascii import hexlify >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> from Crypto.Protocol.SecretSharing import Shamir >>> >>> key = get_random_bytes(16) >>> shares = Shamir.split(2, 5, key) >>> for idx, share in shares: >>> print "Index #%d: %s" % (idx, hexlify(share)) >>> >>> with open("clear.txt", "rb") as fi, open("enc.txt", "wb") as fo: >>> cipher = AES.new(key, AES.MODE_EAX) >>> ct, tag = cipher.encrypt(fi.read()), cipher.digest() >>> fo.write(cipher.nonce + tag + ct)
Each person can be given one share and the encrypted file.
When 2 people gather together with their shares, they can decrypt the file:
>>> from binascii import unhexlify >>> from Crypto.Cipher import AES >>> from Crypto.Protocol.SecretSharing import Shamir >>> >>> shares = [] >>> for x in range(2): >>> in_str = raw_input("Enter index and share separated by comma: ") >>> idx, share = [ strip(s) for s in in_str.split(",") ] >>> shares.append((idx, unhexlify(share))) >>> key = Shamir.combine(shares) >>> >>> with open("enc.txt", "rb") as fi: >>> nonce, tag = [ fi.read(16) for x in range(2) ] >>> cipher = AES.new(key, AES.MODE_EAX, nonce) >>> try: >>> result = cipher.decrypt(fi.read()) >>> cipher.verify(tag) >>> with open("clear2.txt", "wb") as fo: >>> fo.write(result) >>> except ValueError: >>> print "The shares were incorrect"
- ATTENTION:
Reconstruction may succeed but still produce the incorrect secret if any of the presented shares is incorrect (due to data corruption or to a malicious participant).
It is extremely important to also use an authentication mechanism (such as the EAX cipher mode in the example).
- class Crypto.Protocol.SecretSharing.Shamir
Shamir's secret sharing scheme.
A secret is split into n shares, and it is sufficient to collect k of them to reconstruct the secret.
- static combine(shares, ssss=False)
Recombine a secret, if enough shares are presented.
- Parameters
- shares (tuples) -- The k tuples, each containin the index (an integer) and the share (a byte string, 16 bytes long) that were assigned to a participant.
- ssss (bool) -- If True, the shares were produced by the ssss utility. Default: False.
- Returns
The original secret, as a byte string (16 bytes long).
- static split(k, n, secret, ssss=False)
Split a secret into n shares.
The secret can be reconstructed later using just k shares out of the original n. Each share must be kept confidential to the person it was assigned to.
Each share is associated to an index (starting from 1).
- Parameters
- k (integer) -- The sufficient number of shares to reconstruct the secret (k < n).
- n (integer) -- The number of shares that this method will create.
- secret (byte string) -- A byte string of 16 bytes (e.g. the AES 128 key).
- ssss (bool) -- If True, the shares can be used with the ssss utility. Default: False.
- Return (tuples):
n tuples. A tuple is meant for each participant and it contains two items:
- the unique index (an integer)
- the share (a byte string, 16 bytes)
Diffie-Hellman Key Agreement
Diffie-Hellman (DH) is a key agreement scheme based on asymmetric cryptography.
It enables two parties (below referred to as U and V) to jointly compute a shared secret across an untrusted communication channel, without explicitly transmitting the secret itself or parts of it.
In other words, an adversary can monitor the channel, see all exchanged messages, and still learn nothing about the shared secret.
The shared secret is not used directly. The two parties will derive symmetric keys from it, and use those to encrypt and authenticate subsequent messages.
[image]
- NOTE:
The Diffie-Hellman protocol is fairly generic and it can be implemented in many ways.
This Python module implements Diffie-Hellman according to Chapter 6 of NIST SP 800-56A Rev. 3, and only for elliptic curve cryptography (Ecc CDH).
Examples
First, a minimal example where only static keys are used:
from Crypto.PublicKey import ECC from Crypto.Hash import SHAKE128 from Crypto.Protocol.DH import key_agreement # This KDF has been agreed in advance def kdf(x): return SHAKE128.new(x).read(32) # In a real scenario, this key already exists U = ECC.generate(curve='p256') # In a real scenario, this key is received from the peer # and it is verified as authentic V = ECC.generate(curve='p256').public_key() session_key = key_agreement(static_priv=U, static_pub=V, kdf=kdf) # session_key is an AES-256 key, which will be used to encrypt # subsequent communications
NIST SP 800-56A recommends to bind the key agreement to some information concerning the context of the operation, for instance a description of what the keys are used for:
from Crypto.Hash import TupleHash128 from Crypto.Protocol.DH import key_agreement # Random value (e.g., a nonce) session_salt = b'XYZ' # The unique identifier of each party id_u = 'Client 12' id_v = 'Server 25' def kdf(x): h = TupleHash128.new(digest_bytes=32) h.update(x, session_salt, id_u.encode(), # To UTF-8 id_v.encode(), # To UTF-8 b'Email encryption', b'TupleHash128', b'AES256') return h.digest() # In a real scenario, this key already exists U = ECC.generate(curve='p256') # In a real scenario, this key is received from the peer # and it is verified as authentic V = ECC.generate(curve='p256').public_key() key = key_agreement(static_priv=U, static_pub=V, kdf=kdf)
The examples above all used static keys only. In order to achieve Perfect Forward Secrecy, it is recommended that at least one party (but ideally both) contributes to the key agreement with one ephemeral key (that is, one key pair generated for the session, and destroyed at the end):
from Crypto.PublicKey import ECC from Crypto.Hash import SHAKE128 from Crypto.Protocol.DH import key_agreement # This KDF has been agreed in advance def kdf(x): return SHAKE128.new(x).read(32) # In a real scenario, this long-term key already exists U_static = ECC.generate(curve='p256') # This ephemeral key is generated only for this session U_ephemeral = ECC.generate(curve='p256') # In a real scenario, this long-term key is received from the peer # and it is verified as authentic V_static = ECC.generate(curve='p256').public_key() # In a real scenario, the peer generated this ephemeral key only # for this session. It doesn't need to be authenticated if the # static key of V already has been. V_ephemeral = ECC.generate(curve='p256').public_key() session_key = key_agreement(static_priv=U_static, static_pub=V_static, eph_priv=U_ephemeral, eph_pub=V_ephemeral, kdf=kdf) # session_key is an AES-256 key, which will be used to encrypt # subsequent communications
Specification
- Crypto.Protocol.DH.key_agreement(**kwargs)
Perform a Diffie-Hellman key agreement.
- Keywords:
- kdf (callable):
A key derivation function that accepts bytes as input and returns bytes.
- static_priv (EccKey):
The local static private key. Optional.
- static_pub (EccKey):
The static public key that belongs to the peer. Optional.
- eph_priv (EccKey):
The local ephemeral private key, generated for this session. Optional.
- eph_pub (EccKey):
The ephemeral public key, received from the peer for this session. Optional.
At least two keys must be passed, of which one is a private key and one a public key.
- Returns (bytes):
The derived secret key material.
- Crypto.Protocol.DH.import_x25519_public_key(encoded)
Create a new X25519 public key object, starting from the key encoded as raw bytes, in the format described in RFC7748.
- Parameters
encoded (bytes) -- The x25519 public key to import. It must be 32 bytes.
- Returns
a new Ecc key object.
- Return type
Crypto.PublicKey.EccKey
- Raises
ValueError -- when the given key cannot be parsed.
- Crypto.Protocol.DH.import_x25519_private_key(encoded)
Create a new X25519 private key object, starting from the key encoded as raw bytes, in the format described in RFC7748.
- Parameters
encoded (bytes) -- The X25519 private key to import. It must be 32 bytes.
- Returns
a new Ecc key object.
- Return type
Crypto.PublicKey.EccKey
- Raises
ValueError -- when the given key cannot be parsed.
- Crypto.Protocol.DH.import_x448_public_key(encoded)
Create a new X448 public key object, starting from the key encoded as raw bytes, in the format described in RFC7748.
- Parameters
encoded (bytes) -- The x448 public key to import. It must be 56 bytes.
- Returns
a new Ecc key object.
- Return type
Crypto.PublicKey.EccKey
- Raises
ValueError -- when the given key cannot be parsed.
- Crypto.Protocol.DH.import_x448_private_key(encoded)
Create a new X448 private key object, starting from the key encoded as raw bytes, in the format described in RFC7748.
- Parameters
encoded (bytes) -- The X448 private key to import. It must be 56 bytes.
- Returns
a new Ecc key object.
- Return type
Crypto.PublicKey.EccKey
- Raises
ValueError -- when the given key cannot be parsed.
Key Derivation Function
The kdf parameter must be a cryptographically secure key derivation function, not password-based. For instance, some reasonable choices are:
- HKDF
- SHAKE128 or SHAKE256
- SP 800-180 Counter Mode
- TupleHash128 or TupleHash256
KDFs are typically fed with multiple inputs, whereas the kdf function must take exactly one (of type bytes). Therefore, a temporary function kdf should be constructed by fixing some of the inputs of the underlying KDF. For example using functools:
from Crypto.Protocol.KDF import HKDF from Crypto.Hash import SHA256 import functools kdf = functoools.partial(HKDF, key_len=32, salt=b'nonce', hashmod=SHA256, num_keys=2, context=b'Some context about the operation') # Pass kdf to key_agreement()
In other cases, defining a local function can be sufficient:
import os from Crypto.Hash import SHAKE128 # A non-secret value generated for the session nonce = os.urandom(16) def kdf(x): return SHAKE128.new(x + nonce).read(32) # Pass kdf to key_agreement()
Recommendations
This module only provides the fundamental low-level primitive of the Diffie-Hellman key agreement. When designing the procotol, users should ensure that:
- Each party is certain that the public key of the peer is authentic, and that the risk of Man-in-the-Middle attacks is considered.
- The requirement for Perfect Forward Secrecy is understood and, if necessary, ephemeral keys are generated, used in the key agreement, and then destroyed.
- The risk of Key compromise impersonation is understood. With that attack, an adversary that compromises our static key, can impersonate any other user to us. The use of ephemeral keys addresses this risk too.
- Some form of Key Confirmation is included after the key agreement (e.g., with a MAC), to immediately detect if the shared secret has not being correctly calculated.
- Key Derivation Functions
- Secret Sharing Schemes
- Diffie-Hellman Key Agreement
Crypto.IO package
Modules for reading and writing cryptographic data.
Pem
Set of functions for encapsulating data according to the PEM format.
PEM (Privacy Enhanced Mail) was an IETF standard for securing emails via a Public Key Infrastructure. It is specified in RFC 1421-1424.
Even though it has been abandoned, the simple message encapsulation it defined is still widely used today for encoding binary cryptographic objects like keys and certificates into text.
- Crypto.IO.PEM.decode(pem_data, passphrase=None)
Decode a PEM block into binary.
- Parameters
- pem_data (string) -- The PEM block.
- passphrase (byte string) -- If given and the PEM block is encrypted, the key will be derived from the passphrase.
- Returns
A tuple with the binary data, the marker string, and a boolean to indicate if decryption was performed.
- Raises
ValueError -- if decoding fails, if the PEM file is encrypted and no passphrase has
been provided or if the passphrase is incorrect.
- Crypto.IO.PEM.encode(data, marker, passphrase=None, randfunc=None)
Encode a piece of binary data into PEM format.
- Parameters
- data (byte string) -- The piece of binary data to encode.
- marker (string) -- The marker for the PEM block (e.g. "PUBLIC KEY"). Note that there is no official master list for all allowed markers. Still, you can refer to the OpenSSL source code.
- passphrase (byte string) -- If given, the PEM block will be encrypted. The key is derived from the passphrase.
- randfunc (callable) -- Random number generation function; it accepts an integer N and returns a byte string of random data, N bytes long. If not given, a new one is instantiated.
- Returns
The PEM block, as a string.
Pkcs#8
PKCS#8 is a standard for encoding asymmetric private keys, such as Rsa or Ecc, so that they can be stored or exchanged. The private key can either be encrypted with a passphrase or left in the clear.
Example of how to encrypt an Ecc private key (even though normally you would use the export_key method of the key itself):
from Crypto.PublicKey import ECC from Crypto.IO import PKCS8 key = ECC.generate(curve='p256') pkey = key.export_key(format='DER'), passphrase = b'secret santa' encrypted_key = PKCS8.wrap( pkey, "1.2.840.10045.2.1", # unrestricted ECC passphrase=passphrase, protection='PBKDF2WithHMAC-SHA512AndAES256-CBC', prot_params={'iteration_count': 210000} )
Encryption parameters
When creating an encrypted Pkcs#8 container, the two parameters protection and prot_params drive the encryption algorithm:
protection (mandatory), a string that defines how the encryption key is derived from the passphrase, and which cipher to use. The string must follow one of the two patterns:
- 'PBKDF2WithHMAC-' + hash + 'And' + cipher
- 'scryptAnd' + cipher
where hash is the name of the cryptographic hash (recommended: 'SHA512') and cipher is the name of the cipher mode to use (recommended: 'AES256-CBC').
Other values for hash are 'SHA1', 'SHA224', 'SHA256', 'SHA384', 'SHA512-224', 'SHA512-256', 'SHA3-224', 'SHA3-256', 'SHA3-384', 'SHA3-512'.
Other values for cipher are 'AES128-GCM', 'AES192-GCM', 'AES256-GCM', 'AES128-CBC', 'AES192-CBC' or 'DES-EDE3-CBC'.
prot_params (optional), a dictionary to override the parameters of the key derivation function:
Key Description iteration_count The KDF algorithm is repeated several times to slow down brute force attacks on passwords (called N or CPU/memory cost in scrypt).
For PBKDF2 with SHA512 the recommended value is 210 000 (default is 1 000).
For scrypt the recommended value is 131 072 (default value is 16 384).salt_size Salt is used to thwart dictionary and rainbow attacks on passwords. The default value is 8 bytes. block_size (scrypt only) Memory-cost (r). The default value is 8. parallelization (scrypt only) CPU-cost (p). The default value is 1.
Legacy algorithms
The following protection mechanisms are only supported for importing keys. They are much weaker than the ones listed above, and they are provided for backward compatibility only:
- pbeWithMD5AndRC2-CBC
- pbeWithMD5AndDES-CBC
- pbeWithSHA1AndRC2-CBC
- pbeWithSHA1AndDES-CBC
- Crypto.IO.PKCS8.unwrap(p8_private_key, passphrase=None)
Unwrap a private key from a Pkcs#8 blob (clear or encrypted).
- Parameters
p8_private_key (bytes) -- The private key wrapped into a Pkcs#8 container, DER encoded.
- Keyword Arguments
passphrase (byte string or string) -- The passphrase to use to decrypt the blob (if it is encrypted).
- Returns
A tuple containing
- the algorithm identifier of the wrapped key (OID, dotted string)
- the private key (bytes, DER encoded)
- the associated parameters (bytes, DER encoded) or None
- Raises
ValueError -- if decoding fails
- Crypto.IO.PKCS8.wrap(private_key, key_oid, passphrase=None, protection=None, prot_params=None, key_params=<Crypto.Util.asn1.DerNull object>, randfunc=None)
Wrap a private key into a Pkcs#8 blob (clear or encrypted).
- Parameters
- private_key (bytes) -- The private key encoded in binary form. The actual encoding is algorithm specific. In most cases, it is DER.
- key_oid (string) -- The object identifier (OID) of the private key to wrap. It is a dotted string, like '1.2.840.113549.1.1.1' (for Rsa keys) or '1.2.840.10045.2.1' (for Ecc keys).
- Keyword Arguments
- passphrase (bytes or string) -- The secret passphrase from which the wrapping key is derived. Set it only if encryption is required.
- protection (string) -- The identifier of the algorithm to use for securely wrapping the key. Refer to the encryption parameters . The default value is 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'.
- prot_params (dictionary) -- Parameters for the key derivation function (KDF). Refer to the encryption parameters .
- key_params (DER object or None) -- The parameters field to use in the AlgorithmIdentifier SEQUENCE. If None, no parameters field will be added. By default, the ASN.1 type NULL is used.
- randfunc (callable) -- Random number generation function; it should accept a single integer N and return a string of random data, N bytes long. If not specified, a new RNG will be instantiated from Crypto.Random.
- Returns
The PKCS#8-wrapped private key (possibly encrypted).
- Return type
bytes
Crypto.Random package
- Crypto.Random.get_random_bytes(N)
Return a random byte string of length N.
Crypto.Random.random module
- Crypto.Random.random.getrandbits(N)
Return a random integer, at most N bits long.
- Crypto.Random.random.randrange([start], stop[, step])
Return a random integer in the range (start, stop, step). By default, start is 0 and step is 1.
- Crypto.Random.random.randint(a, b)
Return a random integer in the range no smaller than a and no larger than b.
- Crypto.Random.random.choice(seq)
Return a random element picked from the sequence seq.
- Crypto.Random.random.shuffle(seq)
Randomly shuffle the sequence seq in-place.
- Crypto.Random.random.sample(population, k)
Randomly chooses k distinct elements from the list population.
Crypto.Util package
Useful modules that don't belong in any other package.
Crypto.Util.asn1 module
This module provides minimal support for encoding and decoding ASN.1 DER objects.
- class Crypto.Util.asn1.DerBitString(value=b'', implicit=None, explicit=None)
Class to model a DER BIT STRING.
An example of encoding is:
>>> from Crypto.Util.asn1 import DerBitString >>> bs_der = DerBitString(b'\xAA') >>> bs_der.value += b'\xBB' >>> print(bs_der.encode().hex())
which will show 030300aabb, the DER encoding for the bit string b'\xAA\xBB'.
For decoding:
>>> s = bytes.fromhex('030300aabb') >>> try: >>> bs_der = DerBitString() >>> bs_der.decode(s) >>> print(bs_der.value.hex()) >>> except ValueError: >>> print "Not a valid DER BIT STRING"
the output will be aabb.
- Variables
value (byte string) -- The content of the string
- decode(der_encoded, strict=False)
Decode a complete DER BIT STRING, and re-initializes this object with it.
- Parameters
- der_encoded (byte string) -- a complete DER BIT STRING.
- strict (boolean) -- Whether decoding must check for strict DER compliancy.
- Raises
ValueError -- in case of parsing errors.
- encode()
Return the DER BIT STRING, fully encoded as a byte string.
- class Crypto.Util.asn1.DerBoolean(value=False, implicit=None, explicit=None)
Class to model a DER-encoded BOOLEAN.
An example of encoding is:
>>> from Crypto.Util.asn1 import DerBoolean >>> bool_der = DerBoolean(True) >>> print(bool_der.encode().hex())
which will show 0101ff, the DER encoding of True.
And for decoding:
>>> s = bytes.fromhex('0101ff') >>> try: >>> bool_der = DerBoolean() >>> bool_der.decode(s) >>> print(bool_der.value) >>> except ValueError: >>> print "Not a valid DER BOOLEAN"
the output will be True.
- Variables
value (boolean) -- The boolean value
- decode(der_encoded, strict=False)
Decode a DER-encoded BOOLEAN, and re-initializes this object with it.
- Parameters
der_encoded (byte string) -- A DER-encoded BOOLEAN.
- Raises
ValueError -- in case of parsing errors.
- encode()
Return the DER BOOLEAN, fully encoded as a binary string.
- class Crypto.Util.asn1.DerInteger(value=0, implicit=None, explicit=None)
Class to model a DER INTEGER.
An example of encoding is:
>>> from Crypto.Util.asn1 import DerInteger >>> from binascii import hexlify, unhexlify >>> int_der = DerInteger(9) >>> print hexlify(int_der.encode())
which will show 020109, the DER encoding of 9.
And for decoding:
>>> s = unhexlify(b'020109') >>> try: >>> int_der = DerInteger() >>> int_der.decode(s) >>> print int_der.value >>> except ValueError: >>> print "Not a valid DER INTEGER"
the output will be 9.
- Variables
value (integer) -- The integer value
- decode(der_encoded, strict=False)
Decode a DER-encoded INTEGER, and re-initializes this object with it.
- Parameters
der_encoded (byte string) -- A complete INTEGER DER element.
- Raises
ValueError -- in case of parsing errors.
- encode()
Return the DER INTEGER, fully encoded as a binary string.
- class Crypto.Util.asn1.DerNull
Class to model a DER NULL element.
- class Crypto.Util.asn1.DerObject(asn1Id=None, payload=b'', implicit=None, constructed=False, explicit=None)
Base class for defining a single DER object.
This class should never be directly instantiated.
- decode(der_encoded, strict=False)
Decode a complete DER element, and re-initializes this object with it.
- Parameters
der_encoded (byte string) -- A complete DER element.
- Raises
ValueError -- in case of parsing errors.
- encode()
Return this DER element, fully encoded as a binary byte string.
- class Crypto.Util.asn1.DerObjectId(value='', implicit=None, explicit=None)
Class to model a DER OBJECT ID.
An example of encoding is:
>>> from Crypto.Util.asn1 import DerObjectId >>> from binascii import hexlify, unhexlify >>> oid_der = DerObjectId("1.2") >>> oid_der.value += ".840.113549.1.1.1" >>> print hexlify(oid_der.encode())
which will show 06092a864886f70d010101, the DER encoding for the Rsa Object Identifier 1.2.840.113549.1.1.1.
For decoding:
>>> s = unhexlify(b'06092a864886f70d010101') >>> try: >>> oid_der = DerObjectId() >>> oid_der.decode(s) >>> print oid_der.value >>> except ValueError: >>> print "Not a valid DER OBJECT ID"
the output will be 1.2.840.113549.1.1.1.
- Variables
value (string) -- The Object ID (OID), a dot separated list of integers
- decode(der_encoded, strict=False)
Decode a complete DER OBJECT ID, and re-initializes this object with it.
- Parameters
- der_encoded (byte string) -- A complete DER OBJECT ID.
- strict (boolean) -- Whether decoding must check for strict DER compliancy.
- Raises
ValueError -- in case of parsing errors.
- encode()
Return the DER OBJECT ID, fully encoded as a binary string.
- class Crypto.Util.asn1.DerOctetString(value=b'', implicit=None)
Class to model a DER OCTET STRING.
An example of encoding is:
>>> from Crypto.Util.asn1 import DerOctetString >>> from binascii import hexlify, unhexlify >>> os_der = DerOctetString(b'\xaa') >>> os_der.payload += b'\xbb' >>> print hexlify(os_der.encode())
which will show 0402aabb, the DER encoding for the byte string b'\xAA\xBB'.
For decoding:
>>> s = unhexlify(b'0402aabb') >>> try: >>> os_der = DerOctetString() >>> os_der.decode(s) >>> print hexlify(os_der.payload) >>> except ValueError: >>> print "Not a valid DER OCTET STRING"
the output will be aabb.
- Variables
payload (byte string) -- The content of the string
- class Crypto.Util.asn1.DerSequence(startSeq=None, implicit=None, explicit=None)
Class to model a DER SEQUENCE.
This object behaves like a dynamic Python sequence.
Sub-elements that are INTEGERs behave like Python integers.
Any other sub-element is a binary string encoded as a complete DER sub-element (TLV).
An example of encoding is:
>>> from Crypto.Util.asn1 import DerSequence, DerInteger >>> from binascii import hexlify, unhexlify >>> obj_der = unhexlify('070102') >>> seq_der = DerSequence([4]) >>> seq_der.append(9) >>> seq_der.append(obj_der.encode()) >>> print hexlify(seq_der.encode())
which will show 3009020104020109070102, the DER encoding of the sequence containing 4, 9, and the object with payload 02.
For decoding:
>>> s = unhexlify(b'3009020104020109070102') >>> try: >>> seq_der = DerSequence() >>> seq_der.decode(s) >>> print len(seq_der) >>> print seq_der[0] >>> print seq_der[:] >>> except ValueError: >>> print "Not a valid DER SEQUENCE"
the output will be:
3 4 [4, 9, b'']
- decode(der_encoded, strict=False, nr_elements=None, only_ints_expected=False)
Decode a complete DER SEQUENCE, and re-initializes this object with it.
- Parameters
- der_encoded (byte string) -- A complete SEQUENCE DER element.
- nr_elements (None or integer or list of integers) -- The number of members the SEQUENCE can have
- only_ints_expected (boolean) -- Whether the SEQUENCE is expected to contain only integers.
- strict (boolean) -- Whether decoding must check for strict DER compliancy.
- Raises
ValueError -- in case of parsing errors.
DER INTEGERs are decoded into Python integers. Any other DER element is not decoded. Its validity is not checked.
- encode()
Return this DER SEQUENCE, fully encoded as a binary string.
- Raises
ValueError -- if some elements in the sequence are neither integers
nor byte strings.
- hasInts(only_non_negative=True)
Return the number of items in this sequence that are integers.
- Parameters
only_non_negative (boolean) -- If True, negative integers are not counted in.
- hasOnlyInts(only_non_negative=True)
Return True if all items in this sequence are integers or non-negative integers.
This function returns False is the sequence is empty, or at least one member is not an integer.
- Parameters
only_non_negative (boolean) -- If True, the presence of negative integers causes the method to return False.
- class Crypto.Util.asn1.DerSetOf(startSet=None, implicit=None)
Class to model a DER SET OF.
An example of encoding is:
>>> from Crypto.Util.asn1 import DerBitString >>> from binascii import hexlify, unhexlify >>> so_der = DerSetOf([4,5]) >>> so_der.add(6) >>> print hexlify(so_der.encode())
which will show 3109020104020105020106, the DER encoding of a SET OF with items 4,5, and 6.
For decoding:
>>> s = unhexlify(b'3109020104020105020106') >>> try: >>> so_der = DerSetOf() >>> so_der.decode(s) >>> print [x for x in so_der] >>> except ValueError: >>> print "Not a valid DER SET OF"
the output will be [4, 5, 6].
- add(elem)
Add an element to the set.
- Parameters
elem (byte string or integer) -- An element of the same type of objects already in the set. It can be an integer or a DER encoded object.
- decode(der_encoded, strict=False)
Decode a complete SET OF DER element, and re-initializes this object with it.
DER INTEGERs are decoded into Python integers. Any other DER element is left undecoded; its validity is not checked.
- Parameters
- der_encoded (byte string) -- a complete DER BIT SET OF.
- strict (boolean) -- Whether decoding must check for strict DER compliancy.
- Raises
ValueError -- in case of parsing errors.
- encode()
Return this SET OF DER element, fully encoded as a binary string.
Crypto.Util.Padding module
This module provides minimal support for adding and removing standard padding from data. Example:
>>> from Crypto.Util.Padding import pad, unpad >>> from Crypto.Cipher import AES >>> from Crypto.Random import get_random_bytes >>> >>> data = b'Unaligned' # 9 bytes >>> key = get_random_bytes(32) >>> iv = get_random_bytes(16) >>> >>> cipher1 = AES.new(key, AES.MODE_CBC, iv) >>> ct = cipher1.encrypt(pad(data, 16)) >>> >>> cipher2 = AES.new(key, AES.MODE_CBC, iv) >>> pt = unpad(cipher2.decrypt(ct), 16) >>> assert(data == pt)
- Crypto.Util.Padding.pad(data_to_pad, block_size, style='pkcs7')
Apply standard padding.
- Parameters
- data_to_pad (byte string) -- The data that needs to be padded.
- block_size (integer) -- The block boundary to use for padding. The output length is guaranteed to be a multiple of block_size.
- style (string) -- Padding algorithm. It can be 'pkcs7' (default), 'iso7816' or 'x923'.
- Returns
the original data with the appropriate padding added at the end.
- Return type
byte string
- Crypto.Util.Padding.unpad(padded_data, block_size, style='pkcs7')
Remove standard padding.
- Parameters
- padded_data (byte string) -- A piece of data with padding that needs to be stripped.
- block_size (integer) -- The block boundary to use for padding. The input length must be a multiple of block_size.
- style (string) -- Padding algorithm. It can be 'pkcs7' (default), 'iso7816' or 'x923'.
- Returns
data without padding.
- Return type
byte string
- Raises
ValueError -- if the padding is incorrect.
Crypto.Util.RFC1751 module
- Crypto.Util.RFC1751.english_to_key(s)
Transform a string into a corresponding key.
Example:
>>> from Crypto.Util.RFC1751 import english_to_key >>> english_to_key('RAM LOIS GOAD CREW CARE HIT') b'66666666'
- Parameters
s (string) -- the string with the words separated by whitespace; the number of words must be a multiple of 6.
- Returns
A byte string.
- Crypto.Util.RFC1751.key_to_english(key)
Transform an arbitrary key into a string containing English words.
Example:
>>> from Crypto.Util.RFC1751 import key_to_english >>> key_to_english(b'66666666') 'RAM LOIS GOAD CREW CARE HIT'
- Parameters
key (byte string) -- The key to convert. Its length must be a multiple of 8.
- Returns
A string of English words.
Crypto.Util.strxor module
Fast XOR for byte strings.
- Crypto.Util.strxor.strxor(term1, term2, output=None)
From two byte strings of equal length, create a third one which is the byte-by-byte XOR of the two.
- Parameters
- term1 (bytes/bytearray/memoryview) -- The first byte string to XOR.
- term2 (bytes/bytearray/memoryview) -- The second byte string to XOR.
- output (bytearray/memoryview) -- The location where the result will be written to. It must have the same length as term1 and term2. If None, the result is returned.
- Return
If output is None, a new byte string with the result. Otherwise None.
- NOTE:
term1 and term2 must have the same length.
- Crypto.Util.strxor.strxor_c(term, c, output=None)
From a byte string, create a second one of equal length where each byte is XOR-red with the same value.
- Parameters
- term (bytes/bytearray/memoryview) -- The byte string to XOR.
- c (int) -- Every byte in the string will be XOR-ed with this value. It must be between 0 and 255 (included).
- output (None or bytearray/memoryview) -- The location where the result will be written to. It must have the same length as term. If None, the result is returned.
- Returns
If output is None, a new bytes string with the result. Otherwise None.
Crypto.Util.Counter module
The Crypto.Util.Counter module provides the functionality to create more complex counter blocks for the CTR cipher mode.
Introduction to counter blocks
CTR (Counter) is a mode of operation for block ciphers. In CTR mode, the ciphertext is generated by dividing the plaintext into blocks and then XOR-ing each block with a unique keystream.
The keystream is produced by encrypting a sequence of counter blocks, which must all be distinct to prevent repetitions in the keystream. Counter blocks themselves do not need to be kept secret. Encryption is done using ECB.
The most straightforward approach to create counter blocks is to include a counter field, and increment it by one within each subsequent counter block.
Creating counter blocks without Counter
The new() function, at the module level under Crypto.Cipher, allows you to create a new CTR cipher object for a specific base algorithm. It provides parameters for defining the structure of the counter block:
- an optional, fixed prefix
- the counter field encoded in big endian mode
The combined length of these two components must match the block size of the algorithm being used. For example, in the case of AES, the block size is typically 16 bytes.
Creating counter blocks with Counter
If you need a more complex structure for the counter block, you can define it in advance with the function Crypto.Util.Counter.new(), and then pass it to new() of the cipher with the counter parameter. The counter block can then have:
- an optional, fixed prefix
- the counter field, encoded in big endian or little endian mode
- an optional, fixed suffix
As before, the total length must match the block size.
The counter blocks with a big endian counter will look like this:
[image]
The counter blocks with a little endian counter will look like this:
[image]
This is an example of AES-CTR encryption with a custom counter:
from Crypto.Cipher import AES from Crypto.Util import Counter from Crypto import Random # The counter block must be # # +--------+----------------+--------+ # | nonce + counter + EFGH + # +--------+----------------+--------+ # 4 bytes 8 bytes 4 bytes nonce = Random.get_random_bytes(4) ctr = Counter.new(64, prefix=nonce, suffix=b'EFGH', little_endian=True, initial_value=10) key = b'AES-128 symm key' plaintext = b'X'*1000000 cipher = AES.new(key, AES.MODE_CTR, counter=ctr) ciphertext = cipher.encrypt(plaintext)
- Crypto.Util.Counter.new(nbits, prefix=b'', suffix=b'', initial_value=1, little_endian=False, allow_wraparound=False)
Create a stateful counter block function suitable for CTR encryption modes.
Each call to the function returns the next counter block. Each counter block is made up by three parts:
prefix counter value postfix The counter value is incremented by 1 at each call.
- Parameters
- nbits (integer) -- Length of the desired counter value, in bits. It must be a multiple of 8.
- prefix (byte string) -- The constant prefix of the counter block. By default, no prefix is used.
- suffix (byte string) -- The constant postfix of the counter block. By default, no suffix is used.
- initial_value (integer) -- The initial value of the counter. Default value is 1. Its length in bits must not exceed the argument nbits.
- little_endian (boolean) -- If True, the counter number will be encoded in little endian format. If False (default), in big endian format.
- allow_wraparound (boolean) -- This parameter is ignored. An OverflowError exception is always raised when the counter wraps around to zero.
- Returns
An object that can be passed with the counter parameter to a CTR mode cipher.
It must hold that len(prefix) + nbits//8 + len(suffix) matches the block size of the underlying block cipher.
Crypto.Util.number module
- Crypto.Util.number.bytes_to_long(s)
Convert a byte string to a long integer (big endian).
In Python 3.2+, use the native method instead:
>>> int.from_bytes(s, 'big')
For instance:
>>> int.from_bytes(b'P', 'big') 80
This is (essentially) the inverse of long_to_bytes().
- Crypto.Util.number.ceil_div(n, d)
Return ceil(n/d), that is, the smallest integer r such that r*d >= n
- Crypto.Util.number.getPrime(N, randfunc=None)
Return a random N-bit prime number.
N must be an integer larger than 1. If randfunc is omitted, then Random.get_random_bytes() is used.
- Crypto.Util.number.getRandomInteger(N, randfunc=None)
Return a random number at most N bits long.
If randfunc is omitted, then Random.get_random_bytes() is used.
Deprecated since version 3.0: This function is for internal use only and may be renamed or removed in the future. Use Crypto.Random.random.getrandbits() instead.
- Crypto.Util.number.getRandomNBitInteger(N, randfunc=None)
Return a random number with exactly N-bits, i.e. a random number between 2**(N-1) and (2**N)-1.
If randfunc is omitted, then Random.get_random_bytes() is used.
Deprecated since version 3.0: This function is for internal use only and may be renamed or removed in the future.
- Crypto.Util.number.getRandomRange(a, b, randfunc=None)
Return a random number n so that a <= n < b.
If randfunc is omitted, then Random.get_random_bytes() is used.
Deprecated since version 3.0: This function is for internal use only and may be renamed or removed in the future. Use Crypto.Random.random.randrange() instead.
- Crypto.Util.number.getStrongPrime(N, e=0, false_positive_prob=1e-06, randfunc=None)
Return a random strong N-bit prime number. In this context, p is a strong prime if p-1 and p+1 have at least one large prime factor.
- Parameters
- N (integer) -- the exact length of the strong prime. It must be a multiple of 128 and > 512.
- e (integer) -- if provided, the returned prime (minus 1) will be coprime to e and thus suitable for Rsa where e is the public exponent.
- false_positive_prob (float) -- The statistical probability for the result not to be actually a prime. It defaults to 10-6. Note that the real probability of a false-positive is far less. This is just the mathematically provable limit.
- randfunc (callable) -- A function that takes a parameter N and that returns a random byte string of such length. If omitted, Crypto.Random.get_random_bytes() is used.
- Returns
The new strong prime.
Deprecated since version 3.0: This function is for internal use only and may be renamed or removed in the future.
- Crypto.Util.number.inverse(u, v)
The inverse of u mod v.
- Crypto.Util.number.isPrime(N, false_positive_prob=1e-06, randfunc=None)
Test if a number N is a prime.
- Parameters
- false_positive_prob (float) -- The statistical probability for the result not to be actually a prime. It defaults to 10-6. Note that the real probability of a false-positive is far less. This is just the mathematically provable limit.
- randfunc (callable) -- A function that takes a parameter N and that returns a random byte string of such length. If omitted, Crypto.Random.get_random_bytes() is used.
- Returns
True if the input is indeed prime.
- Crypto.Util.number.long_to_bytes(n, blocksize=0)
Convert a positive integer to a byte string using big endian encoding.
If blocksize is absent or zero, the byte string will be of minimal length.
Otherwise, the length of the byte string is guaranteed to be a multiple of blocksize. If necessary, zeroes (\x00) are added at the left.
NOTE:
In Python 3, if you are sure that n can fit into blocksize bytes, you can simply use the native method instead:
>>> n.to_bytes(blocksize, 'big')
For instance:
>>> n = 80 >>> n.to_bytes(2, 'big') b'\x00P'
However, and unlike this long_to_bytes() function, an OverflowError exception is raised if n does not fit.
- Crypto.Util.number.size(N)
Returns the size of the number N in bits.
All cryptographic functionalities are organized in sub-packages; each sub-package is dedicated to solving a specific class of problems.
Package | Description |
Crypto.Cipher | Modules for protecting confidentiality that is, for encrypting and decrypting data (example: AES). |
Crypto.Signature | Modules for assuring authenticity, that is, for creating and verifying digital signatures of messages (example: PKCS#1 v1.5). |
Crypto.Hash | Modules for creating cryptographic digests (example: SHA-256). |
Crypto.PublicKey | Modules for generating, exporting or importing public keys (example: Rsa or Ecc). |
Crypto.Protocol | Modules for faciliting secure communications between parties, in most cases by leveraging cryptographic primitives from other modules (example: Shamir's Secret Sharing scheme). |
Crypto.IO | Modules for dealing with encodings commonly used for cryptographic data (example: Pem). |
Crypto.Random | Modules for generating random data. |
Crypto.Util | General purpose routines (example: XOR for byte strings). |
In certain cases, there is some overlap between these categories. For instance, authenticity is also provided by Message Authentication Codes, and some can be built using digests, so they are included in the Crypto.Hash package (example: HMAC). Also, cryptographers have over time realized that encryption without authentication is often of limited value so recent ciphers found in the Crypto.Cipher package embed it (example: GCM).
PyCryptodome strives to maintain strong backward compatibility with the old PyCrypto's API (except for those few cases where that is harmful to security) so a few modules don't appear where they should (example: the ASN.1 module is under Crypto.Util as opposed to Crypto.IO).
Examples
Encrypt data with AES
The following code generates a new AES-128 key and encrypts a piece of data into a file. We use the CTR mode (which is a classic mode of operation, simple but not recommended anymore).
With CTR alone, the receiver is not able to detect if the ciphertext (i.e., the encrypted data) was modified while in transit. To address that risk, we also attach a MAC authentication tag (HMAC with SHA256), made with a second key.
from Crypto.Cipher import AES from Crypto.Hash import HMAC, SHA256 from Crypto.Random import get_random_bytes data = 'secret data to transmit'.encode() aes_key = get_random_bytes(16) hmac_key = get_random_bytes(16) cipher = AES.new(aes_key, AES.MODE_CTR) ciphertext = cipher.encrypt(data) hmac = HMAC.new(hmac_key, digestmod=SHA256) tag = hmac.update(cipher.nonce + ciphertext).digest() with open("encrypted.bin", "wb") as f: f.write(tag) f.write(cipher.nonce) f.write(ciphertext) # Share securely aes_key and hmac_key with the receiver # encrypted.bin can be sent over an unsecure channel
At the other end, the receiver can securely load the piece of data back (if they know the two keys!). Note that the code generates a ValueError exception when tampering is detected.
import sys from Crypto.Cipher import AES from Crypto.Hash import HMAC, SHA256 # Somehow, the receiver securely get aes_key and hmac_key # encrypted.bin can be sent over an unsecure channel with open("encrypted.bin", "rb") as f: tag = f.read(32) nonce = f.read(8) ciphertext = f.read() try: hmac = HMAC.new(hmac_key, digestmod=SHA256) tag = hmac.update(nonce + ciphertext).verify(tag) except ValueError: print("The message was modified!") sys.exit(1) cipher = AES.new(aes_key, AES.MODE_CTR, nonce=nonce) message = cipher.decrypt(ciphertext) print("Message:", message.decode())
Encrypt and authenticate data in one step
The code in the previous section contains three subtle but important design decisions: the nonce of the cipher is authenticated, the authentication is performed after encryption, and encryption and authentication use two uncorrelated keys. It is not easy to securely combine cryptographic primitives, so more modern cryptographic cipher modes have been created such as, the OCB mode (see also other authenticated encryption modes like EAX, GCM, CCM, SIV).
from Crypto.Cipher import AES from Crypto.Random import get_random_bytes data = 'secret data to transmit'.encode() aes_key = get_random_bytes(16) cipher = AES.new(aes_key, AES.MODE_OCB) ciphertext, tag = cipher.encrypt_and_digest(data) assert len(cipher.nonce) == 15 with open("encrypted.bin", "wb") as f: f.write(tag) f.write(cipher.nonce) f.write(ciphertext) # Share securely aes_key with the receiver # encrypted.bin can be sent over an unsecure channel
Decryption is also simpler:
import sys from Crypto.Cipher import AES # Somehow, the receiver securely get aes_key and hmac_key # encrypted.bin can be sent over an unsecure channel with open("encrypted.bin", "rb") as f: tag = f.read(16) nonce = f.read(15) ciphertext = f.read() cipher = AES.new(aes_key, AES.MODE_OCB, nonce=nonce) try: message = cipher.decrypt_and_verify(ciphertext, tag) except ValueError: print("The message was modified!") sys.exit(1) print("Message:", message.decode())
Generate an RSA key
The following code generates a new Rsa key pair (secret) and saves it into a file, protected by a password. We use the scrypt key derivation function to thwart dictionary attacks. At the end, the code prints our the Rsa public key in ASCII/Pem format:
from Crypto.PublicKey import RSA secret_code = "Unguessable" key = RSA.generate(2048) encrypted_key = key.export_key(passphrase=secret_code, pkcs=8, protection="scryptAndAES128-CBC", prot_params={'iteration_count':131072}) with open("rsa_key.bin", "wb") as f: f.write(encrypted_key) print(key.publickey().export_key())
The following code reads the private Rsa key back in, and then prints again the public key:
from Crypto.PublicKey import RSA secret_code = "Unguessable" encoded_key = open("rsa_key.bin", "rb").read() key = RSA.import_key(encoded_key, passphrase=secret_code) print(key.publickey().export_key())
Generate public key and private key
The following code generates public key stored in receiver.pem and private key stored in private.pem. These files will be used in the examples below. Every time, it generates different public key and private key pair.
from Crypto.PublicKey import RSA key = RSA.generate(2048) private_key = key.export_key() with open("private.pem", "wb") as f: f.write(private_key) public_key = key.publickey().export_key() with open("receiver.pem", "wb") as f: f.write(public_key)
Encrypt data with RSA
The following code encrypts a piece of data for a receiver we have the Rsa public key of. The Rsa public key is stored in a file called receiver.pem.
Since we want to be able to encrypt an arbitrary amount of data, we use a hybrid encryption scheme. We use Rsa with PKCS#1 OAEP for asymmetric encryption of an AES session key. The session key can then be used to encrypt all the actual data.
As in the first example, we use the EAX mode to allow detection of unauthorized modifications.
from Crypto.PublicKey import RSA from Crypto.Random import get_random_bytes from Crypto.Cipher import AES, PKCS1_OAEP data = "I met aliens in UFO. Here is the map.".encode("utf-8") recipient_key = RSA.import_key(open("receiver.pem").read()) session_key = get_random_bytes(16) # Encrypt the session key with the public RSA key cipher_rsa = PKCS1_OAEP.new(recipient_key) enc_session_key = cipher_rsa.encrypt(session_key) # Encrypt the data with the AES session key cipher_aes = AES.new(session_key, AES.MODE_EAX) ciphertext, tag = cipher_aes.encrypt_and_digest(data) with open("encrypted_data.bin", "wb") as f: f.write(enc_session_key) f.write(cipher_aes.nonce) f.write(tag) f.write(ciphertext)
The receiver has the private Rsa key. They will use it to decrypt the session key first, and with that the rest of the file:
from Crypto.PublicKey import RSA from Crypto.Cipher import AES, PKCS1_OAEP private_key = RSA.import_key(open("private.pem").read()) with open("encrypted_data.bin", "rb") as f: enc_session_key = f.read(private_key.size_in_bytes()) nonce = f.read(16) tag = f.read(16) ciphertext = f.read() # Decrypt the session key with the private RSA key cipher_rsa = PKCS1_OAEP.new(private_key) session_key = cipher_rsa.decrypt(enc_session_key) # Decrypt the data with the AES session key cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce) data = cipher_aes.decrypt_and_verify(ciphertext, tag) print(data.decode("utf-8"))
Frequently Asked Questions
Is CTR cipher mode compatible with Java?
Yes. When you instantiate your AES cipher in Java:
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); SecretKeySpec keySpec = new SecretKeySpec(new byte[16], "AES"); IvParameterSpec ivSpec = new IvParameterSpec(new byte[16]); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
You are effectively using CTR mode without a fixed nonce and with a 128-bit big endian counter starting at 0. The counter will wrap around only after 2¹²⁸ blocks.
You can replicate the same keystream in PyCryptodome with:
ivSpec = b'\x00' * 16 ctr = AES.new(keySpec, AES.MODE_CTR, initial_value=ivSpec, nonce=b'')
Are RSASSA-PSS signatures compatible with Java?
Yes. For Java, you must consider that by default the mask is generated by MGF1 with SHA-1 (regardless of how you hash the message) and the salt is 20 bytes long.
If you want to use another algorithm or another salt length, you must instantiate a PSSParameterSpec object, for instance:
Signature ss = Signature.getInstance("SHA256withRSA/PSS"); AlgorithmParameters pss1 = ss.getParameters(); PSSParameterSpec pssParameterSpec = new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), 32, 0xBC); ss.setParameter(spec1);
Are RSASSA-PSS signatures compatible with OpenSSL?
Yes, but one quirk of OpenSSL (and of a few other libraries, especially if they are wrappers to OpenSSL) is that the salt length is computed in two possible ways:
Salt length | Value for EVP_PKEY_CTX_set_rsa_pss_saltlen() | openssl pkeyutl command |
Same as digest size | RSA_PSS_SALTLEN_DIGEST | -pkeyopt rsa_pss_saltlen:digest |
Maximized | RSA_PSS_SALTLEN_MAX | -pkeyopt rsa_pss_saltlen:max |
In PyCryptodome, the salt length matches the digest size by default (which is what RFC8017 recommends). However, you can also maximize the salt length with:
key = RSA.import_key(open('privkey.der').read()) h = SHA256.new(message) max_salt_bytes = key.size_in_bytes() - h.digest_size - 2 signature = pss.new(key, salt_bytes=max_salt_bytes).sign(h)
Why do I get the error No module named Crypto on Windows?
Check the directory where Python packages are installed, like:
/path/to/python/Lib/site-packages/
You might find a directory named crypto, with all the PyCryptodome files in it.
The most likely cause is described here and you can fix the problem with:
pip uninstall crypto pip uninstall pycryptodome pip install pycryptodome
The root cause is that, in the past, you most likely have installed an unrelated but similarly named package called crypto, which happens to operate under the namespace crypto.
The Windows filesystem is case-insensitive so crypto and Crypto are effectively considered the same thing. When you subsequently install pycryptodome, pip finds that a directory named with the target namespace already exists (under the rules of the underlying filesystem), and therefore installs all the sub-packages of pycryptodome in it. This is probably a reasonable behavior, if it wasn't that pip does not issue any warning even if it could detect the issue.
Why does strxor raise TypeError: argument 2 must be bytes, not bytearray?
Most probably you have installed both the pycryptodome and the old pycrypto packages.
Run pip uninstall pycrypto and try again.
The old PyCrypto shipped with a strxor module written as a native library (.so or .dll file). If you install pycryptodome, the old native module will still take priority over the new Python extension that comes in the latter.
Why do I get a translation_unit_or_empty undefined error with pycparser?
Unfortunately,``pycparser`` does not work with optimzed (-O) Python builds, which strips out the docstrings, causing this error. This is a known issue and it will not be fixed.
The possible workarounds are:
- Do not run Python iwth -O
- Remove cffi and cparser. PyCryptodome will fall back to ctypes for interfacing with the native modules.
- Use an earlier version of cparser (2.14)
Contribute and Support
- Do not be afraid to contribute with small and apparently insignificant improvements like correction to typos. Every change counts.
- Read carefully the License of PyCryptodome. By submitting your code, you acknowledge that you accept to release it according to the BSD 2-clause license.
- You must disclaim which parts of your code in your contribution were partially copied or derived from an existing source. Ensure that the original is licensed in a way compatible to the BSD 2-clause license.
You can propose changes in any way you find most convenient. However, the preferred approach is to:
- Clone the main repository on GitHub.
- Create a branch and modify the code.
- Send a pull request upstream with a meaningful description.
- Provide tests (in Crypto.SelfTest) along with code. If you fix a bug add a test that fails in the current version and passes with your change.
- If your change breaks backward compatibility, highlight it and include a justification.
- Ensure that your code complies to PEP8 and PEP257.
- If you add or modify a public interface, make sure the relevant type stubs remain up to date.
- Ensure that your code does not use constructs or includes modules not present in Python 2.6.
- Add a short summary of the change to the file Changelog.rst.
- Add your name to the list of contributors in the file AUTHORS.rst.
The PyCryptodome mailing list is hosted on Google Groups. You can mail any comment or question to pycryptodome@googlegroups.com.
Bug reports can be filed on the GitHub tracker.
Future Plans
Future releases will include:
- Update Crypto.Signature.DSS to FIPS 186-4
- Make all hash objects non-copyable and immutable after the first digest
- Add alias 'segment_bits' to parameter 'segment_size' for CFB
- Coverage testing
- Implement AES with bitslicing
- Add unit tests for Pem I/O
- Move old ciphers into a Museum submodule
- Add more Ecc curves
- Import/export of Ecc keys with compressed points
- Add algorithms:
- Elliptic Curves (ECIES, ECDH)
- Camellia, GOST
- Diffie-Hellman
- bcrypt
- argon2
- SRP
- Add more key management:
- Export/import of Dsa domain parameters
- JWK
- Add support for CMS/PKCS#7
- Add support for RNG backed by PKCS#11 and/or KMIP
- Add support for Format-Preserving Encryption
- Remove dependency on libtomcrypto headers
- Speed up (T)DES with a bitsliced implementation
- Run lint on the C code
- Add (minimal) support for PGP
- Add (minimal) support for PKIX / X.509
Changelog
3.21.0 (30 September 2024)
New features
- By setting the PYCRYPTODOME_DISABLE_GMP environment variable, the GMP library will not be used even if detected.
- Add support for Curve25519 / X25519.
- Add support for Curve448 / X448.
- Add attribute curve to EccPoint and EccXPoint classes, with the canonical name of the curve.
- GH#781: the label for the SP800_108_Counter KDF may now contain zero bytes. Thanks to Julien Rische.
- GH#814: Rsa keys for PSS can be imported.
Resolved issues
- GH#810: fixed negation of Ed25519 points.
- GH#819: accept an RFC5916 ECPrivateKey even if it doesn't contain any of the optional elements (parameters [0] and publicKey[1]).
Other changes
- Remove support for Python 3.5.
3.20.0 (9 January 2024)
New features
- Added support for TurboSHAKE128 and TurboSHAKE256.
- Added method Crypto.Hash.new() to generate a hash object given a hash name.
- Added support for AES-GCM encryption of PBES2 and Pkcs#8 containers.
- Added support for SHA-2 and SHA-3 algorithms in PBKDF2 when creating PBES2 and Pkcs#8 containers.
- Export of Rsa keys accepts the prot_params dictionary as parameter to control the number of iterations for PBKDF2 and scrypt.
- C unit tests also run on non-x86 architectures.
Resolved issues
- GH#787: Fixed autodetect logic for GCC 14 in combination with LTO.
3.19.1 (28 December 2023)
Resolved issues
- Fixed a side-channel leakage with OAEP decryption that could be exploited to carry out a Manger attack (CVE-2023-52323). Thanks to Hubert Kario.
3.19.0 (16 September 2023)
New features
- The update() methods of TupleHash128 and TupleHash256 objects can now hash multiple items (byte strings) at once. Thanks to Sylvain Pelissier.
- Added support for ECDH, with Crypto.Protocol.DH.
Resolved issues
- GH#754: due to a bug in cffi, do not use it on Windows with Python 3.12+.
3.18.0 (18 May 2023)
New features
- Added support for DER BOOLEAN encodings.
- The library now compiles on Windows ARM64. Thanks to Niyas Sait.
Resolved issues
- GH#722: nonce attribute was not correctly set for XChaCha20_Poly1305 ciphers. Thanks to Liam Haber.
- GH#728: Workaround for a possible x86 emulator bug in Windows for ARM64.
- GH#739: OID encoding for arc 2 didn't accept children larger than 39. Thanks to James.
- Correctly check that the scalar matches the point when importing an Ecc private key.
3.17.0 (29 January 2023)
New features
- Added support for the Counter Mode KDF defined in SP 800-108 Rev 1.
- Reduce the minimum tag length for the EAX cipher to 2 bytes.
- An Rsa object has 4 new properties for the CRT coefficients: dp, dq, invq and invq (invp is the same value as the existing u).
Resolved issues
- GH#526: improved typing for Rsa.construct.
- GH#534: reduced memory consumption when using a large number of cipher objects.
- GH#598: fixed missing error handling for Util.number.inverse.
- GH#629: improved typing for AES.new and the various mode-specific types it returns. Thanks to Greg Werbin.
- GH#653: added workaround for an alleged GCC compiler bug that affected Ed25519 code compiled for AVX2.
- GH#658: attribute curve of an Ecc key was not always the preferred curve name, as it used to be in v3.15.0 (independently of the curve name specified when generating the key).
- GH#637: fixed typing for legacy modules PKCS1_v1_5 and PKCS1_PSS, as their verify() returned a boolean.
- GH#664: with OCB mode, nonces of maximum length (15 bytes) were actually used as 14 bytes nonces. After this fix, data that was encrypted in past using the (default) nonce length of 15 bytes can still be decrypted by reducing the nonce to its first 14 bytes.
- GH#705: improved typing for nonce, iv, and IV parameters of cipher objects.
Other changes
- Build PyPy wheels only for versions 3.8 and 3.9, and not for 3.7 anymore.
3.16.0 (26 November 2022)
New features
- Build wheels for musl Linux. Thanks to Ben Raz.
Resolved issues
- GH#639: ARC4 now also works with 'keys' as short as 8 bits.
- GH#669: fix segfaults when running in a manylinux2010 i686 image.
3.15.0 (22 June 2022)
New features
- Add support for curves Ed25519 and Ed448, including export and import of keys.
- Add support for EdDSA signatures.
- Add support for Asymmetric Key Packages (RFC5958) to import private keys.
Resolved issues
- GH#620: for Crypto.Util.number.getPrime , do not sequentially scan numbers searching for a prime.
3.14.1 (5 February 2022)
Resolved issues
- GH#595: Fixed memory leak for GMP integers. Thanks to Witalij Siebert and Pablo Quílez.
3.14.0 (30 January 2022)
New features
- Add support for curve NIST P-192.
3.13.0 (23 January 2022)
New features
- Add support for curve NIST P-224.
Resolved issues
- GH#590: Fixed typing info for Crypto.PublicKey.Ecc.
Other changes
- Relaxed ECDSA requirements for FIPS 186 signatures and accept any SHA-2 or SHA-3 hash. sign() and verify() will be performed even if the hash is stronger than the Ecc key.
3.12.0 (4 December 2021)
New features
- Ecc keys in the SEC1 format can be exported and imported.
- Add support for KMAC128, KMAC256, TupleHash128, and TupleHash256 (NIST SP-800 185).
- Add support for KangarooTwelve.
Resolved issues
- GH#563: An asymmetric key could not be imported as a memoryview.
- GH#566: cSHAKE128/256 generated a wrong output for customization strings longer than 255 bytes.
- GH#582: CBC decryption generated the wrong plaintext when the input and the output were the same buffer. Thanks to Michael K. Ashburn.
3.11.0 (8 October 2021)
Resolved issues
- GH#512: Especially for very small bit sizes, Crypto.Util.number.getPrime() was occasionally generating primes larger than given the bit size. Thanks to Koki Takahashi.
- GH#552: Correct typing annotations for PKCS115_Cipher.decrypt().
- GH#555: decrypt() method of a PKCS#1v1.5 cipher returned a bytearray instead of bytes.
- GH#557: External Dsa domain parameters were accepted even when the modulus (p) was not prime. This affected Crypto.PublicKey.Dsa.generate() and Crypto.PublicKey.Dsa.construct(). Thanks to Koki Takahashi.
New features
- Added cSHAKE128 and cSHAKE256 (of SHA-3 family). Thanks to Michael Schaffner.
- GH#558: The flag RTLD_DEEPBIND passed to dlopen() is not well supported by address sanitizers. It is now possible to set the environment variable PYCRYPTDOME_DISABLE_DEEPBIND to drop that flag and allow security testing.
3.10.4 (25 September 2021)
Resolved issues
- Output of Crypto.Util.number.long_to_bytes() was not always a multiple of blocksize.
3.10.3 (22 September 2021)
Resolved issues
- GH#376: Fixed symbol conflict between different versions of libgmp.
- GH#481: Improved robustness of PKCS#1v1.5 decryption against timing attacks.
- GH#506 and GH#509: Fixed segmentation faults on Apple M1 and other Aarch64 SoCs, when the GMP library was accessed via ctypes. Do not use GMP's own sscanf and snprintf routines: instead, use simpler conversion routines.
- GH#510: Workaround for cffi calling ctypes.util.find_library(), which invokes gcc and ld on Linux, considerably slowing down all imports. On certain configurations, that may also leave temporary files behind.
- GH#517: Fix RSAES-OAEP, as it didn't always fail when zero padding was incorrect.
New features
- Added support for SHA-3 hash functions to HMAC.
Other changes
- The Windows wheels of Python 2.7 now require the VS2015 runtime to be installed in the system, because Microsoft stopped distributing the VS2008 compiler in April 2021. VS2008 was used to compile the Python 2.7 extensions.
3.10.1 (9 February 2021)
Other changes
- Python 3 wheels use abi3 ABI tag.
- Remove Appveyor CI.
3.10.0 (6 February 2021)
Resolved issues
- Fixed a potential memory leak when initializing block ciphers.
- GH#466: Crypto.Math.miller_rabin_test() was still using the system random source and not the one provided as parameter.
- GH#469: Rsa objects have the method public_key() like Ecc objects. The old method publickey() is still available for backward compatibility.
- GH#476: Crypto.Util.Padding.unpad() was raising an incorrect exception in case of zero-length inputs. Thanks to Captainowie.
- GH#491: better exception message when Counter.new() is called with an integer initial_value than doesn't fit into nbits bits.
- GH#496: added missing block_size member for ECB cipher objects. Thanks to willem.
- GH#500: nonce member of an XChaCha20 cipher object was not matching the original nonce. Thanks to Charles Machalow.
Other changes
- The bulk of the test vectors have been moved to the separate package pycryptodome-test-vectors. As result, packages pycryptodome and pycryptodomex become significantly smaller (from 14MB to 3MB).
- Moved CI tests and build service from Travis CI to GitHub Actions.
Breaks in compatibility
- Drop support for Python 2.6 and 3.4.
3.9.9 (2 November 2020)
Resolved issues
- GH#435: Fixed Crypto.Util.number.size for negative numbers.
New features
- Build Python 3.9 wheels on Windows.
3.9.8 (23 June 2020)
Resolved issues
- GH#426: The Shamir's secret sharing implementation is not actually compatible with ssss. Added an optional parameter to enable interoperability.
- GH#427: Skip altogether loading of gmp.dll on Windows.
- GH#420: Fix incorrect CFB decryption when the input and the output are the same buffer.
New features
- Speed up Shamir's secret sharing routines. Thanks to ncarve.
3.9.7 (20 February 2020)
Resolved issues
- GH#381: Make notarization possible again on OS X when using wheels. Thanks to Colin Atkinson.
3.9.6 (2 February 2020)
Resolved issues
- Fix building of wheels for OS X by explicitly setting sysroot location.
3.9.5 (1 February 2020)
Resolved issues
- Rsa OAEP decryption was not verifying that all PS bytes are zero.
- GH#372: fixed memory leak for operations that use memoryviews when cffi is not installed.
- Fixed wrong ASN.1 OID for HMAC-SHA512 in PBE2.
New features
- Updated Wycheproof test vectors to version 0.8r12.
3.9.4 (18 November 2019)
Resolved issues
- GH#341: Prevent key_to_english from creating invalid data when fed with keys of length not multiple of 8. Thanks to vstoykovbg.
- GH#347: Fix blocking Rsa signing/decryption when key has very small factor. Thanks to Martijn Pieters.
3.9.3 (12 November 2019)
Resolved issues
- GH#308: Align stack of functions using SSE2 intrinsics to avoid crashes, when compiled with gcc on 32-bit x86 platforms.
3.9.2 (10 November 2019)
New features
- Add Python 3.8 wheels for Mac.
Resolved issues
- GH#308: Avoid allocating arrays of __m128i on the stack, to cope with buggy compilers.
- GH#322: Remove blanket -O3 optimization for gcc and clang, to cope with buggy compilers.
- GH#337: Fix typing stubs for signatures.
- GH#338: Deal with gcc installations that don't have x86intrin.h.
3.9.1 (1 November 2019)
New features
- Add Python 3.8 wheels for Linux and Windows.
Resolved issues
- GH#328: minor speed-up when importing Rsa.
3.9.0 (27 August 2019)
New features
- Add support for loading Pem files encrypted with AES256-CBC.
- Add support for XChaCha20 and XChaCha20-Poly1305 ciphers.
- Add support for bcrypt key derivation function (Crypto.Protocol.KDF.bcrypt).
- Add support for left multiplication of an EC point by a scalar.
- Add support for importing Ecc and Rsa keys in the new OpenSSH format.
Resolved issues
3.8.2 (30 May 2019)
Resolved issues
- GH#291: fix strict aliasing problem, emerged with GCC 9.1.
3.8.1 (4 April 2019)
New features
Resolved issues
- repr() did not work for Ecc.EccKey objects.
- Fix installation in development mode (setup install develop or pip install -e .).
- Minimal length for Blowfish cipher is 32 bits, not 40 bits.
- Various updates to docs.
3.8.0 (23 March 2019)
New features
Resolved issues
- DER objects were not rejected if their length field had a leading zero.
- Allow legacy RC2 ciphers to have 40-bit keys.
- ASN.1 Object IDs did not allow the value 0 in the path.
Breaks in compatibility
- point_at_infinity() becomes an instance method for Crypto.PublicKey.Ecc.EccKey, from a static one.
3.7.3 (19 January 2019)
Resolved issues
- GH#258: False positive on PSS signatures when externally provided salt is too long.
- Include type stub files for Crypto.IO and Crypto.Util.
3.7.2 (26 November 2018)
Resolved issues
- GH#242: Fixed compilation problem on ARM platforms.
3.7.1 (25 November 2018)
New features
- Added type stubs to enable static type checking with mypy. Thanks to Michael Nix.
- New update_after_digest flag for CMAC.
Resolved issues
- GH#232: Fixed problem with gcc 4.x when compiling ghash_clmul.c.
- GH#238: Incorrect digest value produced by CMAC after cloning the object.
- Method update() of an EAX cipher object was returning the underlying CMAC object, instead of the EAX object itself.
- Method update() of a CMAC object was not throwing an exception after the digest was computed (with digest() or verify()).
3.7.0 (27 October 2018)
New features
- Added support for Poly1305 MAC (with AES and ChaCha20 ciphers for key derivation).
- Added support for ChaCha20-Poly1305 AEAD cipher.
- New parameter output for Crypto.Util.strxor.strxor, Crypto.Util.strxor.strxor_c, encrypt and decrypt methods in symmetric ciphers (Crypto.Cipher package). output is a pre-allocated buffer (a bytearray or a writeable memoryview) where the result must be stored. This requires less memory for very large payloads; it is also more efficient when encrypting (or decrypting) several small payloads.
Resolved issues
- GH#266: AES-GCM hangs when processing more than 4GB at a time on x86 with PCLMULQDQ instruction.
Breaks in compatibility
- Drop support for Python 3.3.
- Remove Crypto.Util.py3compat.unhexlify and Crypto.Util.py3compat.hexlify.
- With the old Python 2.6, use only ctypes (and not cffi) to interface to native code.
3.6.6 (17 August 2018)
Resolved issues
- GH#198: Fix vulnerability on AESNI ECB with payloads smaller than 16 bytes (CVE-2018-15560).
3.6.5 (12 August 2018)
Resolved issues
- GH#187: Fixed incorrect AES encryption/decryption with AES acceleration on x86 due to gcc's optimization and strict aliasing rules.
- GH#188: More prime number candidates than necessary where discarded as composite due to the limited way D values were searched in the Lucas test.
- Fixed ResouceWarnings and DeprecationWarnings.
- Workaround for Python 3.7.0 bug on Windows (https://bugs.python.org/issue34108).
3.6.4 (10 July 2018)
New features
- Build Python 3.7 wheels on Linux, Windows and Mac.
Resolved issues
- GH#178: Rename _cpuid module to make upgrades more robust.
- More meaningful exceptions in case of mismatch in IV length (CBC/OFB/CFB modes).
- Fix compilation issues on Solaris 10/11.
3.6.3 (21 June 2018)
Resolved issues
- GH#175: Fixed incorrect results for CTR encryption/decryption with more than 8 blocks.
3.6.2 (19 June 2018)
New features
- ChaCha20 accepts 96 bit nonces (in addition to 64 bit nonces) as defined in RFC7539.
- Accelerate AES-GCM on x86 using PCLMULQDQ instruction.
- Accelerate AES-ECB and AES-CTR on x86 by pipelining AESNI instructions.
As result of the two improvements above, on x86 (Broadwell):
- AES-ECB and AES-CTR are 3x faster
- AES-GCM is 9x faster
Resolved issues
- On Windows, MPIR library was stilled pulled in if renamed to gmp.dll.
Breaks in compatibility
- In Crypto.Util.number, functions floor_div and exact_div have been removed. Also, ceil_div is limited to non-negative terms only.
3.6.1 (15 April 2018)
New features
- Added Google Wycheproof tests (https://github.com/google/wycheproof) for Rsa, Dsa, ECDSA, GCM, SIV, EAX, CMAC.
- New parameter mac_len (length of MAC tag) for CMAC.
Resolved issues
- In certain circumstances (at counter wrapping, which happens on average after 32 GB) AES GCM produced wrong ciphertexts.
- Method encrypt() of AES SIV cipher could be still called, whereas only encrypt_and_digest() is allowed.
3.6.0 (8 April 2018)
New features
Resolved issues
- Reintroduced Crypto.__version__ variable as in PyCrypto.
- Fixed compilation problem with MinGW.
3.5.1 (8 March 2018)
Resolved issues
- GH#142. Fix mismatch with declaration and definition of addmul128.
3.5.0 (7 March 2018)
New features
- Import and export of Ecc curves in compressed form.
- The initial counter for a cipher in CTR mode can be a byte string (in addition to an integer).
- Faster PBKDF2 for HMAC-based PRFs (at least 20x for short passwords, more for longer passwords). Thanks to Christian Heimes for pointing out the implementation was under-optimized.
- The salt for PBKDF2 can be either a string or bytes (GH#67).
- Ciphers and hash functions accept data as bytearray, not just binary strings.
- The old SHA-1 and MD5 hash functions are available even when Python's own hashlib does not include them.
Resolved issues
- Without libgmp, modular exponentiation (since v3.4.8) crashed on 32-bit big-endian systems.
Breaks in compatibility
- Removed support for Python < 2.6.
3.4.12 (5 February 2018)
Resolved issues
- GH#129. pycryptodomex could only be installed via wheels.
3.4.11 (5 February 2018)
Resolved issues
- GH#121. the record list was still not correct due to PEP3147 and __pycache__ directories. Thanks again to John O'Brien.
3.4.10 (2 February 2018)
Resolved issues
- When creating ElGamal keys, the generator wasn't a square residue: ElGamal encryption done with those keys cannot be secure under the DDH assumption. Thanks to Weikeng Chen.
3.4.9 (1 February 2018)
New features
- More meaningful error messages while importing an Ecc key.
Resolved issues
- GH#123 and #125. The SSE2 command line switch was not always passed on 32-bit x86 platforms.
- GH#121. The record list (--record) was not always correctly filled for the pycryptodomex package. Thanks to John W. O'Brien.
3.4.8 (27 January 2018)
New features
- Added a native extension in pure C for modular exponentiation, optimized for SSE2 on x86. In the process, we drop support for the arbitrary arithmetic library MPIR on Windows, which is painful to compile and deploy. The custom modular exponentiation is 130% (160%) slower on an Intel CPU in 32-bit (64-bit) mode, compared to MPIR. Still, that is much faster that CPython's own pow() function which is 900% (855%) slower than MPIR. Support for the GMP library on Unix remains.
- Added support for manylinux wheels.
- Support for Python 3.7.
Resolved issues
- The Dsa parameter 'p' prime was created with 255 bits cleared (but still with the correct strength).
- GH#106. Not all docs were included in the tar ball. Thanks to Christopher Hoskin.
- GH#109. ECDSA verification failed for DER encoded signatures. Thanks to Alastair Houghton.
- Human-friendly messages for padding errors with ECB and CBC.
3.4.7 (26 August 2017)
New features
- API documentation is made with sphinx instead of epydoc.
- Start using importlib instead of imp where available.
Resolved issues
3.4.6 (18 May 2017)
Resolved issues
- GH#65. Keccak, SHA3, SHAKE and the seek functionality for ChaCha20 were not working on big endian machines. Fixed. Thanks to Mike Gilbert.
- A few fixes in the documentation.
3.4.5 (6 February 2017)
Resolved issues
- The library can also be compiled using MinGW.
3.4.4 (1 February 2017)
Resolved issues
- Removed use of alloca().
- [Security] Removed implementation of deprecated "quick check" feature of PGP block cipher mode.
- Improved the performance of scrypt by converting some Python to C.
3.4.3 (17 October 2016)
Resolved issues
- Undefined warning was raised with libgmp version < 5
- Forgot inclusion of alloca.h
- Fixed a warning about type mismatch raised by recent versions of cffi
3.4.2 (8 March 2016)
Resolved issues
- Fix renaming of package for install command.
3.4.1 (21 February 2016)
New features
- Added option to install the library under the Cryptodome package (instead of Crypto).
3.4 (7 February 2016)
New features
- Added Crypto.PublicKey.Ecc module (NIST P-256 curve only), including export/import of Ecc keys.
- Added support for ECDSA (FIPS 186-3 and RFC6979).
- For CBC/CFB/OFB/CTR cipher objects, encrypt() and decrypt() cannot be intermixed.
- CBC/CFB/OFB, the cipher objects have both IV and iv attributes. new() accepts IV as well as iv as parameter.
- For CFB/OPENPGP cipher object, encrypt() and decrypt() do not require the plaintext or ciphertext pieces to have length multiple of the CFB segment size.
- Added dedicated tests for all cipher modes, including NIST test vectors
- CTR/CCM/EAX/GCM/SIV/Salsa20/ChaCha20 objects expose the nonce attribute.
- For performance reasons, CCM cipher optionally accepted a pre-declaration of the length of the associated data, but never checked if the actual data passed to the cipher really matched that length. Such check is now enforced.
- CTR cipher objects accept parameter nonce and possibly initial_value in alternative to counter (which is deprecated).
- All iv/IV and nonce parameters are optional. If not provided, they will be randomly generated (exception: nonce for CTR mode in case of block sizes smaller than 16 bytes).
- Refactored ARC2 cipher.
- Added Crypto.Cipher.DES3.adjust_key_parity() function.
- Added Rsa.import_key as an alias to the deprecated Rsa.importKey (same for the Dsa module).
- Added size_in_bits() and size_in_bytes() methods to RsaKey.
Resolved issues
- Rsa key size is now returned correctly in RsaKey.__repr__() method (kudos to hannesv).
- CTR mode does not modify anymore counter parameter passed to new() method.
- CTR raises OverflowError instead of ValueError when the counter wraps around.
- Pem files with Windows newlines could not be imported.
- Crypto.IO.Pem and Crypto.IO.PKCS8 used to accept empty passphrases.
- GH#6: NotImplementedError now raised for unsupported methods sign, verify, encrypt, decrypt, blind, unblind and size in objects RsaKey, DsaKey, ElGamalKey.
Breaks in compatibility
- Parameter segment_size cannot be 0 for the CFB mode.
- For OCB ciphers, a final call without parameters to encrypt must end a sequence of calls to encrypt with data (similarly for decrypt).
- Key size for ARC2, ARC4 and Blowfish must be at least 40 bits long (still very weak).
- DES3 (Triple DES module) does not allow keys that degenerate to Single DES.
- Removed method getRandomNumber in Crypto.Util.number.
- Removed module Crypto.pct_warnings.
- Removed attribute Crypto.PublicKey.Rsa.algorithmIdentifier.
3.3.1 (1 November 2015)
New features
- Opt-in for update() after digest() for SHA-3, keccak, BLAKE2 hashes
Resolved issues
- Removed unused SHA-3 and keccak test vectors, therefore significantly reducing the package from 13MB to 3MB.
Breaks in compatibility
- Removed method copy() from BLAKE2 hashes
- Removed ability to update() a BLAKE2 hash after the first call to (hex)digest()
3.3 (29 October 2015)
New features
- Windows wheels bundle the MPIR library
- Detection of faults occurring during secret Rsa operations
- Detection of non-prime (weak) q value in Dsa domain parameters
- Added original Keccak hash family (b=1600 only). In the process, simplified the C code base for SHA-3.
- Added SHAKE128 and SHAKE256 (of SHA-3 family)
Resolved issues
- GH#3: gcc 4.4.7 unhappy about double typedef
Breaks in compatibility
- Removed method copy() from all SHA-3 hashes
- Removed ability to update() a SHA-3 hash after the first call to (hex)digest()
3.2.1 (9 September 2015)
New features
- Windows wheels are automatically built on Appveyor
3.2 (6 September 2015)
New features
- Added hash functions BLAKE2b and BLAKE2s.
- Added stream cipher ChaCha20.
- Added OCB cipher mode.
- CMAC raises an exception whenever the message length is found to be too large and the chance of collisions not negligeable.
- New attribute oid for Hash objects with ASN.1 Object ID
- Added Crypto.Signature.pss and Crypto.Signature.pkcs1_15
- Added NIST test vectors (roughly 1200) for PKCS#1 v1.5 and PSS signatures.
Resolved issues
- tomcrypt_macros.h asm error #1
Breaks in compatibility
3.1 (15 March 2015)
New features
- Speed up execution of Public Key algorithms on PyPy, when backed by the Gnu Multiprecision (GMP) library.
- GMP headers and static libraries are not required anymore at the time PyCryptodome is built. Instead, the code will automatically use the GMP dynamic library (.so/.DLL) if found in the system at runtime.
- Reduced the amount of C code by almost 40% (4700 lines). Modularized and simplified all code (C and Python) related to block ciphers. Pycryptodome is now free of CPython extensions.
- Add support for CI in Windows via Appveyor.
- Rsa and Dsa key generation more closely follows FIPS 186-4 (though it is not 100% compliant).
Resolved issues
- None
Breaks in compatibility
- New dependency on ctypes with Python 2.4.
- The counter parameter of a CTR mode cipher must be generated via Crypto.Util.Counter. It cannot be a generic callable anymore.
- Removed the Crypto.Random.Fortuna package (due to lack of test vectors).
- Removed the Crypto.Hash.new function.
- The allow_wraparound parameter of Crypto.Util.Counter is ignored. An exception is always generated if the counter is reused.
- Dsa.generate, Rsa.generate and ElGamal.generate do not accept the progress_func parameter anymore.
- Removed Crypto.PublicKey.Rsa.RSAImplementation.
- Removed Crypto.PublicKey.Dsa.DSAImplementation.
- Removed ambiguous method size() from Rsa, Dsa and ElGamal keys.
3.0 (24 June 2014)
New features
- Initial support for PyPy.
- SHA-3 hash family based on the April 2014 draft of FIPS 202. See modules Crypto.Hash.SHA3_224/256/384/512. Initial Keccak patch by Fabrizio Tarizzo.
- Salsa20 stream cipher. See module Crypto.Cipher.Salsa20. Patch by Fabrizio Tarizzo.
- Colin Percival's scrypt key derivation function (Crypto.Protocol.KDF.scrypt).
- Proper interface to FIPS 186-3 Dsa. See module Crypto.Signature.DSS.
- Deterministic Dsa (RFC6979). Again, see Crypto.Signature.DSS.
- HMAC-based Extract-and-Expand key derivation function (Crypto.Protocol.KDF.HKDF, RFC5869).
- Shamir's Secret Sharing protocol, compatible with ssss (128 bits only). See module Crypto.Protocol.SecretSharing.
- Ability to generate a Dsa key given the domain parameters.
- Ability to test installation with a simple python -m Crypto.SelfTest.
Resolved issues
- LP#1193521: mpz_powm_sec() (and Python) crashed when modulus was odd.
- Benchmarks work again (they broke when ECB stopped working if an IV was passed. Patch by Richard Mitchell.
- LP#1178485: removed some catch-all exception handlers. Patch by Richard Mitchell.
- LP#1209399: Removal of Python wrappers caused HMAC to silently produce the wrong data with SHA-2 algorithms.
- LP#1279231: remove dead code that does nothing in SHA-2 hashes. Patch by Richard Mitchell.
- LP#1327081: AESNI code accesses memory beyond buffer end.
- Stricter checks on ciphertext and plaintext size for textbook Rsa (kudos to sharego).
Breaks in compatibility
- Removed support for Python < 2.4.
Removed the following methods from all 3 public key object types (Rsa, Dsa, ElGamal):
- sign
- verify
- encrypt
- decrypt
- blind
- unblind
Code that uses such methods is doomed anyway. It should be fixed ASAP to use the algorithms available in Crypto.Signature and Crypto.Cipher.
- The 3 public key object types (Rsa, Dsa, ElGamal) are now unpickable.
- Symmetric ciphers do not have a default mode anymore (used to be ECB). An expression like AES.new(key) will now fail. If ECB is the desired mode, one has to explicitly use AES.new(key, AES.MODE_ECB).
- Unsuccessful verification of a signature will now raise an exception [reverted in 3.2].
- Removed the Crypto.Random.OSRNG package.
- Removed the Crypto.Util.winrandom module.
- Removed the Crypto.Random.randpool module.
- Removed the Crypto.Cipher.XOR module.
- Removed the Crypto.Protocol.AllOrNothing module.
- Removed the Crypto.Protocol.Chaffing module.
- Removed the parameters disabled_shortcut and overflow from Crypto.Util.Counter.new.
Other changes
- Crypto.Random stops being a userspace CSPRNG. It is now a pure wrapper over os.urandom.
- Added certain resistance against side-channel attacks for GHASH (GCM) and Dsa.
- More test vectors for HMAC-RIPEMD-160.
- Update libtomcrypt headers and code to v1.17 (kudos to Richard Mitchell).
- Rsa and Dsa keys are checked for consistency as they are imported.
- Simplified build process by removing autoconf.
- Speed optimization to PBKDF2.
- Add support for MSVC.
- Replaced HMAC code with a BSD implementation. Clarified that starting from the fork, all contributions are released under the BSD license.
License
The source code in PyCryptodome is partially in the public domain and partially released under the BSD 2-Clause license.
In either case, there are minimal if no restrictions on the redistribution, modification and usage of the software.
Public domain
All code originating from PyCrypto is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>
BSD license
All direct contributions to PyCryptodome are released under the following license. The copyright of each piece belongs to the respective author.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE Copyright HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE Copyright HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Author
Legrandin
Copyright
2024, Helder Eijs