KeyManager

class privex.helpers.crypto.KeyManager.KeyManager(key: Union[str, bytes, cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey], password: Union[str, bytes] = None)[source]

Asymmetric key handling class - Generate, save, and load asymmetric keys, with signatures + encryption made easy.

A wrapper around cryptography.hazmat.primitives.asymmetric to make generation, saving, loading, AND usage of asymmetric keys easy.

Basic Usage

Using output_keypair() - you can generate a key pair, and output it at the same time:

>>> priv, pub = KeyManager.output_keypair('id_rsa', 'id_rsa.pub')
>>> pub
b'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbzCL+Dn8B9jS404mETt8fb6+TJek1afFthSBi2qZ0iL8dbv/Go0ig...'

If you don’t want to output the key pair to a file, you can also just generate one and have the private/public keys purely returned as bytes:

>>> priv, pub = KeyManager.generate_keypair(alg='ed25519')
>>> priv
b'-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwB.....T2YxW/Xkz3PkMHrrYBvI0LbUPky
-----END PRIVATE KEY-----'
>>> pub
b'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICJ9OK6v2UGfCgWxzGdPlCQIps+lffLTWwuMLPdqfco6'

Loading a key for signature/encryption operations

You can load a private or public key directly from the string/bytes returned by generate_keypair() like so:

>>> km = KeyManager(priv)

Alternatively, you can load a key straight from disk using load_keyfile() - which will automatically detect the asymmetric algorithm, encoding/output format, and key type (public/private) and return a KeyManager instance:

>>> km = KeyManager.load_keyfile('id_rsa.pub')

Automatic public key generation

If you load a private key, then the constructor will automatically generate the matching public key for you, so that you can use all signature/encryption methods available for your key algorithm.

If you load a public key, then you will only be able to use methods which are available to public keys, such as verify() and encrypt() - you will NOT be able to use sign() or decrypt()

Manually accessing the public/private key class instances

If you need to access the raw cryptography PublicKey/PrivateKey instances, you can access them via the two attributes public_key and private_key after creating a KeyManager instance:

>>> km.public_key
<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0x7f953848c438>
>>> km.private_key
<cryptography.hazmat.backends.openssl.rsa._RSAPrivateKey object at 0x7f95381c1ef0>

Signing, verification, and en/decryption

Once you have a KeyManager instance, you can now use the signing, verification, and en/decryption methods using the loaded key.

Most key algorithms support signing and verification, which can be done using sign() and verify() respectively.

Sensible values for things like padding/hash algorithms are set by default, so you can simply call sign() with just a message, and verify() with just the signature + message:

>>> sig = km.sign('hello world')
>>> km.verify(signature=sig, message='hello world')  # Raises InvalidSignature if it was invalid
True

With RSA keys, you can also encrypt() using the public key, and decrypt() using the private key:

>>> msg = km.encrypt('my secret message')
>>> km.decrypt(msg)
b'my secret message'
__init__(key: Union[str, bytes, cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey], password: Union[str, bytes] = None)[source]

Create an instance of KeyManager using the public/private key data key

If you want to load the key from a file instead of passing it’s data / key class instance, then you should use load_keyfile() instead to create the class instance.

You do NOT need to initialize this class if you’re simply using the class methods / static methods such as generate_keypair() or load_key() - only to use the normal instance methods which require a loaded public/private key, such as sign()

Parameters
  • key – The public/private key data, as either a string, bytes, or one of the various private key class instances or public key class instances (see public_key_types and private_key_types)

  • password (str|bytes) – If your key data is encrypted, pass the password in this argument to decrypt it.

Methods

__init__(key[, password])

Create an instance of KeyManager using the public/private key data key

decrypt(message[, pad, hashing])

Decrypt a message using the loaded private_key - returns the decrypted message as bytes.

encrypt(message[, pad, hashing])

Encrypt a message using the loaded public_key - returns the ciphertext as base64 encoded bytes.

export_key(key, **kwargs)

Export/serialize a given public/private key object as bytes.

export_private(**kwargs)

Serialize the cryptography private key instance loaded into KeyManager into storable bytes.

export_public(**kwargs)

Serialize the cryptography public key instance loaded into KeyManager into storable bytes.

generate_keypair([alg])

Generate a key pair, returning private + public key as serialized bytes based on default_formats and the kwarg format if it’s present.

generate_keypair_raw([alg])

Generate a key pair, returning private + public key instances from the cryptography module.

identify_algorithm(key)

Identifies a cryptography public/private key instance, such as RSAPrivateKey and returns the algorithm name that can be used with other KeyManager methods, e.g.

load_key(data[, password])

