Module sshkey_tools.keys
Classes for handling SSH public/private keys
Expand source code
"""
Classes for handling SSH public/private keys
"""
from base64 import b64decode
from enum import Enum
from struct import unpack
from typing import Union
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends.openssl.dsa import _DSAPrivateKey, _DSAPublicKey
from cryptography.hazmat.backends.openssl.ec import (
_EllipticCurvePrivateKey,
_EllipticCurvePublicKey,
)
from cryptography.hazmat.backends.openssl.ed25519 import (
_Ed25519PrivateKey,
_Ed25519PublicKey,
)
from cryptography.hazmat.backends.openssl.rsa import _RSAPrivateKey, _RSAPublicKey
from cryptography.hazmat.primitives import hashes as _HASHES
from cryptography.hazmat.primitives import serialization as _SERIALIZATION
from cryptography.hazmat.primitives.asymmetric import dsa as _DSA
from cryptography.hazmat.primitives.asymmetric import ec as _ECDSA
from cryptography.hazmat.primitives.asymmetric import ed25519 as _ED25519
from cryptography.hazmat.primitives.asymmetric import padding as _PADDING
from cryptography.hazmat.primitives.asymmetric import rsa as _RSA
from . import exceptions as _EX
from .utils import ensure_bytestring, ensure_string, nullsafe_getattr
from .utils import md5_fingerprint as _FP_MD5
from .utils import sha256_fingerprint as _FP_SHA256
from .utils import sha512_fingerprint as _FP_SHA512
PUBKEY_MAP = {
_RSAPublicKey: "RsaPublicKey",
_DSAPublicKey: "DsaPublicKey",
_EllipticCurvePublicKey: "EcdsaPublicKey",
_Ed25519PublicKey: "Ed25519PublicKey",
}
PRIVKEY_MAP = {
_RSAPrivateKey: "RsaPrivateKey",
_DSAPrivateKey: "DsaPrivateKey",
_EllipticCurvePrivateKey: "EcdsaPrivateKey",
# trunk-ignore(gitleaks/generic-api-key)
_Ed25519PrivateKey: "Ed25519PrivateKey",
}
ECDSA_HASHES = {
"secp256r1": _HASHES.SHA256,
"secp384r1": _HASHES.SHA384,
"secp521r1": _HASHES.SHA512,
}
PubkeyClasses = Union[
_RSA.RSAPublicKey,
_DSA.DSAPublicKey,
_ECDSA.EllipticCurvePublicKey,
_ED25519.Ed25519PublicKey,
]
PrivkeyClasses = Union[
_RSA.RSAPrivateKey,
_DSA.DSAPrivateKey,
_ECDSA.EllipticCurvePrivateKey,
_ED25519.Ed25519PrivateKey,
]
class RsaAlgs(Enum):
"""
RSA Algorithms
Values:
SHA1
SHA256
SHA512
"""
SHA1 = ("ssh-rsa", _HASHES.SHA1)
SHA256 = ("rsa-sha2-256", _HASHES.SHA256)
SHA512 = ("rsa-sha2-512", _HASHES.SHA512)
class EcdsaCurves(Enum):
"""
ECDSA Curves
Values:
P256
P384
P521
"""
P256 = _ECDSA.SECP256R1
P384 = _ECDSA.SECP384R1
P521 = _ECDSA.SECP521R1
class FingerprintHashes(Enum):
"""
Fingerprint hashes
Values:
MD5
SHA256
SHA512
"""
MD5 = _FP_MD5
SHA256 = _FP_SHA256
SHA512 = _FP_SHA512
class PublicKey:
"""
Class for handling SSH public keys
"""
def __init__(
self, key: PrivkeyClasses = None, comment: Union[str, bytes] = "", **kwargs
) -> None:
self.key = key
self.comment = comment
self.public_numbers = kwargs.get("public_numbers", None)
self.key_type = kwargs.get("key_type", None)
self.serialized = kwargs.get("serialized", None)
self.export_opts = [
_SERIALIZATION.Encoding.OpenSSH,
_SERIALIZATION.PublicFormat.OpenSSH,
]
# Ensure comment is not None
self.comment = nullsafe_getattr(self, "comment", "")
@classmethod
def from_class(
cls,
key_class: PubkeyClasses,
comment: Union[str, bytes] = "",
key_type: Union[str, bytes] = None,
) -> "PublicKey":
"""
Creates a new SSH Public key from a cryptography class
Args:
key_class (PubkeyClasses): The cryptography class containing the public key
comment (Union[str, bytes], optional): Comment to add to the key. Defaults to None.
key_type (Union[str, bytes], optional): Manually specify the key type. Defaults to None.
Raises:
_EX.InvalidKeyException: The key you are trying to load is invalid
Returns:
PublicKey: Any of the PublicKey child classes
"""
try:
return globals()[PUBKEY_MAP[key_class.__class__]](
key_class, comment, key_type
)
except KeyError:
raise _EX.InvalidKeyException("Invalid public key") from KeyError
@classmethod
def from_string(
cls, data: Union[str, bytes], encoding: str = "utf-8"
) -> "PublicKey":
"""
Loads an SSH public key from a string containing the data
in OpenSSH format (SubjectPublickeyInfo)
Args:
data (Union[str, bytes]): The string or byte data containing the key
Returns:
PublicKey: Any of the PublicKey child classes
"""
split = ensure_bytestring(data, encoding).split(b" ")
comment = None
if len(split) > 2:
comment = split[2]
return cls.from_class(
key_class=_SERIALIZATION.load_ssh_public_key(b" ".join(split[:2])),
comment=comment,
)
@classmethod
def from_file(cls, path: str) -> "PublicKey":
"""
Loads an SSH Public key from a file
Args:
path (str): The path to the file
Returns:
PublicKey: Any of the PublicKey child classes
"""
with open(path, "rb") as file:
data = file.read()
return cls.from_string(data)
@classmethod
# pylint: disable=broad-except
def from_bytes(cls, data: bytes) -> "PublicKey":
"""
Loads a public key from byte data
Args:
data (bytes): The bytestring containing the public key
Raises:
_EX.InvalidKeyException: Invalid data input
Returns:
PublicKey: PublicKey subclass depending on the key type
"""
for key_class in PUBKEY_MAP.values():
try:
key = globals()[key_class].from_raw_bytes(data)
return key
except Exception:
pass
raise _EX.InvalidKeyException("Invalid public key")
def get_fingerprint(
self, hash_method: FingerprintHashes = FingerprintHashes.SHA256
) -> str:
"""
Generates a fingerprint of the public key
Args:
hash_method (FingerprintHashes, optional): Type of hash. Defaults to SHA256.
Returns:
str: The hash of the public key
"""
return hash_method(self.raw_bytes())
def serialize(self) -> bytes:
"""
Serialize the key for storage in file or string
Returns:
bytes: The serialized key in OpenSSH format
"""
return self.key.public_bytes(*self.export_opts)
def raw_bytes(self) -> bytes:
"""
Export the public key to a raw byte string
Returns:
bytes: The raw certificate bytes
"""
return b64decode(self.serialize().split(b" ")[1])
def to_string(self, encoding: str = "utf-8") -> str:
"""
Export the public key as a string
Returns:
str: The public key in OpenSSH format
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
"""
return " ".join(
[
ensure_string(self.serialize(), encoding),
ensure_string(nullsafe_getattr(self, "comment", ""), encoding),
]
)
def to_file(self, path: str, encoding: str = "utf-8") -> None:
"""
Export the public key to a file
Args:
path (str): The path of the file
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
"""
with open(path, "w", encoding=encoding) as pubkey_file:
pubkey_file.write(self.to_string())
class PrivateKey:
"""
Class for handling SSH Private keys
"""
def __init__(self, key: PrivkeyClasses, public_key: PublicKey, **kwargs) -> None:
self.key = key
self.public_key = public_key
self.private_numbers = kwargs.get("private_numbers", None)
self.export_opts = {
"encoding": _SERIALIZATION.Encoding.PEM,
"format": _SERIALIZATION.PrivateFormat.OpenSSH,
"encryption": _SERIALIZATION.BestAvailableEncryption,
}
@classmethod
def from_class(cls, key_class: PrivkeyClasses) -> "PrivateKey":
"""
Import an SSH Private key from a cryptography key class
Args:
key_class (PrivkeyClasses): A cryptography private key class
Raises:
_EX.InvalidKeyException: Invalid private key
Returns:
PrivateKey: One of the PrivateKey child classes
"""
try:
return globals()[PRIVKEY_MAP[key_class.__class__]](key_class)
except KeyError:
raise _EX.InvalidKeyException("Invalid private key") from KeyError
@classmethod
def from_string(
cls,
key_data: Union[str, bytes],
password: Union[str, bytes] = None,
encoding: str = "utf-8",
) -> "PrivateKey":
"""
Loads an SSH private key from a string containing the key data
Args:
key_data (Union[str, bytes]): The string containing the key data
password (str, optional): The password for the private key. Defaults to None.
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
Returns:
PrivateKey: Any of the PrivateKey child classes
"""
key_data, password = ensure_bytestring((key_data, password), encoding=encoding)
private_key = _SERIALIZATION.load_ssh_private_key(key_data, password=password)
return cls.from_class(private_key)
@classmethod
def from_file(
cls,
path: str,
password: Union[str, bytes] = None,
) -> "PrivateKey":
"""
Loads an SSH private key from a file
Args:
path (str): The path to the file
password (str, optional): The encryption password. Defaults to None.
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
Returns:
PrivateKey: Any of the PrivateKey child classes
"""
with open(path, "rb") as key_file:
return cls.from_string(key_file.read(), password)
def get_fingerprint(
self, hash_method: FingerprintHashes = FingerprintHashes.SHA256
) -> str:
"""
Generates a fingerprint of the private key
Args:
hash_method (FingerprintHashes, optional): Type of hash. Defaults to SHA256.
Returns:
str: The hash of the private key
"""
return self.public_key.get_fingerprint(hash_method)
def to_bytes(self, password: Union[str, bytes] = None) -> bytes:
"""
Exports the private key to a byte string
Args:
password (Union[str, bytes], optional): The password to set for the key.
Defaults to None.
Returns:
bytes: The private key in PEM format
"""
password = ensure_bytestring(password)
encryption = _SERIALIZATION.NoEncryption()
if password is not None:
encryption = self.export_opts["encryption"](password)
return self.key.private_bytes(
self.export_opts["encoding"], self.export_opts["format"], encryption
)
def to_string(
self, password: Union[str, bytes] = None, encoding: str = "utf-8"
) -> str:
"""
Exports the private key to a string
Args:
password (Union[str, bytes], optional): The password to set for the key.
Defaults to None.
encoding (str, optional): The encoding of the string. Defaults to 'utf-8'.
Returns:
bytes: The private key in PEM format
"""
return ensure_string(self.to_bytes(password), encoding)
def to_file(
self, path: str, password: Union[str, bytes] = None, encoding: str = "utf-8"
) -> None:
"""
Exports the private key to a file
Args:
password (Union[str, bytes], optional): The password to set for the key.
Defaults to None.
Returns:
bytes: The private key in PEM format
"""
with open(path, "w", encoding=encoding) as key_file:
key_file.write(self.to_string(password, encoding))
class RsaPublicKey(PublicKey):
"""
Class for holding RSA public keys
"""
def __init__(
self,
key: _RSA.RSAPublicKey,
comment: Union[str, bytes] = None,
key_type: Union[str, bytes] = None,
serialized: bytes = None,
):
super().__init__(
key=key,
comment=comment,
key_type=key_type,
public_numbers=key.public_numbers(),
serialized=serialized,
)
@classmethod
# pylint: disable=invalid-name
def from_numbers(cls, e: int, n: int) -> "RsaPublicKey":
"""
Loads an RSA Public Key from the public numbers e and n
Args:
e (int): e-value
n (int): n-value
Returns:
RsaPublicKey: _description_
"""
return cls(key=_RSA.RSAPublicNumbers(e, n).public_key())
def verify(
self, data: bytes, signature: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512
) -> None:
"""
Verifies a signature
Args:
data (bytes): The data to verify
signature (bytes): The signature to verify
hash_method (HashMethods): The hash method to use
Raises:
Raises a sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
"""
try:
return self.key.verify(
signature, data, _PADDING.PKCS1v15(), hash_alg.value[1]()
)
except InvalidSignature:
raise _EX.InvalidSignatureException(
"The signature is invalid for the given data"
) from InvalidSignature
class RsaPrivateKey(PrivateKey):
"""
Class for holding RSA private keys
"""
def __init__(self, key: _RSA.RSAPrivateKey):
super().__init__(
key=key,
public_key=RsaPublicKey(key.public_key()),
private_numbers=key.private_numbers(),
)
@classmethod
# pylint: disable=invalid-name,too-many-arguments
def from_numbers(
cls,
e: int,
n: int,
d: int,
p: int = None,
q: int = None,
dmp1: int = None,
dmq1: int = None,
iqmp: int = None,
) -> "RsaPrivateKey":
"""
Load an RSA private key from numbers
Args:
n (int): The public modulus (n)
e (int): The public exponent (e)
d (int): The private exponent (d)
p (int, optional): One of two primes (p) composing the public modulus.
Automatically generates if not provided.
q (int, optional): One of two primes (q) composing the public modulus.
Automatically generates if not provided
dmp1 (int, optional): Chinese remainder theorem coefficient to speed up operations
Calculated as d mod (p-1)
Automatically generates if not provided
dmq1 (int, optional): Chinese remainder theorem coefficient to speed up operations
Calculated as d mod(q-1)
Automatically generates if not provided
iqmp (int, optional): Chinese remainder theorem coefficient to speed up operations
Calculated as q^-1 mod p
Automatically generates if not provided
Returns:
RsaPrivateKey: An instance of RsaPrivateKey
"""
if None in (p, q):
p, q = _RSA.rsa_recover_prime_factors(n, e, d)
dmp1 = _RSA.rsa_crt_dmp1(d, p) if dmp1 is None else dmp1
dmq1 = _RSA.rsa_crt_dmq1(d, q) if dmq1 is None else dmq1
iqmp = _RSA.rsa_crt_iqmp(p, q) if iqmp is None else iqmp
return cls(
key=_RSA.RSAPrivateNumbers(
public_numbers=_RSA.RSAPublicNumbers(e, n),
p=p,
q=q,
d=d,
dmp1=_RSA.rsa_crt_dmp1(d, p),
dmq1=_RSA.rsa_crt_dmq1(d, q),
iqmp=_RSA.rsa_crt_iqmp(p, q),
).private_key()
)
@classmethod
def generate(
cls, key_size: int = 4096, public_exponent: int = 65537
) -> "RsaPrivateKey":
"""
Generates a new RSA private key
Args:
key_size (int, optional): The number of bytes for the key. Defaults to 4096.
public_exponent (int, optional): The public exponent to use. Defaults to 65537.
Returns:
RsaPrivateKey: Instance of RsaPrivateKey
"""
return cls.from_class(
_RSA.generate_private_key(
public_exponent=public_exponent, key_size=key_size
)
)
def sign(self, data: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512) -> bytes:
"""
Signs a block of data and returns the signature
Args:
data (bytes): Block of byte data to sign
hash_alg (RsaAlgs, optional): Algorithm to use for hashing.
Defaults to SHA512.
Returns:
bytes: The signature bytes
"""
return self.key.sign(data, _PADDING.PKCS1v15(), hash_alg.value[1]())
class DsaPublicKey(PublicKey):
"""
Class for holding DSA public keys
"""
def __init__(
self,
key: _DSA.DSAPublicKey,
comment: Union[str, bytes] = None,
key_type: Union[str, bytes] = None,
serialized: bytes = None,
):
super().__init__(
key=key,
comment=comment,
key_type=key_type,
public_numbers=key.public_numbers(),
serialized=serialized,
)
self.parameters = key.parameters().parameter_numbers()
@classmethod
# pylint: disable=invalid-name
def from_numbers(cls, p: int, q: int, g: int, y: int) -> "DsaPublicKey":
"""
Create a DSA public key from public numbers and parameters
Args:
p (int): P parameter, the prime modulus
q (int): Q parameter, the order of the subgroup
g (int): G parameter, the generator
y (int): The public number Y
Returns:
DsaPublicKey: An instance of DsaPublicKey
"""
return cls(
key=_DSA.DSAPublicNumbers(
y=y, parameter_numbers=_DSA.DSAParameterNumbers(p=p, q=q, g=g)
).public_key()
)
def verify(self, data: bytes, signature: bytes) -> None:
"""
Verifies a signature
Args:
data (bytes): The data to verify
signature (bytes): The signature to verify
Raises:
Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
"""
try:
return self.key.verify(signature, data, _HASHES.SHA1())
except InvalidSignature:
raise _EX.InvalidSignatureException(
"The signature is invalid for the given data"
) from InvalidSignature
class DsaPrivateKey(PrivateKey):
"""
Class for holding DSA private keys
"""
def __init__(self, key: _DSA.DSAPrivateKey):
super().__init__(
key=key,
public_key=DsaPublicKey(key.public_key()),
private_numbers=key.private_numbers(),
)
@classmethod
# pylint: disable=invalid-name,too-many-arguments
def from_numbers(cls, p: int, q: int, g: int, y: int, x: int) -> "DsaPrivateKey":
"""
Creates a new DsaPrivateKey object from parameters and public/private numbers
Args:
p (int): P parameter, the prime modulus
q (int): Q parameter, the order of the subgroup
g (int): G parameter, the generator
y (int): The public number Y
x (int): The private number X
Returns:
_type_: _description_
"""
return cls(
key=_DSA.DSAPrivateNumbers(
public_numbers=_DSA.DSAPublicNumbers(
y=y, parameter_numbers=_DSA.DSAParameterNumbers(p=p, q=q, g=g)
),
x=x,
).private_key()
)
@classmethod
def generate(cls) -> "DsaPrivateKey":
"""
Generate a new DSA private key
Key size is fixed since OpenSSH only supports 1024-bit DSA keys
Returns:
DsaPrivateKey: An instance of DsaPrivateKey
"""
return cls.from_class(_DSA.generate_private_key(key_size=1024))
def sign(self, data: bytes):
"""
Signs a block of data and returns the signature
Args:
data (bytes): Block of byte data to sign
Returns:
bytes: The signature bytes
"""
return self.key.sign(data, _HASHES.SHA1())
class EcdsaPublicKey(PublicKey):
"""
Class for holding ECDSA public keys
"""
def __init__(
self,
key: _ECDSA.EllipticCurvePublicKey,
comment: Union[str, bytes] = None,
key_type: Union[str, bytes] = None,
serialized: bytes = None,
):
super().__init__(
key=key,
comment=comment,
key_type=key_type,
public_numbers=key.public_numbers(),
serialized=serialized,
)
@classmethod
# pylint: disable=invalid-name
def from_numbers(
cls, curve: Union[str, _ECDSA.EllipticCurve], x: int, y: int
) -> "EcdsaPublicKey":
"""
Create an ECDSA public key from public numbers and parameters
Args:
curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key
x (int): The affine X component of the public point
y (int): The affine Y component of the public point
Returns:
EcdsaPublicKey: An instance of EcdsaPublicKey
"""
if not isinstance(curve, _ECDSA.EllipticCurve) and curve not in ECDSA_HASHES:
raise _EX.InvalidCurveException(
f"Invalid curve, must be one of {', '.join(ECDSA_HASHES.keys())}"
)
if isinstance(curve, _ECDSA.EllipticCurve):
curve = curve.name
return cls(
key=_ECDSA.EllipticCurvePublicNumbers(
curve=getattr(_ECDSA, curve.upper())(),
x=x,
y=y,
).public_key()
)
def verify(self, data: bytes, signature: bytes) -> None:
"""
Verifies a signature
Args:
data (bytes): The data to verify
signature (bytes): The signature to verify
Raises:
Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
"""
try:
curve_hash = ECDSA_HASHES[self.key.curve.name]()
return self.key.verify(signature, data, _ECDSA.ECDSA(curve_hash))
except InvalidSignature:
raise _EX.InvalidSignatureException(
"The signature is invalid for the given data"
) from InvalidSignature
class EcdsaPrivateKey(PrivateKey):
"""
Class for holding ECDSA private keys
"""
def __init__(self, key: _ECDSA.EllipticCurvePrivateKey):
super().__init__(
key=key,
public_key=EcdsaPublicKey(key.public_key()),
private_numbers=key.private_numbers(),
)
@classmethod
# pylint: disable=invalid-name
def from_numbers(
cls, curve: Union[str, _ECDSA.EllipticCurve], x: int, y: int, private_value: int
):
"""
Creates a new EcdsaPrivateKey object from parameters and public/private numbers
Args:
curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key
x (int): The affine X component of the public point
y (int): The affine Y component of the public point
private_value (int): The private value
Returns:
_type_: _description_
"""
if not isinstance(curve, _ECDSA.EllipticCurve) and curve not in ECDSA_HASHES:
raise _EX.InvalidCurveException(
f"Invalid curve, must be one of {', '.join(ECDSA_HASHES.keys())}"
)
if isinstance(curve, _ECDSA.EllipticCurve):
curve = curve.name
return cls(
key=_ECDSA.EllipticCurvePrivateNumbers(
public_numbers=_ECDSA.EllipticCurvePublicNumbers(
curve=getattr(_ECDSA, curve.upper())(),
x=x,
y=y,
),
private_value=private_value,
).private_key()
)
@classmethod
def generate(cls, curve: EcdsaCurves = EcdsaCurves.P521):
"""
Generate a new ECDSA private key
Args:
curve (EcdsaCurves): Which curve to use. Default secp521r1
Returns:
EcdsaPrivateKey: An instance of EcdsaPrivateKey
"""
return cls.from_class(_ECDSA.generate_private_key(curve=curve.value))
def sign(self, data: bytes):
"""
Signs a block of data and returns the signature
Args:
data (bytes): Block of byte data to sign
Returns:
bytes: The signature bytes
"""
curve_hash = ECDSA_HASHES[self.key.curve.name]()
return self.key.sign(data, _ECDSA.ECDSA(curve_hash))
class Ed25519PublicKey(PublicKey):
"""
Class for holding ED25519 public keys
"""
def __init__(
self,
key: _ED25519.Ed25519PublicKey,
comment: Union[str, bytes] = None,
key_type: Union[str, bytes] = None,
serialized: bytes = None,
):
super().__init__(
key=key, comment=comment, key_type=key_type, serialized=serialized
)
@classmethod
def from_raw_bytes(cls, raw_bytes: bytes) -> "Ed25519PublicKey":
"""
Load an ED25519 public key from raw bytes
Args:
raw_bytes (bytes): The raw bytes of the key
Returns:
Ed25519PublicKey: Instance of Ed25519PublicKey
"""
if b"ssh-ed25519" in raw_bytes:
id_length = unpack(">I", raw_bytes[:4])[0] + 8
raw_bytes = raw_bytes[id_length:]
return cls.from_class(
_ED25519.Ed25519PublicKey.from_public_bytes(data=raw_bytes)
)
def verify(self, data: bytes, signature: bytes) -> None:
"""
Verifies a signature
Args:
data (bytes): The data to verify
signature (bytes): The signature to verify
Raises:
Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
"""
try:
return self.key.verify(signature, data)
except InvalidSignature:
raise _EX.InvalidSignatureException(
"The signature is invalid for the given data"
) from InvalidSignature
class Ed25519PrivateKey(PrivateKey):
"""
Class for holding ED25519 private keys
"""
def __init__(self, key: _ED25519.Ed25519PrivateKey):
super().__init__(key=key, public_key=Ed25519PublicKey(key.public_key()))
@classmethod
def from_raw_bytes(cls, raw_bytes: bytes) -> "Ed25519PrivateKey":
"""
Load an ED25519 private key from raw bytes
Args:
raw_bytes (bytes): The raw bytes of the key
Returns:
Ed25519PrivateKey: Instance of Ed25519PrivateKey
"""
return cls.from_class(
_ED25519.Ed25519PrivateKey.from_private_bytes(data=raw_bytes)
)
@classmethod
def generate(cls) -> "Ed25519PrivateKey":
"""
Generates a new ED25519 Private Key
Returns:
Ed25519PrivateKey: Instance of Ed25519PrivateKey
"""
return cls.from_class(_ED25519.Ed25519PrivateKey.generate())
def raw_bytes(self) -> bytes:
"""
Export the raw key bytes
Returns:
bytes: The key bytes
"""
return self.key.private_bytes(
encoding=_SERIALIZATION.Encoding.Raw,
format=_SERIALIZATION.PrivateFormat.Raw,
encryption_algorithm=_SERIALIZATION.NoEncryption(),
)
def sign(self, data: bytes):
"""
Signs a block of data and returns the signature
Args:
data (bytes): Block of byte data to sign
Returns:
bytes: The signature bytes
"""
return self.key.sign(data)
Classes
class DsaPrivateKey (key: cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey)
-
Class for holding DSA private keys
Expand source code
class DsaPrivateKey(PrivateKey): """ Class for holding DSA private keys """ def __init__(self, key: _DSA.DSAPrivateKey): super().__init__( key=key, public_key=DsaPublicKey(key.public_key()), private_numbers=key.private_numbers(), ) @classmethod # pylint: disable=invalid-name,too-many-arguments def from_numbers(cls, p: int, q: int, g: int, y: int, x: int) -> "DsaPrivateKey": """ Creates a new DsaPrivateKey object from parameters and public/private numbers Args: p (int): P parameter, the prime modulus q (int): Q parameter, the order of the subgroup g (int): G parameter, the generator y (int): The public number Y x (int): The private number X Returns: _type_: _description_ """ return cls( key=_DSA.DSAPrivateNumbers( public_numbers=_DSA.DSAPublicNumbers( y=y, parameter_numbers=_DSA.DSAParameterNumbers(p=p, q=q, g=g) ), x=x, ).private_key() ) @classmethod def generate(cls) -> "DsaPrivateKey": """ Generate a new DSA private key Key size is fixed since OpenSSH only supports 1024-bit DSA keys Returns: DsaPrivateKey: An instance of DsaPrivateKey """ return cls.from_class(_DSA.generate_private_key(key_size=1024)) def sign(self, data: bytes): """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign Returns: bytes: The signature bytes """ return self.key.sign(data, _HASHES.SHA1())
Ancestors
Static methods
def from_numbers(p: int, q: int, g: int, y: int, x: int) ‑> DsaPrivateKey
-
Creates a new DsaPrivateKey object from parameters and public/private numbers
Args
p
:int
- P parameter, the prime modulus
q
:int
- Q parameter, the order of the subgroup
g
:int
- G parameter, the generator
y
:int
- The public number Y
x
:int
- The private number X
Returns
_type_
- description
Expand source code
@classmethod # pylint: disable=invalid-name,too-many-arguments def from_numbers(cls, p: int, q: int, g: int, y: int, x: int) -> "DsaPrivateKey": """ Creates a new DsaPrivateKey object from parameters and public/private numbers Args: p (int): P parameter, the prime modulus q (int): Q parameter, the order of the subgroup g (int): G parameter, the generator y (int): The public number Y x (int): The private number X Returns: _type_: _description_ """ return cls( key=_DSA.DSAPrivateNumbers( public_numbers=_DSA.DSAPublicNumbers( y=y, parameter_numbers=_DSA.DSAParameterNumbers(p=p, q=q, g=g) ), x=x, ).private_key() )
def generate() ‑> DsaPrivateKey
-
Generate a new DSA private key Key size is fixed since OpenSSH only supports 1024-bit DSA keys
Returns
DsaPrivateKey
- An instance of DsaPrivateKey
Expand source code
@classmethod def generate(cls) -> "DsaPrivateKey": """ Generate a new DSA private key Key size is fixed since OpenSSH only supports 1024-bit DSA keys Returns: DsaPrivateKey: An instance of DsaPrivateKey """ return cls.from_class(_DSA.generate_private_key(key_size=1024))
Methods
def sign(self, data: bytes)
-
Signs a block of data and returns the signature
Args
data
:bytes
- Block of byte data to sign
Returns
bytes
- The signature bytes
Expand source code
def sign(self, data: bytes): """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign Returns: bytes: The signature bytes """ return self.key.sign(data, _HASHES.SHA1())
Inherited members
class DsaPublicKey (key: cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None)
-
Class for holding DSA public keys
Expand source code
class DsaPublicKey(PublicKey): """ Class for holding DSA public keys """ def __init__( self, key: _DSA.DSAPublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None, ): super().__init__( key=key, comment=comment, key_type=key_type, public_numbers=key.public_numbers(), serialized=serialized, ) self.parameters = key.parameters().parameter_numbers() @classmethod # pylint: disable=invalid-name def from_numbers(cls, p: int, q: int, g: int, y: int) -> "DsaPublicKey": """ Create a DSA public key from public numbers and parameters Args: p (int): P parameter, the prime modulus q (int): Q parameter, the order of the subgroup g (int): G parameter, the generator y (int): The public number Y Returns: DsaPublicKey: An instance of DsaPublicKey """ return cls( key=_DSA.DSAPublicNumbers( y=y, parameter_numbers=_DSA.DSAParameterNumbers(p=p, q=q, g=g) ).public_key() ) def verify(self, data: bytes, signature: bytes) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify Raises: Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: return self.key.verify(signature, data, _HASHES.SHA1()) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Ancestors
Static methods
def from_numbers(p: int, q: int, g: int, y: int) ‑> DsaPublicKey
-
Create a DSA public key from public numbers and parameters
Args
p
:int
- P parameter, the prime modulus
q
:int
- Q parameter, the order of the subgroup
g
:int
- G parameter, the generator
y
:int
- The public number Y
Returns
DsaPublicKey
- An instance of DsaPublicKey
Expand source code
@classmethod # pylint: disable=invalid-name def from_numbers(cls, p: int, q: int, g: int, y: int) -> "DsaPublicKey": """ Create a DSA public key from public numbers and parameters Args: p (int): P parameter, the prime modulus q (int): Q parameter, the order of the subgroup g (int): G parameter, the generator y (int): The public number Y Returns: DsaPublicKey: An instance of DsaPublicKey """ return cls( key=_DSA.DSAPublicNumbers( y=y, parameter_numbers=_DSA.DSAParameterNumbers(p=p, q=q, g=g) ).public_key() )
Methods
def verify(self, data: bytes, signature: bytes) ‑> None
-
Verifies a signature
Args
data
:bytes
- The data to verify
signature
:bytes
- The signature to verify
Raises
Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
Expand source code
def verify(self, data: bytes, signature: bytes) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify Raises: Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: return self.key.verify(signature, data, _HASHES.SHA1()) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Inherited members
class EcdsaCurves (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
ECDSA Curves
Values
P256 P384 P521
Expand source code
class EcdsaCurves(Enum): """ ECDSA Curves Values: P256 P384 P521 """ P256 = _ECDSA.SECP256R1 P384 = _ECDSA.SECP384R1 P521 = _ECDSA.SECP521R1
Ancestors
- enum.Enum
Class variables
var P256
var P384
var P521
class EcdsaPrivateKey (key: cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey)
-
Class for holding ECDSA private keys
Expand source code
class EcdsaPrivateKey(PrivateKey): """ Class for holding ECDSA private keys """ def __init__(self, key: _ECDSA.EllipticCurvePrivateKey): super().__init__( key=key, public_key=EcdsaPublicKey(key.public_key()), private_numbers=key.private_numbers(), ) @classmethod # pylint: disable=invalid-name def from_numbers( cls, curve: Union[str, _ECDSA.EllipticCurve], x: int, y: int, private_value: int ): """ Creates a new EcdsaPrivateKey object from parameters and public/private numbers Args: curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key x (int): The affine X component of the public point y (int): The affine Y component of the public point private_value (int): The private value Returns: _type_: _description_ """ if not isinstance(curve, _ECDSA.EllipticCurve) and curve not in ECDSA_HASHES: raise _EX.InvalidCurveException( f"Invalid curve, must be one of {', '.join(ECDSA_HASHES.keys())}" ) if isinstance(curve, _ECDSA.EllipticCurve): curve = curve.name return cls( key=_ECDSA.EllipticCurvePrivateNumbers( public_numbers=_ECDSA.EllipticCurvePublicNumbers( curve=getattr(_ECDSA, curve.upper())(), x=x, y=y, ), private_value=private_value, ).private_key() ) @classmethod def generate(cls, curve: EcdsaCurves = EcdsaCurves.P521): """ Generate a new ECDSA private key Args: curve (EcdsaCurves): Which curve to use. Default secp521r1 Returns: EcdsaPrivateKey: An instance of EcdsaPrivateKey """ return cls.from_class(_ECDSA.generate_private_key(curve=curve.value)) def sign(self, data: bytes): """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign Returns: bytes: The signature bytes """ curve_hash = ECDSA_HASHES[self.key.curve.name]() return self.key.sign(data, _ECDSA.ECDSA(curve_hash))
Ancestors
Static methods
def from_numbers(curve: Union[str, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve], x: int, y: int, private_value: int)
-
Creates a new EcdsaPrivateKey object from parameters and public/private numbers
Args
- curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key
x
:int
- The affine X component of the public point
y
:int
- The affine Y component of the public point
private_value
:int
- The private value
Returns
_type_
- description
Expand source code
@classmethod # pylint: disable=invalid-name def from_numbers( cls, curve: Union[str, _ECDSA.EllipticCurve], x: int, y: int, private_value: int ): """ Creates a new EcdsaPrivateKey object from parameters and public/private numbers Args: curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key x (int): The affine X component of the public point y (int): The affine Y component of the public point private_value (int): The private value Returns: _type_: _description_ """ if not isinstance(curve, _ECDSA.EllipticCurve) and curve not in ECDSA_HASHES: raise _EX.InvalidCurveException( f"Invalid curve, must be one of {', '.join(ECDSA_HASHES.keys())}" ) if isinstance(curve, _ECDSA.EllipticCurve): curve = curve.name return cls( key=_ECDSA.EllipticCurvePrivateNumbers( public_numbers=_ECDSA.EllipticCurvePublicNumbers( curve=getattr(_ECDSA, curve.upper())(), x=x, y=y, ), private_value=private_value, ).private_key() )
def generate(curve: EcdsaCurves = EcdsaCurves.P521)
-
Generate a new ECDSA private key
Args
curve
:EcdsaCurves
- Which curve to use. Default secp521r1
Returns
EcdsaPrivateKey
- An instance of EcdsaPrivateKey
Expand source code
@classmethod def generate(cls, curve: EcdsaCurves = EcdsaCurves.P521): """ Generate a new ECDSA private key Args: curve (EcdsaCurves): Which curve to use. Default secp521r1 Returns: EcdsaPrivateKey: An instance of EcdsaPrivateKey """ return cls.from_class(_ECDSA.generate_private_key(curve=curve.value))
Methods
def sign(self, data: bytes)
-
Signs a block of data and returns the signature
Args
data
:bytes
- Block of byte data to sign
Returns
bytes
- The signature bytes
Expand source code
def sign(self, data: bytes): """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign Returns: bytes: The signature bytes """ curve_hash = ECDSA_HASHES[self.key.curve.name]() return self.key.sign(data, _ECDSA.ECDSA(curve_hash))
Inherited members
class EcdsaPublicKey (key: cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None)
-
Class for holding ECDSA public keys
Expand source code
class EcdsaPublicKey(PublicKey): """ Class for holding ECDSA public keys """ def __init__( self, key: _ECDSA.EllipticCurvePublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None, ): super().__init__( key=key, comment=comment, key_type=key_type, public_numbers=key.public_numbers(), serialized=serialized, ) @classmethod # pylint: disable=invalid-name def from_numbers( cls, curve: Union[str, _ECDSA.EllipticCurve], x: int, y: int ) -> "EcdsaPublicKey": """ Create an ECDSA public key from public numbers and parameters Args: curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key x (int): The affine X component of the public point y (int): The affine Y component of the public point Returns: EcdsaPublicKey: An instance of EcdsaPublicKey """ if not isinstance(curve, _ECDSA.EllipticCurve) and curve not in ECDSA_HASHES: raise _EX.InvalidCurveException( f"Invalid curve, must be one of {', '.join(ECDSA_HASHES.keys())}" ) if isinstance(curve, _ECDSA.EllipticCurve): curve = curve.name return cls( key=_ECDSA.EllipticCurvePublicNumbers( curve=getattr(_ECDSA, curve.upper())(), x=x, y=y, ).public_key() ) def verify(self, data: bytes, signature: bytes) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify Raises: Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: curve_hash = ECDSA_HASHES[self.key.curve.name]() return self.key.verify(signature, data, _ECDSA.ECDSA(curve_hash)) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Ancestors
Static methods
def from_numbers(curve: Union[str, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve], x: int, y: int) ‑> EcdsaPublicKey
-
Create an ECDSA public key from public numbers and parameters
Args
- curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key
x
:int
- The affine X component of the public point
y
:int
- The affine Y component of the public point
Returns
EcdsaPublicKey
- An instance of EcdsaPublicKey
Expand source code
@classmethod # pylint: disable=invalid-name def from_numbers( cls, curve: Union[str, _ECDSA.EllipticCurve], x: int, y: int ) -> "EcdsaPublicKey": """ Create an ECDSA public key from public numbers and parameters Args: curve Union[str, _ECDSA.EllipticCurve]: Curve used by the key x (int): The affine X component of the public point y (int): The affine Y component of the public point Returns: EcdsaPublicKey: An instance of EcdsaPublicKey """ if not isinstance(curve, _ECDSA.EllipticCurve) and curve not in ECDSA_HASHES: raise _EX.InvalidCurveException( f"Invalid curve, must be one of {', '.join(ECDSA_HASHES.keys())}" ) if isinstance(curve, _ECDSA.EllipticCurve): curve = curve.name return cls( key=_ECDSA.EllipticCurvePublicNumbers( curve=getattr(_ECDSA, curve.upper())(), x=x, y=y, ).public_key() )
Methods
def verify(self, data: bytes, signature: bytes) ‑> None
-
Verifies a signature
Args
data
:bytes
- The data to verify
signature
:bytes
- The signature to verify
Raises
Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
Expand source code
def verify(self, data: bytes, signature: bytes) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify Raises: Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: curve_hash = ECDSA_HASHES[self.key.curve.name]() return self.key.verify(signature, data, _ECDSA.ECDSA(curve_hash)) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Inherited members
class Ed25519PrivateKey (key: cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey)
-
Class for holding ED25519 private keys
Expand source code
class Ed25519PrivateKey(PrivateKey): """ Class for holding ED25519 private keys """ def __init__(self, key: _ED25519.Ed25519PrivateKey): super().__init__(key=key, public_key=Ed25519PublicKey(key.public_key())) @classmethod def from_raw_bytes(cls, raw_bytes: bytes) -> "Ed25519PrivateKey": """ Load an ED25519 private key from raw bytes Args: raw_bytes (bytes): The raw bytes of the key Returns: Ed25519PrivateKey: Instance of Ed25519PrivateKey """ return cls.from_class( _ED25519.Ed25519PrivateKey.from_private_bytes(data=raw_bytes) ) @classmethod def generate(cls) -> "Ed25519PrivateKey": """ Generates a new ED25519 Private Key Returns: Ed25519PrivateKey: Instance of Ed25519PrivateKey """ return cls.from_class(_ED25519.Ed25519PrivateKey.generate()) def raw_bytes(self) -> bytes: """ Export the raw key bytes Returns: bytes: The key bytes """ return self.key.private_bytes( encoding=_SERIALIZATION.Encoding.Raw, format=_SERIALIZATION.PrivateFormat.Raw, encryption_algorithm=_SERIALIZATION.NoEncryption(), ) def sign(self, data: bytes): """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign Returns: bytes: The signature bytes """ return self.key.sign(data)
Ancestors
Static methods
def from_raw_bytes(raw_bytes: bytes) ‑> Ed25519PrivateKey
-
Load an ED25519 private key from raw bytes
Args
raw_bytes
:bytes
- The raw bytes of the key
Returns
Ed25519PrivateKey
- Instance of Ed25519PrivateKey
Expand source code
@classmethod def from_raw_bytes(cls, raw_bytes: bytes) -> "Ed25519PrivateKey": """ Load an ED25519 private key from raw bytes Args: raw_bytes (bytes): The raw bytes of the key Returns: Ed25519PrivateKey: Instance of Ed25519PrivateKey """ return cls.from_class( _ED25519.Ed25519PrivateKey.from_private_bytes(data=raw_bytes) )
def generate() ‑> Ed25519PrivateKey
-
Expand source code
@classmethod def generate(cls) -> "Ed25519PrivateKey": """ Generates a new ED25519 Private Key Returns: Ed25519PrivateKey: Instance of Ed25519PrivateKey """ return cls.from_class(_ED25519.Ed25519PrivateKey.generate())
Methods
def raw_bytes(self) ‑> bytes
-
Export the raw key bytes
Returns
bytes
- The key bytes
Expand source code
def raw_bytes(self) -> bytes: """ Export the raw key bytes Returns: bytes: The key bytes """ return self.key.private_bytes( encoding=_SERIALIZATION.Encoding.Raw, format=_SERIALIZATION.PrivateFormat.Raw, encryption_algorithm=_SERIALIZATION.NoEncryption(), )
def sign(self, data: bytes)
-
Signs a block of data and returns the signature
Args
data
:bytes
- Block of byte data to sign
Returns
bytes
- The signature bytes
Expand source code
def sign(self, data: bytes): """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign Returns: bytes: The signature bytes """ return self.key.sign(data)
Inherited members
class Ed25519PublicKey (key: cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None)
-
Class for holding ED25519 public keys
Expand source code
class Ed25519PublicKey(PublicKey): """ Class for holding ED25519 public keys """ def __init__( self, key: _ED25519.Ed25519PublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None, ): super().__init__( key=key, comment=comment, key_type=key_type, serialized=serialized ) @classmethod def from_raw_bytes(cls, raw_bytes: bytes) -> "Ed25519PublicKey": """ Load an ED25519 public key from raw bytes Args: raw_bytes (bytes): The raw bytes of the key Returns: Ed25519PublicKey: Instance of Ed25519PublicKey """ if b"ssh-ed25519" in raw_bytes: id_length = unpack(">I", raw_bytes[:4])[0] + 8 raw_bytes = raw_bytes[id_length:] return cls.from_class( _ED25519.Ed25519PublicKey.from_public_bytes(data=raw_bytes) ) def verify(self, data: bytes, signature: bytes) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify Raises: Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: return self.key.verify(signature, data) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Ancestors
Static methods
def from_raw_bytes(raw_bytes: bytes) ‑> Ed25519PublicKey
-
Load an ED25519 public key from raw bytes
Args
raw_bytes
:bytes
- The raw bytes of the key
Returns
Ed25519PublicKey
- Instance of Ed25519PublicKey
Expand source code
@classmethod def from_raw_bytes(cls, raw_bytes: bytes) -> "Ed25519PublicKey": """ Load an ED25519 public key from raw bytes Args: raw_bytes (bytes): The raw bytes of the key Returns: Ed25519PublicKey: Instance of Ed25519PublicKey """ if b"ssh-ed25519" in raw_bytes: id_length = unpack(">I", raw_bytes[:4])[0] + 8 raw_bytes = raw_bytes[id_length:] return cls.from_class( _ED25519.Ed25519PublicKey.from_public_bytes(data=raw_bytes) )
Methods
def verify(self, data: bytes, signature: bytes) ‑> None
-
Verifies a signature
Args
data
:bytes
- The data to verify
signature
:bytes
- The signature to verify
Raises
Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
Expand source code
def verify(self, data: bytes, signature: bytes) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify Raises: Raises an sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: return self.key.verify(signature, data) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Inherited members
class FingerprintHashes (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
Fingerprint hashes
Values
MD5 SHA256 SHA512
Expand source code
class FingerprintHashes(Enum): """ Fingerprint hashes Values: MD5 SHA256 SHA512 """ MD5 = _FP_MD5 SHA256 = _FP_SHA256 SHA512 = _FP_SHA512
Ancestors
- enum.Enum
Methods
def MD5(data: bytes, prefix: bool = True) ‑> str
-
Returns an MD5 fingerprint of the given data.
Args
data
:bytes
- The data to fingerprint
prefix
:bool
, optional- Whether to prefix the fingerprint with MD5:
Returns
str
- The fingerprint (OpenSSH style MD5:xx:xx:xx…)
Expand source code
def md5_fingerprint(data: bytes, prefix: bool = True) -> str: """ Returns an MD5 fingerprint of the given data. Args: data (bytes): The data to fingerprint prefix (bool, optional): Whether to prefix the fingerprint with MD5: Returns: str: The fingerprint (OpenSSH style MD5:xx:xx:xx...) """ digest = hl.md5(data).hexdigest() return ("MD5:" if prefix else "") + ":".join( a + b for a, b in zip(digest[::2], digest[1::2]) )
def SHA256(data: bytes, prefix: bool = True) ‑> str
-
Returns a SHA256 fingerprint of the given data.
Args
data
:bytes
- The data to fingerprint
prefix
:bool
, optional- Whether to prefix the fingerprint with SHA256:
Returns
str
- The fingerprint (OpenSSH style SHA256:xx:xx:xx…)
Expand source code
def sha256_fingerprint(data: bytes, prefix: bool = True) -> str: """ Returns a SHA256 fingerprint of the given data. Args: data (bytes): The data to fingerprint prefix (bool, optional): Whether to prefix the fingerprint with SHA256: Returns: str: The fingerprint (OpenSSH style SHA256:xx:xx:xx...) """ digest = hl.sha256(data).digest() return ("SHA256:" if prefix else "") + b64encode(digest).replace(b"=", b"").decode( "utf-8" )
def SHA512(data: bytes, prefix: bool = True) ‑> str
-
Returns a SHA512 fingerprint of the given data.
Args
data
:bytes
- The data to fingerprint
prefix
:bool
, optional- Whether to prefix the fingerprint with SHA512:
Returns
str
- The fingerprint (OpenSSH style SHA256:xx:xx:xx…)
Expand source code
def sha512_fingerprint(data: bytes, prefix: bool = True) -> str: """ Returns a SHA512 fingerprint of the given data. Args: data (bytes): The data to fingerprint prefix (bool, optional): Whether to prefix the fingerprint with SHA512: Returns: str: The fingerprint (OpenSSH style SHA256:xx:xx:xx...) """ digest = hl.sha512(data).digest() return ("SHA512:" if prefix else "") + b64encode(digest).replace(b"=", b"").decode( "utf-8" )
class PrivateKey (key: Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey, cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey], public_key: PublicKey, **kwargs)
-
Class for handling SSH Private keys
Expand source code
class PrivateKey: """ Class for handling SSH Private keys """ def __init__(self, key: PrivkeyClasses, public_key: PublicKey, **kwargs) -> None: self.key = key self.public_key = public_key self.private_numbers = kwargs.get("private_numbers", None) self.export_opts = { "encoding": _SERIALIZATION.Encoding.PEM, "format": _SERIALIZATION.PrivateFormat.OpenSSH, "encryption": _SERIALIZATION.BestAvailableEncryption, } @classmethod def from_class(cls, key_class: PrivkeyClasses) -> "PrivateKey": """ Import an SSH Private key from a cryptography key class Args: key_class (PrivkeyClasses): A cryptography private key class Raises: _EX.InvalidKeyException: Invalid private key Returns: PrivateKey: One of the PrivateKey child classes """ try: return globals()[PRIVKEY_MAP[key_class.__class__]](key_class) except KeyError: raise _EX.InvalidKeyException("Invalid private key") from KeyError @classmethod def from_string( cls, key_data: Union[str, bytes], password: Union[str, bytes] = None, encoding: str = "utf-8", ) -> "PrivateKey": """ Loads an SSH private key from a string containing the key data Args: key_data (Union[str, bytes]): The string containing the key data password (str, optional): The password for the private key. Defaults to None. encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. Returns: PrivateKey: Any of the PrivateKey child classes """ key_data, password = ensure_bytestring((key_data, password), encoding=encoding) private_key = _SERIALIZATION.load_ssh_private_key(key_data, password=password) return cls.from_class(private_key) @classmethod def from_file( cls, path: str, password: Union[str, bytes] = None, ) -> "PrivateKey": """ Loads an SSH private key from a file Args: path (str): The path to the file password (str, optional): The encryption password. Defaults to None. encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. Returns: PrivateKey: Any of the PrivateKey child classes """ with open(path, "rb") as key_file: return cls.from_string(key_file.read(), password) def get_fingerprint( self, hash_method: FingerprintHashes = FingerprintHashes.SHA256 ) -> str: """ Generates a fingerprint of the private key Args: hash_method (FingerprintHashes, optional): Type of hash. Defaults to SHA256. Returns: str: The hash of the private key """ return self.public_key.get_fingerprint(hash_method) def to_bytes(self, password: Union[str, bytes] = None) -> bytes: """ Exports the private key to a byte string Args: password (Union[str, bytes], optional): The password to set for the key. Defaults to None. Returns: bytes: The private key in PEM format """ password = ensure_bytestring(password) encryption = _SERIALIZATION.NoEncryption() if password is not None: encryption = self.export_opts["encryption"](password) return self.key.private_bytes( self.export_opts["encoding"], self.export_opts["format"], encryption ) def to_string( self, password: Union[str, bytes] = None, encoding: str = "utf-8" ) -> str: """ Exports the private key to a string Args: password (Union[str, bytes], optional): The password to set for the key. Defaults to None. encoding (str, optional): The encoding of the string. Defaults to 'utf-8'. Returns: bytes: The private key in PEM format """ return ensure_string(self.to_bytes(password), encoding) def to_file( self, path: str, password: Union[str, bytes] = None, encoding: str = "utf-8" ) -> None: """ Exports the private key to a file Args: password (Union[str, bytes], optional): The password to set for the key. Defaults to None. Returns: bytes: The private key in PEM format """ with open(path, "w", encoding=encoding) as key_file: key_file.write(self.to_string(password, encoding))
Subclasses
Static methods
def from_class(key_class: Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey, cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey]) ‑> PrivateKey
-
Import an SSH Private key from a cryptography key class
Args
key_class
:PrivkeyClasses
- A cryptography private key class
Raises
_EX.InvalidKeyException
- Invalid private key
Returns
PrivateKey
- One of the PrivateKey child classes
Expand source code
@classmethod def from_class(cls, key_class: PrivkeyClasses) -> "PrivateKey": """ Import an SSH Private key from a cryptography key class Args: key_class (PrivkeyClasses): A cryptography private key class Raises: _EX.InvalidKeyException: Invalid private key Returns: PrivateKey: One of the PrivateKey child classes """ try: return globals()[PRIVKEY_MAP[key_class.__class__]](key_class) except KeyError: raise _EX.InvalidKeyException("Invalid private key") from KeyError
def from_file(path: str, password: Union[str, bytes] = None) ‑> PrivateKey
-
Loads an SSH private key from a file
Args
path
:str
- The path to the file
password
:str
, optional- The encryption password. Defaults to None.
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
Returns
PrivateKey
- Any of the PrivateKey child classes
Expand source code
@classmethod def from_file( cls, path: str, password: Union[str, bytes] = None, ) -> "PrivateKey": """ Loads an SSH private key from a file Args: path (str): The path to the file password (str, optional): The encryption password. Defaults to None. encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. Returns: PrivateKey: Any of the PrivateKey child classes """ with open(path, "rb") as key_file: return cls.from_string(key_file.read(), password)
def from_string(key_data: Union[str, bytes], password: Union[str, bytes] = None, encoding: str = 'utf-8') ‑> PrivateKey
-
Loads an SSH private key from a string containing the key data
Args
key_data
:Union[str, bytes]
- The string containing the key data
password
:str
, optional- The password for the private key. Defaults to None.
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
Returns
PrivateKey
- Any of the PrivateKey child classes
Expand source code
@classmethod def from_string( cls, key_data: Union[str, bytes], password: Union[str, bytes] = None, encoding: str = "utf-8", ) -> "PrivateKey": """ Loads an SSH private key from a string containing the key data Args: key_data (Union[str, bytes]): The string containing the key data password (str, optional): The password for the private key. Defaults to None. encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. Returns: PrivateKey: Any of the PrivateKey child classes """ key_data, password = ensure_bytestring((key_data, password), encoding=encoding) private_key = _SERIALIZATION.load_ssh_private_key(key_data, password=password) return cls.from_class(private_key)
Methods
def get_fingerprint(self, hash_method: FingerprintHashes = <function sha256_fingerprint>) ‑> str
-
Generates a fingerprint of the private key
Args
hash_method
:FingerprintHashes
, optional- Type of hash. Defaults to SHA256.
Returns
str
- The hash of the private key
Expand source code
def get_fingerprint( self, hash_method: FingerprintHashes = FingerprintHashes.SHA256 ) -> str: """ Generates a fingerprint of the private key Args: hash_method (FingerprintHashes, optional): Type of hash. Defaults to SHA256. Returns: str: The hash of the private key """ return self.public_key.get_fingerprint(hash_method)
def to_bytes(self, password: Union[str, bytes] = None) ‑> bytes
-
Exports the private key to a byte string
Args
password
:Union[str, bytes]
, optional- The password to set for the key. Defaults to None.
Returns
bytes
- The private key in PEM format
Expand source code
def to_bytes(self, password: Union[str, bytes] = None) -> bytes: """ Exports the private key to a byte string Args: password (Union[str, bytes], optional): The password to set for the key. Defaults to None. Returns: bytes: The private key in PEM format """ password = ensure_bytestring(password) encryption = _SERIALIZATION.NoEncryption() if password is not None: encryption = self.export_opts["encryption"](password) return self.key.private_bytes( self.export_opts["encoding"], self.export_opts["format"], encryption )
def to_file(self, path: str, password: Union[str, bytes] = None, encoding: str = 'utf-8') ‑> None
-
Exports the private key to a file
Args
password
:Union[str, bytes]
, optional- The password to set for the key. Defaults to None.
Returns
bytes
- The private key in PEM format
Expand source code
def to_file( self, path: str, password: Union[str, bytes] = None, encoding: str = "utf-8" ) -> None: """ Exports the private key to a file Args: password (Union[str, bytes], optional): The password to set for the key. Defaults to None. Returns: bytes: The private key in PEM format """ with open(path, "w", encoding=encoding) as key_file: key_file.write(self.to_string(password, encoding))
def to_string(self, password: Union[str, bytes] = None, encoding: str = 'utf-8') ‑> str
-
Exports the private key to a string
Args
password
:Union[str, bytes]
, optional- The password to set for the key. Defaults to None.
encoding
:str
, optional- The encoding of the string. Defaults to 'utf-8'.
Returns
bytes
- The private key in PEM format
Expand source code
def to_string( self, password: Union[str, bytes] = None, encoding: str = "utf-8" ) -> str: """ Exports the private key to a string Args: password (Union[str, bytes], optional): The password to set for the key. Defaults to None. encoding (str, optional): The encoding of the string. Defaults to 'utf-8'. Returns: bytes: The private key in PEM format """ return ensure_string(self.to_bytes(password), encoding)
class PublicKey (key: Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey, cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePrivateKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey] = None, comment: Union[str, bytes] = '', **kwargs)
-
Class for handling SSH public keys
Expand source code
class PublicKey: """ Class for handling SSH public keys """ def __init__( self, key: PrivkeyClasses = None, comment: Union[str, bytes] = "", **kwargs ) -> None: self.key = key self.comment = comment self.public_numbers = kwargs.get("public_numbers", None) self.key_type = kwargs.get("key_type", None) self.serialized = kwargs.get("serialized", None) self.export_opts = [ _SERIALIZATION.Encoding.OpenSSH, _SERIALIZATION.PublicFormat.OpenSSH, ] # Ensure comment is not None self.comment = nullsafe_getattr(self, "comment", "") @classmethod def from_class( cls, key_class: PubkeyClasses, comment: Union[str, bytes] = "", key_type: Union[str, bytes] = None, ) -> "PublicKey": """ Creates a new SSH Public key from a cryptography class Args: key_class (PubkeyClasses): The cryptography class containing the public key comment (Union[str, bytes], optional): Comment to add to the key. Defaults to None. key_type (Union[str, bytes], optional): Manually specify the key type. Defaults to None. Raises: _EX.InvalidKeyException: The key you are trying to load is invalid Returns: PublicKey: Any of the PublicKey child classes """ try: return globals()[PUBKEY_MAP[key_class.__class__]]( key_class, comment, key_type ) except KeyError: raise _EX.InvalidKeyException("Invalid public key") from KeyError @classmethod def from_string( cls, data: Union[str, bytes], encoding: str = "utf-8" ) -> "PublicKey": """ Loads an SSH public key from a string containing the data in OpenSSH format (SubjectPublickeyInfo) Args: data (Union[str, bytes]): The string or byte data containing the key Returns: PublicKey: Any of the PublicKey child classes """ split = ensure_bytestring(data, encoding).split(b" ") comment = None if len(split) > 2: comment = split[2] return cls.from_class( key_class=_SERIALIZATION.load_ssh_public_key(b" ".join(split[:2])), comment=comment, ) @classmethod def from_file(cls, path: str) -> "PublicKey": """ Loads an SSH Public key from a file Args: path (str): The path to the file Returns: PublicKey: Any of the PublicKey child classes """ with open(path, "rb") as file: data = file.read() return cls.from_string(data) @classmethod # pylint: disable=broad-except def from_bytes(cls, data: bytes) -> "PublicKey": """ Loads a public key from byte data Args: data (bytes): The bytestring containing the public key Raises: _EX.InvalidKeyException: Invalid data input Returns: PublicKey: PublicKey subclass depending on the key type """ for key_class in PUBKEY_MAP.values(): try: key = globals()[key_class].from_raw_bytes(data) return key except Exception: pass raise _EX.InvalidKeyException("Invalid public key") def get_fingerprint( self, hash_method: FingerprintHashes = FingerprintHashes.SHA256 ) -> str: """ Generates a fingerprint of the public key Args: hash_method (FingerprintHashes, optional): Type of hash. Defaults to SHA256. Returns: str: The hash of the public key """ return hash_method(self.raw_bytes()) def serialize(self) -> bytes: """ Serialize the key for storage in file or string Returns: bytes: The serialized key in OpenSSH format """ return self.key.public_bytes(*self.export_opts) def raw_bytes(self) -> bytes: """ Export the public key to a raw byte string Returns: bytes: The raw certificate bytes """ return b64decode(self.serialize().split(b" ")[1]) def to_string(self, encoding: str = "utf-8") -> str: """ Export the public key as a string Returns: str: The public key in OpenSSH format encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. """ return " ".join( [ ensure_string(self.serialize(), encoding), ensure_string(nullsafe_getattr(self, "comment", ""), encoding), ] ) def to_file(self, path: str, encoding: str = "utf-8") -> None: """ Export the public key to a file Args: path (str): The path of the file encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. """ with open(path, "w", encoding=encoding) as pubkey_file: pubkey_file.write(self.to_string())
Subclasses
Static methods
def from_bytes(data: bytes) ‑> PublicKey
-
Loads a public key from byte data
Args
data
:bytes
- The bytestring containing the public key
Raises
_EX.InvalidKeyException
- Invalid data input
Returns
PublicKey
- PublicKey subclass depending on the key type
Expand source code
@classmethod # pylint: disable=broad-except def from_bytes(cls, data: bytes) -> "PublicKey": """ Loads a public key from byte data Args: data (bytes): The bytestring containing the public key Raises: _EX.InvalidKeyException: Invalid data input Returns: PublicKey: PublicKey subclass depending on the key type """ for key_class in PUBKEY_MAP.values(): try: key = globals()[key_class].from_raw_bytes(data) return key except Exception: pass raise _EX.InvalidKeyException("Invalid public key")
def from_class(key_class: Union[cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey, cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey], comment: Union[str, bytes] = '', key_type: Union[str, bytes] = None) ‑> PublicKey
-
Creates a new SSH Public key from a cryptography class
Args
key_class
:PubkeyClasses
- The cryptography class containing the public key
comment
:Union[str, bytes]
, optional- Comment to add to the key. Defaults to None.
key_type
:Union[str, bytes]
, optional- Manually specify the key type. Defaults to None.
Raises
_EX.InvalidKeyException
- The key you are trying to load is invalid
Returns
PublicKey
- Any of the PublicKey child classes
Expand source code
@classmethod def from_class( cls, key_class: PubkeyClasses, comment: Union[str, bytes] = "", key_type: Union[str, bytes] = None, ) -> "PublicKey": """ Creates a new SSH Public key from a cryptography class Args: key_class (PubkeyClasses): The cryptography class containing the public key comment (Union[str, bytes], optional): Comment to add to the key. Defaults to None. key_type (Union[str, bytes], optional): Manually specify the key type. Defaults to None. Raises: _EX.InvalidKeyException: The key you are trying to load is invalid Returns: PublicKey: Any of the PublicKey child classes """ try: return globals()[PUBKEY_MAP[key_class.__class__]]( key_class, comment, key_type ) except KeyError: raise _EX.InvalidKeyException("Invalid public key") from KeyError
def from_file(path: str) ‑> PublicKey
-
Loads an SSH Public key from a file
Args
path
:str
- The path to the file
Returns
PublicKey
- Any of the PublicKey child classes
Expand source code
@classmethod def from_file(cls, path: str) -> "PublicKey": """ Loads an SSH Public key from a file Args: path (str): The path to the file Returns: PublicKey: Any of the PublicKey child classes """ with open(path, "rb") as file: data = file.read() return cls.from_string(data)
def from_string(data: Union[str, bytes], encoding: str = 'utf-8') ‑> PublicKey
-
Loads an SSH public key from a string containing the data in OpenSSH format (SubjectPublickeyInfo)
Args
data
:Union[str, bytes]
- The string or byte data containing the key
Returns
PublicKey
- Any of the PublicKey child classes
Expand source code
@classmethod def from_string( cls, data: Union[str, bytes], encoding: str = "utf-8" ) -> "PublicKey": """ Loads an SSH public key from a string containing the data in OpenSSH format (SubjectPublickeyInfo) Args: data (Union[str, bytes]): The string or byte data containing the key Returns: PublicKey: Any of the PublicKey child classes """ split = ensure_bytestring(data, encoding).split(b" ") comment = None if len(split) > 2: comment = split[2] return cls.from_class( key_class=_SERIALIZATION.load_ssh_public_key(b" ".join(split[:2])), comment=comment, )
Methods
def get_fingerprint(self, hash_method: FingerprintHashes = <function sha256_fingerprint>) ‑> str
-
Generates a fingerprint of the public key
Args
hash_method
:FingerprintHashes
, optional- Type of hash. Defaults to SHA256.
Returns
str
- The hash of the public key
Expand source code
def get_fingerprint( self, hash_method: FingerprintHashes = FingerprintHashes.SHA256 ) -> str: """ Generates a fingerprint of the public key Args: hash_method (FingerprintHashes, optional): Type of hash. Defaults to SHA256. Returns: str: The hash of the public key """ return hash_method(self.raw_bytes())
def raw_bytes(self) ‑> bytes
-
Export the public key to a raw byte string
Returns
bytes
- The raw certificate bytes
Expand source code
def raw_bytes(self) -> bytes: """ Export the public key to a raw byte string Returns: bytes: The raw certificate bytes """ return b64decode(self.serialize().split(b" ")[1])
def serialize(self) ‑> bytes
-
Serialize the key for storage in file or string
Returns
bytes
- The serialized key in OpenSSH format
Expand source code
def serialize(self) -> bytes: """ Serialize the key for storage in file or string Returns: bytes: The serialized key in OpenSSH format """ return self.key.public_bytes(*self.export_opts)
def to_file(self, path: str, encoding: str = 'utf-8') ‑> None
-
Export the public key to a file
Args
path
:str
- The path of the file
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
Expand source code
def to_file(self, path: str, encoding: str = "utf-8") -> None: """ Export the public key to a file Args: path (str): The path of the file encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. """ with open(path, "w", encoding=encoding) as pubkey_file: pubkey_file.write(self.to_string())
def to_string(self, encoding: str = 'utf-8') ‑> str
-
Export the public key as a string
Returns
str
- The public key in OpenSSH format
encoding(str, optional): The encoding of the file. Defaults to 'utf-8'.
Expand source code
def to_string(self, encoding: str = "utf-8") -> str: """ Export the public key as a string Returns: str: The public key in OpenSSH format encoding(str, optional): The encoding of the file. Defaults to 'utf-8'. """ return " ".join( [ ensure_string(self.serialize(), encoding), ensure_string(nullsafe_getattr(self, "comment", ""), encoding), ] )
class RsaAlgs (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
RSA Algorithms
Values
SHA1 SHA256 SHA512
Expand source code
class RsaAlgs(Enum): """ RSA Algorithms Values: SHA1 SHA256 SHA512 """ SHA1 = ("ssh-rsa", _HASHES.SHA1) SHA256 = ("rsa-sha2-256", _HASHES.SHA256) SHA512 = ("rsa-sha2-512", _HASHES.SHA512)
Ancestors
- enum.Enum
Class variables
var SHA1
var SHA256
var SHA512
class RsaPrivateKey (key: cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey)
-
Class for holding RSA private keys
Expand source code
class RsaPrivateKey(PrivateKey): """ Class for holding RSA private keys """ def __init__(self, key: _RSA.RSAPrivateKey): super().__init__( key=key, public_key=RsaPublicKey(key.public_key()), private_numbers=key.private_numbers(), ) @classmethod # pylint: disable=invalid-name,too-many-arguments def from_numbers( cls, e: int, n: int, d: int, p: int = None, q: int = None, dmp1: int = None, dmq1: int = None, iqmp: int = None, ) -> "RsaPrivateKey": """ Load an RSA private key from numbers Args: n (int): The public modulus (n) e (int): The public exponent (e) d (int): The private exponent (d) p (int, optional): One of two primes (p) composing the public modulus. Automatically generates if not provided. q (int, optional): One of two primes (q) composing the public modulus. Automatically generates if not provided dmp1 (int, optional): Chinese remainder theorem coefficient to speed up operations Calculated as d mod (p-1) Automatically generates if not provided dmq1 (int, optional): Chinese remainder theorem coefficient to speed up operations Calculated as d mod(q-1) Automatically generates if not provided iqmp (int, optional): Chinese remainder theorem coefficient to speed up operations Calculated as q^-1 mod p Automatically generates if not provided Returns: RsaPrivateKey: An instance of RsaPrivateKey """ if None in (p, q): p, q = _RSA.rsa_recover_prime_factors(n, e, d) dmp1 = _RSA.rsa_crt_dmp1(d, p) if dmp1 is None else dmp1 dmq1 = _RSA.rsa_crt_dmq1(d, q) if dmq1 is None else dmq1 iqmp = _RSA.rsa_crt_iqmp(p, q) if iqmp is None else iqmp return cls( key=_RSA.RSAPrivateNumbers( public_numbers=_RSA.RSAPublicNumbers(e, n), p=p, q=q, d=d, dmp1=_RSA.rsa_crt_dmp1(d, p), dmq1=_RSA.rsa_crt_dmq1(d, q), iqmp=_RSA.rsa_crt_iqmp(p, q), ).private_key() ) @classmethod def generate( cls, key_size: int = 4096, public_exponent: int = 65537 ) -> "RsaPrivateKey": """ Generates a new RSA private key Args: key_size (int, optional): The number of bytes for the key. Defaults to 4096. public_exponent (int, optional): The public exponent to use. Defaults to 65537. Returns: RsaPrivateKey: Instance of RsaPrivateKey """ return cls.from_class( _RSA.generate_private_key( public_exponent=public_exponent, key_size=key_size ) ) def sign(self, data: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512) -> bytes: """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign hash_alg (RsaAlgs, optional): Algorithm to use for hashing. Defaults to SHA512. Returns: bytes: The signature bytes """ return self.key.sign(data, _PADDING.PKCS1v15(), hash_alg.value[1]())
Ancestors
Static methods
def from_numbers(e: int, n: int, d: int, p: int = None, q: int = None, dmp1: int = None, dmq1: int = None, iqmp: int = None) ‑> RsaPrivateKey
-
Load an RSA private key from numbers
Args
n
:int
- The public modulus (n)
e
:int
- The public exponent (e)
d
:int
- The private exponent (d)
p
:int
, optional- One of two primes (p) composing the public modulus. Automatically generates if not provided.
q
:int
, optional- One of two primes (q) composing the public modulus. Automatically generates if not provided
dmp1
:int
, optional- Chinese remainder theorem coefficient to speed up operations Calculated as d mod (p-1) Automatically generates if not provided
dmq1
:int
, optional- Chinese remainder theorem coefficient to speed up operations Calculated as d mod(q-1) Automatically generates if not provided
iqmp
:int
, optional- Chinese remainder theorem coefficient to speed up operations Calculated as q^-1 mod p Automatically generates if not provided
Returns
RsaPrivateKey
- An instance of RsaPrivateKey
Expand source code
@classmethod # pylint: disable=invalid-name,too-many-arguments def from_numbers( cls, e: int, n: int, d: int, p: int = None, q: int = None, dmp1: int = None, dmq1: int = None, iqmp: int = None, ) -> "RsaPrivateKey": """ Load an RSA private key from numbers Args: n (int): The public modulus (n) e (int): The public exponent (e) d (int): The private exponent (d) p (int, optional): One of two primes (p) composing the public modulus. Automatically generates if not provided. q (int, optional): One of two primes (q) composing the public modulus. Automatically generates if not provided dmp1 (int, optional): Chinese remainder theorem coefficient to speed up operations Calculated as d mod (p-1) Automatically generates if not provided dmq1 (int, optional): Chinese remainder theorem coefficient to speed up operations Calculated as d mod(q-1) Automatically generates if not provided iqmp (int, optional): Chinese remainder theorem coefficient to speed up operations Calculated as q^-1 mod p Automatically generates if not provided Returns: RsaPrivateKey: An instance of RsaPrivateKey """ if None in (p, q): p, q = _RSA.rsa_recover_prime_factors(n, e, d) dmp1 = _RSA.rsa_crt_dmp1(d, p) if dmp1 is None else dmp1 dmq1 = _RSA.rsa_crt_dmq1(d, q) if dmq1 is None else dmq1 iqmp = _RSA.rsa_crt_iqmp(p, q) if iqmp is None else iqmp return cls( key=_RSA.RSAPrivateNumbers( public_numbers=_RSA.RSAPublicNumbers(e, n), p=p, q=q, d=d, dmp1=_RSA.rsa_crt_dmp1(d, p), dmq1=_RSA.rsa_crt_dmq1(d, q), iqmp=_RSA.rsa_crt_iqmp(p, q), ).private_key() )
def generate(key_size: int = 4096, public_exponent: int = 65537) ‑> RsaPrivateKey
-
Generates a new RSA private key
Args
key_size
:int
, optional- The number of bytes for the key. Defaults to 4096.
public_exponent
:int
, optional- The public exponent to use. Defaults to 65537.
Returns
RsaPrivateKey
- Instance of RsaPrivateKey
Expand source code
@classmethod def generate( cls, key_size: int = 4096, public_exponent: int = 65537 ) -> "RsaPrivateKey": """ Generates a new RSA private key Args: key_size (int, optional): The number of bytes for the key. Defaults to 4096. public_exponent (int, optional): The public exponent to use. Defaults to 65537. Returns: RsaPrivateKey: Instance of RsaPrivateKey """ return cls.from_class( _RSA.generate_private_key( public_exponent=public_exponent, key_size=key_size ) )
Methods
def sign(self, data: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512) ‑> bytes
-
Signs a block of data and returns the signature
Args
data
:bytes
- Block of byte data to sign
hash_alg
:RsaAlgs
, optional- Algorithm to use for hashing. Defaults to SHA512.
Returns
bytes
- The signature bytes
Expand source code
def sign(self, data: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512) -> bytes: """ Signs a block of data and returns the signature Args: data (bytes): Block of byte data to sign hash_alg (RsaAlgs, optional): Algorithm to use for hashing. Defaults to SHA512. Returns: bytes: The signature bytes """ return self.key.sign(data, _PADDING.PKCS1v15(), hash_alg.value[1]())
Inherited members
class RsaPublicKey (key: cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None)
-
Class for holding RSA public keys
Expand source code
class RsaPublicKey(PublicKey): """ Class for holding RSA public keys """ def __init__( self, key: _RSA.RSAPublicKey, comment: Union[str, bytes] = None, key_type: Union[str, bytes] = None, serialized: bytes = None, ): super().__init__( key=key, comment=comment, key_type=key_type, public_numbers=key.public_numbers(), serialized=serialized, ) @classmethod # pylint: disable=invalid-name def from_numbers(cls, e: int, n: int) -> "RsaPublicKey": """ Loads an RSA Public Key from the public numbers e and n Args: e (int): e-value n (int): n-value Returns: RsaPublicKey: _description_ """ return cls(key=_RSA.RSAPublicNumbers(e, n).public_key()) def verify( self, data: bytes, signature: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512 ) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify hash_method (HashMethods): The hash method to use Raises: Raises a sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: return self.key.verify( signature, data, _PADDING.PKCS1v15(), hash_alg.value[1]() ) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Ancestors
Static methods
def from_numbers(e: int, n: int) ‑> RsaPublicKey
-
Loads an RSA Public Key from the public numbers e and n
Args
e
:int
- e-value
n
:int
- n-value
Returns
RsaPublicKey
- description
Expand source code
@classmethod # pylint: disable=invalid-name def from_numbers(cls, e: int, n: int) -> "RsaPublicKey": """ Loads an RSA Public Key from the public numbers e and n Args: e (int): e-value n (int): n-value Returns: RsaPublicKey: _description_ """ return cls(key=_RSA.RSAPublicNumbers(e, n).public_key())
Methods
def verify(self, data: bytes, signature: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512) ‑> None
-
Verifies a signature
Args
data
:bytes
- The data to verify
signature
:bytes
- The signature to verify
hash_method
:HashMethods
- The hash method to use
Raises
Raises a sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid
Expand source code
def verify( self, data: bytes, signature: bytes, hash_alg: RsaAlgs = RsaAlgs.SHA512 ) -> None: """ Verifies a signature Args: data (bytes): The data to verify signature (bytes): The signature to verify hash_method (HashMethods): The hash method to use Raises: Raises a sshkey_tools.exceptions.InvalidSignatureException if the signature is invalid """ try: return self.key.verify( signature, data, _PADDING.PKCS1v15(), hash_alg.value[1]() ) except InvalidSignature: raise _EX.InvalidSignatureException( "The signature is invalid for the given data" ) from InvalidSignature
Inherited members