Danger
This is a “Hazardous Materials” module. You should ONLY use it if you’re 100% absolutely sure that you know what you’re doing because this module is full of land mines, dragons, and dinosaurs with laser guns.
RSA
RSA is a public-key algorithm for encrypting and signing messages.
Generation
Unlike symmetric cryptography, where the key is typically just a random series of bytes, RSA keys have a complex internal structure with specific mathematical properties.
- cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key(public_exponent, key_size)[source]
New in version 0.5.
Changed in version 3.0: Tightened restrictions on
public_exponent
.Generates a new RSA private key.
key_size
describes how many bits long the key should be. Larger keys provide more security; currently1024
and below are considered breakable while2048
or4096
are reasonable default key sizes for new keys. Thepublic_exponent
indicates what one mathematical property of the key generation will be. Unless you have a specific reason to do otherwise, you should always use 65537.>>> from cryptography.hazmat.primitives.asymmetric import rsa >>> private_key = rsa.generate_private_key( ... public_exponent=65537, ... key_size=2048, ... )
- Parameters:
public_exponent (int) – The public exponent of the new key. Either 65537 or 3 (for legacy purposes). Almost everyone should use 65537.
key_size (int) – The length of the modulus in bits. For keys generated in 2015 it is strongly recommended to be at least 2048 (See page 41). It must not be less than 512.
- Returns:
An instance of
RSAPrivateKey
.
Key loading
If you already have an on-disk key in the PEM format (which are recognizable by
the distinctive -----BEGIN {format}-----
and -----END {format}-----
markers), you can load it:
>>> from cryptography.hazmat.primitives import serialization
>>> with open("path/to/key.pem", "rb") as key_file:
... private_key = serialization.load_pem_private_key(
... key_file.read(),
... password=None,
... )
Serialized keys may optionally be encrypted on disk using a password. In this
example we loaded an unencrypted key, and therefore we did not provide a
password. If the key is encrypted we can pass a bytes
object as the
password
argument.
There is also support for loading public keys in the SSH format
.
Key serialization
If you have a private key that you’ve loaded you can use
private_bytes()
to serialize the key.
>>> from cryptography.hazmat.primitives import serialization
>>> pem = private_key.private_bytes(
... encoding=serialization.Encoding.PEM,
... format=serialization.PrivateFormat.PKCS8,
... encryption_algorithm=serialization.BestAvailableEncryption(b'mypassword')
... )
>>> pem.splitlines()[0]
b'-----BEGIN ENCRYPTED PRIVATE KEY-----'
It is also possible to serialize without encryption using
NoEncryption
.
>>> pem = private_key.private_bytes(
... encoding=serialization.Encoding.PEM,
... format=serialization.PrivateFormat.TraditionalOpenSSL,
... encryption_algorithm=serialization.NoEncryption()
... )
>>> pem.splitlines()[0]
b'-----BEGIN RSA PRIVATE KEY-----'
For public keys you can use
public_bytes()
to serialize the key.
>>> from cryptography.hazmat.primitives import serialization
>>> public_key = private_key.public_key()
>>> pem = public_key.public_bytes(
... encoding=serialization.Encoding.PEM,
... format=serialization.PublicFormat.SubjectPublicKeyInfo
... )
>>> pem.splitlines()[0]
b'-----BEGIN PUBLIC KEY-----'
Signing
A private key can be used to sign a message. This allows anyone with the public
key to verify that the message was created by someone who possesses the
corresponding private key. RSA signatures require a specific hash function, and
padding to be used. Here is an example of signing message
using RSA, with a
secure hash function and padding:
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.asymmetric import padding
>>> message = b"A message I want to sign"
>>> signature = private_key.sign(
... message,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... hashes.SHA256()
... )
Valid paddings for signatures are
PSS
and
PKCS1v15
. PSS
is the recommended choice for any new protocols or applications, PKCS1v15
should only be used to support legacy protocols.
If your data is too large to be passed in a single call, you can hash it
separately and pass that value using
Prehashed
.
>>> from cryptography.hazmat.primitives.asymmetric import utils
>>> chosen_hash = hashes.SHA256()
>>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
>>> sig = private_key.sign(
... digest,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... utils.Prehashed(chosen_hash)
... )
Verification
The previous section describes what to do if you have a private key and want to
sign something. If you have a public key, a message, a signature, and the
signing algorithm that was used you can check that the private key associated
with a given public key was used to sign that specific message. You can obtain
a public key to use in verification using
load_pem_public_key()
,
load_der_public_key()
,
public_key()
, or
public_key()
.
>>> public_key = private_key.public_key()
>>> public_key.verify(
... signature,
... message,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... hashes.SHA256()
... )
If the signature does not match, verify()
will raise an
InvalidSignature
exception.
If your data is too large to be passed in a single call, you can hash it
separately and pass that value using
Prehashed
.
>>> chosen_hash = hashes.SHA256()
>>> hasher = hashes.Hash(chosen_hash)
>>> hasher.update(b"data & ")
>>> hasher.update(b"more data")
>>> digest = hasher.finalize()
>>> public_key.verify(
... sig,
... digest,
... padding.PSS(
... mgf=padding.MGF1(hashes.SHA256()),
... salt_length=padding.PSS.MAX_LENGTH
... ),
... utils.Prehashed(chosen_hash)
... )
Encryption
RSA encryption is interesting because encryption is performed using the public key, meaning anyone can encrypt data. The data is then decrypted using the private key.
Like signatures, RSA supports encryption with several different padding options. Here’s an example using a secure padding and hash function:
>>> message = b"encrypted data"
>>> ciphertext = public_key.encrypt(
... message,
... padding.OAEP(
... mgf=padding.MGF1(algorithm=hashes.SHA256()),
... algorithm=hashes.SHA256(),
... label=None
... )
... )
Valid paddings for encryption are
OAEP
and
PKCS1v15
. OAEP
is the recommended choice for any new protocols or applications, PKCS1v15
should only be used to support legacy protocols.
Decryption
Once you have an encrypted message, it can be decrypted using the private key:
>>> plaintext = private_key.decrypt(
... ciphertext,
... padding.OAEP(
... mgf=padding.MGF1(algorithm=hashes.SHA256()),
... algorithm=hashes.SHA256(),
... label=None
... )
... )
>>> plaintext == message
True
Padding
- class cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding[source]
New in version 0.2.
- name
- class cryptography.hazmat.primitives.asymmetric.padding.PSS(mgf, salt_length)[source]
New in version 0.3.
Changed in version 0.4: Added
salt_length
parameter.PSS (Probabilistic Signature Scheme) is a signature scheme defined in RFC 3447. It is more complex than PKCS1 but possesses a security proof. This is the recommended padding algorithm for RSA signatures. It cannot be used with RSA encryption.
- Parameters:
- MAX_LENGTH
Pass this attribute to
salt_length
to get the maximum salt length available.
- DIGEST_LENGTH
New in version 37.0.0.
Pass this attribute to
salt_length
to set the salt length to the byte length of the digest passed when callingsign
. Note that this is not the length of the digest passed toMGF1
.
- AUTO
New in version 37.0.0.
Pass this attribute to
salt_length
to automatically determine the salt length when verifying. RaisesValueError
if used when signing.
- class cryptography.hazmat.primitives.asymmetric.padding.OAEP(mgf, algorithm, label)[source]
New in version 0.4.
OAEP (Optimal Asymmetric Encryption Padding) is a padding scheme defined in RFC 3447. It provides probabilistic encryption and is proven secure against several attack types. This is the recommended padding algorithm for RSA encryption. It cannot be used with RSA signing.
- Parameters:
mgf – A mask generation function object. At this time the only supported MGF is
MGF1
.algorithm – An instance of
HashAlgorithm
.label (bytes) – A label to apply. This is a rarely used field and should typically be set to
None
orb""
, which are equivalent.
- algorithm
- Type:
New in version 42.0.0.
The padding’s hash algorithm.
- class cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15[source]
New in version 0.3.
PKCS1 v1.5 (also known as simply PKCS1) is a simple padding scheme developed for use with RSA keys. It is defined in RFC 3447. This padding can be used for signing and encryption.
It is not recommended that
PKCS1v15
be used for new applications,OAEP
should be preferred for encryption andPSS
should be preferred for signatures.Warning
Our implementation of PKCS1 v1.5 decryption is not constant time. See Known security limitations for details.
- cryptography.hazmat.primitives.asymmetric.padding.calculate_max_pss_salt_length(key, hash_algorithm)[source]
New in version 1.5.
- Parameters:
key – An RSA public or private key.
hash_algorithm – A
cryptography.hazmat.primitives.hashes.HashAlgorithm
.
- Returns int:
The computed salt length.
Computes the length of the salt that
PSS
will use ifPSS.MAX_LENGTH
is used.
Mask generation functions
- class cryptography.hazmat.primitives.asymmetric.padding.MGF1(algorithm)[source]
New in version 0.3.
Changed in version 0.6: Removed the deprecated
salt_length
parameter.MGF1 (Mask Generation Function 1) is used as the mask generation function in
PSS
andOAEP
padding. It takes a hash algorithm.- Parameters:
algorithm – An instance of
HashAlgorithm
.
Numbers
These classes hold the constituent components of an RSA key. They are useful only when more traditional Key Serialization is unavailable.
- class cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers(e, n)[source]
New in version 0.5.
The collection of integers that make up an RSA public key.
- public_key()
- Returns:
A new instance of
RSAPublicKey
.
- class cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers(p, q, d, dmp1, dmq1, iqmp, public_numbers)[source]
New in version 0.5.
The collection of integers that make up an RSA private key.
Warning
With the exception of the integers contained in the
RSAPublicNumbers
all attributes of this class must be kept secret. Revealing them will compromise the security of any cryptographic operations performed with a key loaded from them.- public_numbers
- Type:
The
RSAPublicNumbers
which makes up the RSA public key associated with this RSA private key.
- dmp1
- Type:
A Chinese remainder theorem coefficient used to speed up RSA operations. Calculated as: d mod (p-1)
- dmq1
- Type:
A Chinese remainder theorem coefficient used to speed up RSA operations. Calculated as: d mod (q-1)
- iqmp
- Type:
A Chinese remainder theorem coefficient used to speed up RSA operations. Calculated as: q^{-1} mod p
- private_key(*, unsafe_skip_rsa_key_validation=False)
- Parameters:
unsafe_skip_rsa_key_validation (bool) –
New in version 39.0.0.
A keyword-only argument that defaults to
False
. IfTrue
RSA private keys will not be validated. This significantly speeds up loading the keys, but is unsafe unless you are certain the key is valid. User supplied keys should never be loaded with this parameter set toTrue
. If you do load an invalid key this way and attempt to use it OpenSSL may hang, crash, or otherwise misbehave.- Returns:
An instance of
RSAPrivateKey
.
Handling partial RSA private keys
If you are trying to load RSA private keys yourself you may find that not all
parameters required by RSAPrivateNumbers
are available. In particular the
Chinese Remainder Theorem (CRT) values dmp1
, dmq1
, iqmp
may be
missing or present in a different form. For example, OpenPGP does not include
the iqmp
, dmp1
or dmq1
parameters.
The following functions are provided for users who want to work with keys like this without having to do the math themselves.
- cryptography.hazmat.primitives.asymmetric.rsa.rsa_crt_iqmp(p, q)[source]
New in version 0.4.
Computes the
iqmp
(also known asqInv
) parameter from the RSA primesp
andq
.
- cryptography.hazmat.primitives.asymmetric.rsa.rsa_crt_dmp1(private_exponent, p)[source]
New in version 0.4.
Computes the
dmp1
parameter from the RSA private exponent (d
) and primep
.
- cryptography.hazmat.primitives.asymmetric.rsa.rsa_crt_dmq1(private_exponent, q)[source]
New in version 0.4.
Computes the
dmq1
parameter from the RSA private exponent (d
) and primeq
.
- cryptography.hazmat.primitives.asymmetric.rsa.rsa_recover_prime_factors(n, e, d)[source]
New in version 0.8.
Computes the prime factors
(p, q)
given the modulus, public exponent, and private exponent.Note
When recovering prime factors this algorithm will always return
p
andq
such thatp > q
. Note: before 1.5, this function always returnedp
andq
such thatp < q
. It was changed because libraries commonly requirep > q
.- Returns:
A tuple
(p, q)
Key interfaces
- class cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey[source]
New in version 0.2.
An RSA private key.
- decrypt(ciphertext, padding)[source]
New in version 0.4.
Warning
Our implementation of PKCS1 v1.5 decryption is not constant time. See Known security limitations for details.
Decrypt data that was encrypted with the public key.
- Parameters:
ciphertext (bytes) – The ciphertext to decrypt.
padding – An instance of
AsymmetricPadding
.
- Return bytes:
Decrypted data.
- public_key()[source]
- Returns:
An RSA public key object corresponding to the values of the private key.
- sign(data, padding, algorithm)[source]
New in version 1.4.
Changed in version 1.6:
Prehashed
can now be used as analgorithm
.Sign one block of data which can be verified later by others using the public key.
- Parameters:
data (bytes-like) – The message string to sign.
padding – An instance of
AsymmetricPadding
.algorithm – An instance of
HashAlgorithm
orPrehashed
if thedata
you want to sign has already been hashed.
- Return bytes:
Signature.
- private_numbers()[source]
Create a
RSAPrivateNumbers
object.- Returns:
An
RSAPrivateNumbers
instance.
- private_bytes(encoding, format, encryption_algorithm)[source]
Allows serialization of the key to bytes. Encoding (
PEM
orDER
), format (TraditionalOpenSSL
,OpenSSH
orPKCS8
) and encryption algorithm (such asBestAvailableEncryption
orNoEncryption
) are chosen to define the exact serialization.- Parameters:
encoding – A value from the
Encoding
enum.format – A value from the
PrivateFormat
enum.encryption_algorithm – An instance of an object conforming to the
KeySerializationEncryption
interface.
- Return bytes:
Serialized key.
- class cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey[source]
New in version 0.2.
An RSA public key.
- encrypt(plaintext, padding)[source]
New in version 0.4.
Encrypt data with the public key.
- Parameters:
plaintext (bytes) – The plaintext to encrypt.
padding – An instance of
AsymmetricPadding
.
- Return bytes:
Encrypted data.
- Raises:
ValueError – The data could not be encrypted. One possible cause is if
data
is too large; RSA keys can only encrypt data that is smaller than the key size.
- public_numbers()[source]
Create a
RSAPublicNumbers
object.- Returns:
An
RSAPublicNumbers
instance.
- public_bytes(encoding, format)[source]
Allows serialization of the key to bytes. Encoding (
PEM
orDER
) and format (SubjectPublicKeyInfo
orPKCS1
) are chosen to define the exact serialization.- Parameters:
encoding – A value from the
Encoding
enum.format – A value from the
PublicFormat
enum.
- Return bytes:
Serialized key.
- verify(signature, data, padding, algorithm)[source]
New in version 1.4.
Changed in version 1.6:
Prehashed
can now be used as analgorithm
.Verify one block of data was signed by the private key associated with this public key.
- Parameters:
signature (bytes-like) – The signature to verify.
data (bytes-like) – The message string that was signed.
padding – An instance of
AsymmetricPadding
.algorithm – An instance of
HashAlgorithm
orPrehashed
if thedata
you want to verify has already been hashed.
- Returns:
None
- Raises:
cryptography.exceptions.InvalidSignature – If the signature does not validate.
- recover_data_from_signature(signature, padding, algorithm)[source]
New in version 3.3.
Recovers the signed data from the signature. The data typically contains the digest of the original message string. The
padding
andalgorithm
parameters must match the ones used when the signature was created for the recovery to succeed.The
algorithm
parameter can also be set toNone
to recover all the data present in the signature, without regard to its format or the hash algorithm used for its creation.For
PKCS1v15
padding, this method returns the data after removing the padding layer. For standard signatures the data contains the fullDigestInfo
structure. For non-standard signatures, any data can be returned, including zero-length data.Normally you should use the
verify()
function to validate the signature. But for some non-standard signature formats you may need to explicitly recover and validate the signed data. The following are some examples:Some old Thawte and Verisign timestamp certificates without
DigestInfo
.Signed MD5/SHA1 hashes in TLS 1.1 or earlier (RFC 4346, section 4.7).
IKE version 1 signatures without
DigestInfo
(RFC 2409, section 5.1).
- Parameters:
signature (bytes) – The signature.
padding – An instance of
AsymmetricPadding
. Recovery is only supported with some of the padding types. (Currently only withPKCS1v15
).algorithm – An instance of
HashAlgorithm
. Can beNone
to return the all the data present in the signature.
- Return bytes:
The signed data.
- Raises:
cryptography.exceptions.InvalidSignature – If the signature is invalid.
cryptography.exceptions.UnsupportedAlgorithm – If signature data recovery is not supported with the provided
padding
type.