Load a private/public key from a string or bytes data containing the key in some format, such as PEM or OpenSSH.

load_keyfile(filename[, password])

Returns an instance of KeyManager using a public/private key loaded from disk, instead of from string/bytes key data.

output_keypair(priv, pub, *args, **kwargs)

Similar to generate_keypair() - except this also writes the private key and public key to the file locations and/or byte streams specified in the first two arguments (priv and pub)

sign(message[, pad, hashing])

Generate a signature for a given message using the loaded private_key.

verify(signature, message[, pad, hashing])

Verify a signature against a given message using an asymmetric public key.

class Format(private_format, private_encoding, public_format='ssh', public_encoding='ssh')

A class alias, allowing for access to the Format class via a class attribute

classmethod get_format(fmtype, key) → Union[cryptography.hazmat.primitives.serialization.base.Encoding, cryptography.hazmat.primitives.serialization.base.PublicFormat, cryptography.hazmat.primitives.serialization.base.PrivateFormat]
combined_key_types = typing.Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey]

A Union which just combines private_key_types and public_key_types into one type.

curves = {'brainpoolP256r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.BrainpoolP256R1'>, 'brainpoolP384r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.BrainpoolP384R1'>, 'brainpoolP512r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.BrainpoolP512R1'>, 'prime192v1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP192R1'>, 'prime256v1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP256R1'>, 'secp192r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP192R1'>, 'secp224r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP224R1'>, 'secp256k1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP256K1'>, 'secp256r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP256R1'>, 'secp384r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP384R1'>, 'secp521r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECP521R1'>, 'sect163k1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT163K1'>, 'sect163r2': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT163R2'>, 'sect233k1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT233K1'>, 'sect233r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT233R1'>, 'sect283k1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT283K1'>, 'sect283r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT283R1'>, 'sect409k1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT409K1'>, 'sect409r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT409R1'>, 'sect571k1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT571K1'>, 'sect571r1': <class 'cryptography.hazmat.primitives.asymmetric.ec.SECT571R1'>}

An alias for Cryptography’s map of string curve names (e.g. secp521r1) to their respective classes

decrypt(message: Union[str, bytes], pad=None, hashing: cryptography.hazmat.primitives.hashes.HashAlgorithm = <cryptography.hazmat.primitives.hashes.SHA256 object>)bytes[source]

Decrypt a message using the loaded private_key - returns the decrypted message as bytes.

NOTE: Only works for RSA private keys

Parameters
  • message (str|bytes) – The ciphertext to decrypt, as base64 or raw bytes

  • pad – (RSA only) An instance of a cryptography padding class, e.g. padding.PSS

  • hashing (HashAlgorithm) – (ECDSA/RSA) Use this hashing method for padding/signatures

Return bytes decoded

The decrypted version of message as bytes

default_formats = {'ecdsa': {'private_encoding': 'pem', 'private_format': 'pkcs8'}, 'ed25519': {'private_encoding': 'pem', 'private_format': 'pkcs8'}, 'rsa': {'private_encoding': 'pem', 'private_format': 'pkcs8'}}

Default Format formatting options for serialising each key algorithm

default_gen = {'ecdsa': {'backend': <cryptography.hazmat.backends.openssl.backend.Backend object>, 'curve': <cryptography.hazmat.primitives.asymmetric.ec.SECP384R1 object>}, 'ed25519': {}, 'rsa': {'backend': <cryptography.hazmat.backends.openssl.backend.Backend object>, 'key_size': 2048, 'public_exponent': 65537}}

A map of key algorithms to their generator’s default kwargs

encrypt(message: Union[str, bytes], pad=None, hashing: cryptography.hazmat.primitives.hashes.HashAlgorithm = <cryptography.hazmat.primitives.hashes.SHA256 object>)bytes[source]

Encrypt a message using the loaded public_key - returns the ciphertext as base64 encoded bytes.

NOTE: Only works for RSA public keys

Parameters
  • message (str|bytes) – The message to encrypt, e.g. hello world

  • pad – (RSA only) An instance of a cryptography padding class, e.g. padding.PSS

  • hashing (HashAlgorithm) – (ECDSA/RSA) Use this hashing method for padding/signatures

Return bytes ciphertext

The encrypted version of message - encoded with Base64 for easy storage/transport

classmethod export_key(key: Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey], **kwargs)bytes[source]

Export/serialize a given public/private key object as bytes.

Uses the default formatting arguments for the detected algorithm from identify_algorithm(), but you can also force it to treat it as a certain algorithm by passing alg

Uses default formatting options by looking up the algorithm in default_formats

Uses the private key serialization arguments for the detected algorithm out of generators

Example:

>>> priv, pub = KeyManager.generate_keypair_raw('ed25519')
>>> key = KeyManager.export_key(pub)
>>> print(key.decode())
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIOeLS2XOcQz11VUnzh6KIZaNtT10YfzHv779zjm95XSy
-----END PRIVATE KEY-----
Parameters
  • alg (str) – An algorithm name as a string, e.g. rsa or ed25519

  • key (combined_key_types) – An instance of a public/private key type listed in combined_key_types

  • format (Format) – Override some or all of the default format/encoding for the keys. Dict Keys: private_format,public_format,private_encoding,public_encoding

  • format – If passed a Format instance, then this instance will be used for serialization instead of merging defaults from default_formats

  • alg – Use this algorithm name e.g. 'rsa' instead of detecting using identify_algorithm()

Return bytes key

The serialized key.

export_private(**kwargs)bytes[source]

Serialize the cryptography private key instance loaded into KeyManager into storable bytes.

This method requires that you’ve instantiated KeyManager with the private key. It will raise a EncryptionError exception if the private_key instance attribute is empty.

Example:

>>> km = KeyManager.load_keyfile('id_ed25519')
>>> print(km.export_private().decode())
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIOeLS2XOcQz11VUnzh6KIZaNtT10YfzHv779zjm95XSy
-----END PRIVATE KEY-----
Parameters
  • format (Format) – Override some or all of the default format/encoding for the keys. Dict Keys: private_format,public_format,private_encoding,public_encoding

  • format – If passed a Format instance, then this instance will be used for serialization instead of merging defaults from default_formats

Return bytes key

The serialized key.

export_public(**kwargs)bytes[source]

Serialize the cryptography public key instance loaded into KeyManager into storable bytes.

This method works whether you’ve instantiated KeyManager with the public key directly, or the private key, as the public key is automatically interpolated from the private key by __init__()

Example:

>>> km = KeyManager.load_keyfile('id_ed25519.pub')
>>> km.export_public()
b'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA6vtKgeNSBERSY1xmr47Ve3uyRALxPR+qOeFeUHrUaf'
Parameters
  • format (Format) – Override some or all of the default format/encoding for the keys. Dict Keys: private_format,public_format,private_encoding,public_encoding

  • format – If passed a Format instance, then this instance will be used for serialization instead of merging defaults from default_formats

Return bytes key

The serialized key.

classmethod generate_keypair(alg='rsa', **kwargs) → Tuple[bytes, bytes][source]

Generate a key pair, returning private + public key as serialized bytes based on default_formats and the kwarg format if it’s present.

By default, private keys are generally returned in PKCS8 format with PEM encoding, while public keys are OpenSSH format and OpenSSH encoding.

Example:

>>> priv, pub = KeyManager.generate_keypair(alg='rsa', key_size=2048)
>>> priv
b'-----BEGIN PRIVATE KEY-----\nMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMjkl
 ...Pw6eZGFwBEYY\n-----END PRIVATE KEY-----\n'

>>> priv, pub = KeyManager.generate_keypair(alg='ecdsa', curve=ec.SECP521R1)
>>> pub
b'ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1...dJCxguBQnb1hL6aDH4fHCjpy6A=='

To override the formatting/encoding:

>>> priv, pub = KeyManager.generate_keypair(
...     alg='ecdsa', format=dict(private_format='openssl', private_encoding='der')
... )
>>> priv
b'0\x81\xa4\x02\x01\x01\x040u\x1e\x8cI\xcd\xfa\xc8\x97\x83\xf8\xed\x1f\xe5\xbd...'
Parameters
  • alg (str) – The algorithm to generate a key for, e.g. 'rsa'

  • kwargs – All kwargs are forwarded to the matching generator in generators

  • key_size (int) – (for rsa and similar algorithms) Number of bits for the RSA key. Minimum of 512 bits.

  • format (dict) – Override some or all of the default format/encoding for the keys. Dict Keys: private_format,public_format,private_encoding,public_encoding

Returns

classmethod generate_keypair_raw(alg='rsa', **kwargs) → Tuple[Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey], Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey]][source]

Generate a key pair, returning private + public key instances from the cryptography module.

Example:

>>> priv, pub = KeyManager.generate_keypair_raw(alg='rsa', key_size=1024)
>>> priv.private_bytes(encoding=Encoding.PEM, format=PrivateFormat.PKCS8)
b'-----BEGIN PRIVATE KEY-----\nMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMjkl
 ...Pw6eZGFwBEYY\n-----END PRIVATE KEY-----\n'

>>> priv, pub = KeyManager.generate_keypair_raw(alg='ecdsa', curve=ec.SECP521R1)
>>> pub.public_bytes(encoding=Encoding.OpenSSH, format=PublicFormat.OpenSSH)
b'ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1...dJCxguBQnb1hL6aDH4fHCjpy6A=='
Parameters
  • alg (str) – The algorithm to generate a key for, e.g. 'rsa'

  • kwargs – All kwargs are forwarded to the matching generator in generators

Return tuple keys

A tuple containing a private key instance, and public key instance

generators = {'ecdsa': (<function generate_private_key>, {'encryption_algorithm': <cryptography.hazmat.primitives.serialization.base.NoEncryption object>}), 'ed25519': (<bound method Ed25519PrivateKey.generate of <class 'cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey'>>, {'encryption_algorithm': <cryptography.hazmat.primitives.serialization.base.NoEncryption object>}), 'rsa': (<function generate_private_key>, {'encryption_algorithm': <cryptography.hazmat.primitives.serialization.base.NoEncryption object>})}

Maps each key algorithm to a tuple containing the algorithm’s generation function, and any extra kwargs needed for generating a private key

classmethod identify_algorithm(key: Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey])str[source]

Identifies a cryptography public/private key instance, such as RSAPrivateKey and returns the algorithm name that can be used with other KeyManager methods, e.g. 'rsa' or 'ed25519'

Example:

>>> priv, pub = KeyManager.generate_keypair_raw(alg='ecdsa', curve=ec.SECP521R1)
>>> KeyManager.identify_algorithm(priv)
'ecdsa'
>>> priv, pub = KeyManager.generate_keypair_raw()
>>> KeyManager.identify_algorithm(priv)
'rsa'
>>> KeyManager.identify_algorithm(pub)
'rsa'
Parameters

key (combined_key_types) – A cryptography public/private key instance

Return str algorithm

The name of the algorithm used by this key

classmethod load_key(data: Union[str, bytes], password: bytes = None) → Tuple[Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey, cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey], str][source]

Load a private/public key from a string or bytes data containing the key in some format, such as PEM or OpenSSH. Use load_keyfile() to load a key from a file + auto-instantiate KeyManager with it.

Example:

>>> key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG3v6guHpI/j7AIl3F/EWMSReX8fH8MOSq1bC3ZuEjjC'
>>> KeyManager.load_key(key)
(<cryptography.hazmat.backends.openssl.ed25519._Ed25519PublicKey object at 0x7fa118289ba8>, 'public')
Parameters
  • data (str|bytes) – The public/private key data, as a string or bytes

  • password (str|bytes) – If your key data is encrypted, pass the password in this argument to decrypt it.

Raises

InvalidFormat – When the key could not be identified, is not supported, or is corrupted

Return tuple key_data

A tuple containing an instance of the key, and a string public or private Example: (<_Ed25519PublicKey object>, 'public')

classmethod load_keyfile(filename: Union[str, bytes], password: Union[str, bytes] = None)[source]

Returns an instance of KeyManager using a public/private key loaded from disk, instead of from string/bytes key data.

Example:

>>> km = KeyManager.load_keyfile('id_rsa')
>>> d = km.encrypt('hello world')
>>> km.decrypt(d)
b'hello world'
Parameters
  • filename (str|bytes) – The file location where the key is stored

  • password (str|bytes) – If the key is encrypted, specify the password to decrypt it

Raises
  • InvalidFormat – When the key could not be identified, is not supported, or is corrupted

  • FileNotFoundError – The given filename couldn’t be found.

Return KeyManager cls

An instance of KeyManager (or child class) initialised with the key

classmethod output_keypair(priv: Union[str, _io.BufferedWriter], pub: Union[str, _io.TextIOWrapper], *args, **kwargs) → Tuple[bytes, bytes][source]

Similar to generate_keypair() - except this also writes the private key and public key to the file locations and/or byte streams specified in the first two arguments (priv and pub)

Example

Generate a 4096-bit RSA key pair, and output the private key to the file id_rsa , and the public key to id_rsa.pub.

The generated keypair is also returned as a tuple pair (bytes) containing the private and public key:

>>> priv, pub = KeyManager.output_keypair('id_rsa', 'id_rsa.pub', alg='rsa', key_size=4096)
Parameters
  • priv (str|BufferedWriter) – File location to save private key, or writable byte stream

  • pub (str|BufferedWriter) – File location to save public key, or writable byte stream

  • args – All additional args are forwarded to generate_keypair()

  • kwargs – All kwargs are forwarded to generate_keypair()

private_key: Optional[Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey]]

When the class is initialised, this instance attribute holds a cryptography private key class instance, or None if we don’t have a private key available.

private_key_types = typing.Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey]

The cryptography library doesn’t have a standard parent type for private keys, so we need a Union to hold the various private key types for return types, type/instance comparison etc.

public_key: Optional[Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey]]

When the class is initialised, this instance attribute holds a cryptography public key class instance, or None if we don’t have a public key available.

public_key_types = typing.Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey]

Same as private_key_types but for public key types.

raw_priv_types = (<class 'cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization'>, <class 'cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization'>, <class 'cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey'>)

This extracts the actual class types from the Union[] for isinstance() checks

raw_pub_types = (<class 'cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey'>, <class 'cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey'>, <class 'cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey'>)

This extracts the actual class types from the Union[] for isinstance() checks

sign(message: Union[str, bytes], pad=None, hashing: cryptography.hazmat.primitives.hashes.HashAlgorithm = <cryptography.hazmat.primitives.hashes.SHA256 object>)bytes[source]

Generate a signature for a given message using the loaded private_key. The signature is Base64 encoded to allow for easy storage and transmission of the signature, and can later be verified by verify() using public_key

>>> km = KeyManager.load_keyfile('id_rsa')
>>> sig = km.sign('hello world')        # Sign 'hello world' using the id_rsa private key
>>> try:
...     km.verify(sig, 'hello world')   # Verify it using the public key (automatically generated)
...     print('Signature is valid')
>>> except cryptography.exceptions.InvalidSignature:
...     print('Signature IS NOT VALID!')

Alternatively, you can manually run base64.urlsafe_b64decode() to decode the signature back into raw bytes, then you can verify it using the verify method of a cryptography public key instance, such as Ed25519PublicKey or RSAPublicKey

Parameters
  • message (str|bytes) – The message to verify, e.g. hello world

  • pad – (RSA only) An instance of a cryptography padding class, e.g. padding.PSS

  • hashing (HashAlgorithm) – (ECDSA/RSA) Use this hashing method for padding/signatures

Raises

cryptography.exceptions.InvalidSignature – When the signature does not match the message

Return bytes sig

A base64 urlsafe encoded signature

type_name_map = {<class 'cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey'>: 'rsa', <class 'cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey'>: 'rsa', <class 'cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKeyWithSerialization'>: 'rsa', <class 'cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey'>: 'ed25519', <class 'cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey'>: 'ed25519', <class 'cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey'>: 'ecdsa', <class 'cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey'>: 'ecdsa', <class 'cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKeyWithSerialization'>: 'ecdsa'}

Maps public/private key types to their associated algorithm name for type/instance identification

verify(signature: Union[str, bytes], message: Union[str, bytes], pad=None, hashing: cryptography.hazmat.primitives.hashes.HashAlgorithm = <cryptography.hazmat.primitives.hashes.SHA256 object>)bool[source]

Verify a signature against a given message using an asymmetric public key.

>>> km = KeyManager.load_keyfile('id_rsa')
>>> sig = km.sign('hello world')    # Sign 'hello world' using the id_rsa private key
>>> try:
...     km.verify(sig, 'hello world')   # Verify it using the public key (automatically generated)
...     print('Signature is valid')
>>> except cryptography.exceptions.InvalidSignature:
...     print('Signature IS NOT VALID!')
Parameters
  • signature (str|bytes) – The binary, or base64 urlsafe encoded signature to check message against

  • message (str|bytes) – The message to verify, e.g. hello world

  • pad – (RSA only) An instance of a cryptography padding class, e.g. padding.PSS

  • hashing (HashAlgorithm) – (ECDSA/RSA) Use this hashing method for padding/signatures

Raises

cryptography.exceptions.InvalidSignature – When the signature does not match the message

Return bool is_valid

True if signature is valid, otherwise raises InvalidSignature.

Attributes

Attributes

backend

combined_key_types

A Union which just combines private_key_types and public_key_types into one type.

curves

An alias for Cryptography’s map of string curve names (e.g.

default_formats

Default Format formatting options for serialising each key algorithm

default_gen

A map of key algorithms to their generator’s default kwargs

generators

Maps each key algorithm to a tuple containing the algorithm’s generation function, and any extra kwargs needed for generating a private key

private_key_types

The cryptography library doesn’t have a standard parent type for private keys, so we need a Union to hold the various private key types for return types, type/instance comparison etc.

public_key_types

Same as private_key_types but for public key types.

raw_priv_types

This extracts the actual class types from the Union[] for isinstance() checks

raw_pub_types

This extracts the actual class types from the Union[] for isinstance() checks

type_name_map

Maps public/private key types to their associated algorithm name for type/instance identification