From 867dc95b2fc89e2f0643ae47b0654aa63b467d9e Mon Sep 17 00:00:00 2001 From: Lars Scheibling Date: Wed, 7 Jun 2023 12:03:04 +0000 Subject: [PATCH 1/2] Removed DSA tests from unit tests Updated requirement for cryptography --- requirements.txt | 2 +- tests/test_keypairs.py | 128 ++--------------------------------------- 2 files changed, 5 insertions(+), 125 deletions(-) diff --git a/requirements.txt b/requirements.txt index 2c27802..d7c755c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ click -cryptography<41.0.0 +cryptography bcrypt enum34 PrettyTable diff --git a/tests/test_keypairs.py b/tests/test_keypairs.py index 6b60fdb..69cc202 100644 --- a/tests/test_keypairs.py +++ b/tests/test_keypairs.py @@ -6,15 +6,12 @@ import shutil import unittest -from cryptography.hazmat.primitives.asymmetric import dsa as _DSA from cryptography.hazmat.primitives.asymmetric import ec as _EC from cryptography.hazmat.primitives.asymmetric import ed25519 as _ED25519 from cryptography.hazmat.primitives.asymmetric import rsa as _RSA import src.sshkey_tools.exceptions as _EX from src.sshkey_tools.keys import ( - DsaPrivateKey, - DsaPublicKey, EcdsaCurves, EcdsaPrivateKey, EcdsaPublicKey, @@ -30,7 +27,6 @@ class KeypairMethods(unittest.TestCase): def generateClasses(self): self.rsa_key = RsaPrivateKey.generate(2048) - self.dsa_key = DsaPrivateKey.generate() self.ecdsa_key = EcdsaPrivateKey.generate(EcdsaCurves.P256) self.ed25519_key = Ed25519PrivateKey.generate() @@ -45,9 +41,6 @@ def generateFiles(self, folder): os.system( f'ssh-keygen -t rsa -b 2048 -f tests/{folder}/rsa_key_sshkeygen -N "password" > /dev/null 2>&1' ) - os.system( - f'ssh-keygen -t dsa -b 1024 -f tests/{folder}/dsa_key_sshkeygen -N "" > /dev/null 2>&1' - ) os.system( f'ssh-keygen -t ecdsa -b 256 -f tests/{folder}/ecdsa_key_sshkeygen -N "" > /dev/null 2>&1' ) @@ -105,20 +98,20 @@ def test_fail_assertions(self): RsaPrivateKey.from_file( f"tests/{self.folder}/rsa_key_sshkeygen", "password" ), - DsaPrivateKey.from_file(f"tests/{self.folder}/dsa_key_sshkeygen"), + EcdsaPrivateKey.from_file(f"tests/{self.folder}/ecdsa_key_sshkeygen"), ) with self.assertRaises(AssertionError): self.assertEqualPublicKeys( RsaPublicKey, RsaPublicKey.from_file(f"tests/{self.folder}/rsa_key_sshkeygen.pub"), - DsaPublicKey.from_file(f"tests/{self.folder}/dsa_key_sshkeygen.pub"), + EcdsaPublicKey.from_file(f"tests/{self.folder}/ecdsa_key_sshkeygen.pub"), ) with self.assertRaises(AssertionError): self.assertEqualKeyFingerprint( f"tests/{self.folder}/rsa_key_sshkeygen", - f"tests/{self.folder}/dsa_key_sshkeygen", + f"tests/{self.folder}/ecdsa_key_sshkeygen", ) def test_successful_assertions(self): @@ -128,12 +121,6 @@ def test_successful_assertions(self): f"tests/{self.folder}/rsa_key_sshkeygen.pub", ) - self.assertTrue(os.path.isfile(f"tests/{self.folder}/dsa_key_sshkeygen")) - self.assertEqualKeyFingerprint( - f"tests/{self.folder}/dsa_key_sshkeygen", - f"tests/{self.folder}/dsa_key_sshkeygen.pub", - ) - self.assertTrue(os.path.isfile(f"tests/{self.folder}/ecdsa_key_sshkeygen")) self.assertEqualKeyFingerprint( f"tests/{self.folder}/ecdsa_key_sshkeygen", @@ -174,21 +161,6 @@ def test_rsa_incorrect_keysize(self): with self.assertRaises(ValueError): RsaPrivateKey.generate(256) - def test_dsa(self): - - key = DsaPrivateKey.generate() - - assert isinstance(key, DsaPrivateKey) - assert isinstance(key, PrivateKey) - assert isinstance(key.key, _DSA.DSAPrivateKey) - assert isinstance(key.private_numbers, _DSA.DSAPrivateNumbers) - - assert isinstance(key.public_key, DsaPublicKey) - assert isinstance(key.public_key, PublicKey) - assert isinstance(key.public_key.key, _DSA.DSAPublicKey) - assert isinstance(key.public_key.public_numbers, _DSA.DSAPublicNumbers) - assert isinstance(key.public_key.parameters, _DSA.DSAParameterNumbers) - def test_ecdsa(self): curves = [EcdsaCurves.P256, EcdsaCurves.P384, EcdsaCurves.P521] @@ -297,49 +269,6 @@ def test_rsa_files(self): f"tests/{self.folder}/rsa_key_sshkeygen.pub", ) - def test_dsa_files(self): - parent = PrivateKey.from_file(f"tests/{self.folder}/dsa_key_sshkeygen") - child = DsaPrivateKey.from_file(f"tests/{self.folder}/dsa_key_sshkeygen") - - parent_pub = PublicKey.from_file(f"tests/{self.folder}/dsa_key_sshkeygen.pub") - child_pub = DsaPublicKey.from_file(f"tests/{self.folder}/dsa_key_sshkeygen.pub") - - parent.to_file(f"tests/{self.folder}/dsa_key_saved_parent") - child.to_file(f"tests/{self.folder}/dsa_key_saved_child") - - parent_pub.to_file(f"tests/{self.folder}/dsa_key_saved_parent.pub") - child_pub.to_file(f"tests/{self.folder}/dsa_key_saved_child.pub") - - self.assertEqualPrivateKeys(DsaPrivateKey, DsaPublicKey, parent, child) - - self.assertEqualPublicKeys(DsaPublicKey, parent_pub, child_pub) - - self.assertEqualPublicKeys(DsaPublicKey, parent.public_key, child_pub) - - self.assertEqualKeyFingerprint( - f"tests/{self.folder}/dsa_key_sshkeygen", - f"tests/{self.folder}/dsa_key_saved_parent", - ) - - self.assertEqualKeyFingerprint( - f"tests/{self.folder}/dsa_key_sshkeygen.pub", - f"tests/{self.folder}/dsa_key_saved_parent.pub", - ) - - self.assertEqualKeyFingerprint( - f"tests/{self.folder}/dsa_key_saved_parent", - f"tests/{self.folder}/dsa_key_saved_child", - ) - - self.assertEqualKeyFingerprint( - f"tests/{self.folder}/dsa_key_saved_parent.pub", - f"tests/{self.folder}/dsa_key_sshkeygen.pub", - ) - self.assertEqualKeyFingerprint( - f"tests/{self.folder}/dsa_key_saved_parent.pub", - f"tests/{self.folder}/dsa_key_sshkeygen.pub", - ) - def test_ecdsa_files(self): parent = PrivateKey.from_file(f"tests/{self.folder}/ecdsa_key_sshkeygen") child = EcdsaPrivateKey.from_file(f"tests/{self.folder}/ecdsa_key_sshkeygen") @@ -438,7 +367,6 @@ def test_ed25519_files(self): class TestFromClass(KeypairMethods): def setUp(self): self.rsa_key = _RSA.generate_private_key(public_exponent=65537, key_size=2048) - self.dsa_key = _DSA.generate_private_key(key_size=1024) self.ecdsa_key = _EC.generate_private_key(curve=_EC.SECP384R1()) self.ed25519_key = _ED25519.Ed25519PrivateKey.generate() @@ -457,12 +385,6 @@ def test_rsa_from_class(self): self.assertEqualPrivateKeys(RsaPrivateKey, RsaPublicKey, parent, child) - def test_dsa_from_class(self): - parent = PrivateKey.from_class(self.dsa_key) - child = DsaPrivateKey.from_class(self.dsa_key) - - self.assertEqualPrivateKeys(DsaPrivateKey, DsaPublicKey, parent, child) - def test_ecdsa_from_class(self): parent = PrivateKey.from_class(self.ecdsa_key) child = EcdsaPrivateKey.from_class(self.ecdsa_key) @@ -513,30 +435,7 @@ def test_rsa_from_numbers(self): self.assertEqual(self.rsa_key.private_numbers.d, from_numbers.private_numbers.d) - def test_dsa_from_numbers(self): - from_numbers = DsaPrivateKey.from_numbers( - p=self.dsa_key.public_key.parameters.p, - q=self.dsa_key.public_key.parameters.q, - g=self.dsa_key.public_key.parameters.g, - y=self.dsa_key.public_key.public_numbers.y, - x=self.dsa_key.private_numbers.x, - ) - - from_numbers_pub = DsaPublicKey.from_numbers( - p=self.dsa_key.public_key.parameters.p, - q=self.dsa_key.public_key.parameters.q, - g=self.dsa_key.public_key.parameters.g, - y=self.dsa_key.public_key.public_numbers.y, - ) - - self.assertEqualPrivateKeys( - DsaPrivateKey, DsaPublicKey, self.dsa_key, from_numbers - ) - - self.assertEqualPublicKeys( - DsaPublicKey, from_numbers_pub, self.dsa_key.public_key - ) - + def test_ecdsa_from_numbers(self): from_numbers = EcdsaPrivateKey.from_numbers( curve=self.ecdsa_key.public_key.key.curve, @@ -599,16 +498,6 @@ def test_rsa_fingerprint(self): self.assertEqual(key.get_fingerprint(), sshkey_fingerprint) - def test_dsa_fingerprint(self): - key = DsaPrivateKey.from_file( - f"tests/{self.folder}/dsa_key_sshkeygen", - ) - - with os.popen(f"ssh-keygen -lf tests/{self.folder}/dsa_key_sshkeygen") as cmd: - sshkey_fingerprint = cmd.read().split(" ")[1] - - self.assertEqual(key.get_fingerprint(), sshkey_fingerprint) - def test_ecdsa_fingerprint(self): key = EcdsaPrivateKey.from_file( f"tests/{self.folder}/ecdsa_key_sshkeygen", @@ -646,15 +535,6 @@ def test_rsa_signature(self): with self.assertRaises(_EX.InvalidSignatureException): self.rsa_key.public_key.verify(data, signature + b"\x00") - def test_dsa_signature(self): - data = b"\x00" + os.urandom(32) + b"\x00" - signature = self.dsa_key.sign(data) - - self.assertIsNone(self.dsa_key.public_key.verify(data, signature)) - - with self.assertRaises(_EX.InvalidSignatureException): - self.dsa_key.public_key.verify(data, signature + b"\x00") - def test_ecdsa_signature(self): data = b"\x00" + os.urandom(32) + b"\x00" signature = self.ecdsa_key.sign(data) From dcefd5b46b3c2ecc1a93ca35bdc6034f0e0932b4 Mon Sep 17 00:00:00 2001 From: Lars Scheibling Date: Wed, 7 Jun 2023 13:00:17 +0000 Subject: [PATCH 2/2] Removed DSA Support --- README.md | 14 ++-- src/sshkey_tools/cert.py | 14 ++-- src/sshkey_tools/exceptions.py | 5 ++ src/sshkey_tools/fields.py | 88 ++++--------------------- src/sshkey_tools/keys.py | 116 +++++---------------------------- tests/test_certificates.py | 17 +---- 6 files changed, 47 insertions(+), 207 deletions(-) diff --git a/README.md b/README.md index 0e6ada8..1ba20ff 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,15 @@ Python package for managing OpenSSH keypairs and certificates ([protocol.CERTKEYS](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys)). Supported functionality includes: -# Notice +## Notice The DSA algorithm has been deprecated and is removed in pyca/cryptography 41.x, meaning **version 0.9.* of this package will be the last to support DSA keys and certificates** for SSH. If there is any demand to reintroduce DSA support, please open an issue regarding this and we'll look into it. For now, **0.9.* will be restricted to version <41.1 of the cryptography package** and **0.10 will have its DSA support removed**. We've introduced a deprecation notice in version 0.9.3. -## Background +### Background The DSA algorithm is considered deprecated and will be removed in a future version. If possible, use RSA, [(ECDSA)](https://billatnapier.medium.com/ecdsa-weakness-where-nonces-are-reused-2be63856a01a) or ED25519 as a first-hand choice. -## Notice from OpenSSH: +### Notice from OpenSSH: ``` OpenSSH 7.0 and greater similarly disable the ssh-dss (DSA) public key algorithm. It too is weak and we recommend against its use. It can be re-enabled using the HostKeyAlgorithms configuration option: sshd_config(5) HostKeyAlgorithms ``` @@ -19,7 +19,7 @@ OpenSSH 7.0 and greater similarly disable the ssh-dss (DSA) public key algorithm # Features ### SSH Keys -- Supports RSA, DSA (Note: Deprecated), ECDSA and ED25519 keys +- Supports RSA, ECDSA and ED25519 keys - Import existing keys from file, string, byte data or [pyca/cryptography](https://github.com/pyca/cryptography) class - Generate new keys - Get public key from private keys @@ -28,7 +28,7 @@ OpenSSH 7.0 and greater similarly disable the ssh-dss (DSA) public key algorithm - Generate fingerprint ### OpenSSH Certificates -- Supports RSA, DSA, ECDSA and ED25519 certificates +- Supports RSA, ECDSA and ED25519 certificates - Import existing certificates from file, string or bytes - Verify certificate signature against internal or separate public key - Create new certificates from CA private key and subject public key @@ -72,7 +72,6 @@ rm -rf docs/sshkey_tools # Import the certificate classes from sshkey_tools.keys import ( RsaPrivateKey, - DsaPrivateKey, EcdsaPrivateKey, Ed25519PrivateKey, EcdsaCurves @@ -87,7 +86,8 @@ rsa_priv = RsaPrivateKey.generate() rsa_priv = RsaPrivateKey.generate(2048) # Generate DSA keys (since SSH only supports 1024-bit keys, this is the default) -dsa_priv = DsaPrivateKey.generate() +# DEPRECATED +# dsa_priv = DsaPrivateKey.generate() # Generate ECDSA keys (The default curve is P521) ecdsa_priv = EcdsaPrivateKey.generate() diff --git a/src/sshkey_tools/cert.py b/src/sshkey_tools/cert.py index ee04421..e952d96 100644 --- a/src/sshkey_tools/cert.py +++ b/src/sshkey_tools/cert.py @@ -24,7 +24,6 @@ "ssh-rsa-cert-v01@openssh.com": ("RsaCertificate", "RsaPubkeyField"), "rsa-sha2-256-cert-v01@openssh.com": ("RsaCertificate", "RsaPubkeyField"), "rsa-sha2-512-cert-v01@openssh.com": ("RsaCertificate", "RsaPubkeyField"), - "ssh-dss-cert-v01@openssh.com": ("DsaCertificate", "DsaPubkeyField"), "ecdsa-sha2-nistp256-cert-v01@openssh.com": ( "EcdsaCertificate", "EcdsaPubkeyField", @@ -579,14 +578,11 @@ class RsaCertificate(SSHCertificate): class DsaCertificate(SSHCertificate): """The DSA Certificate class (DEPRECATED)""" - - DEFAULT_KEY_TYPE = "ssh-dss-cert-v01@openssh.com" - - def __post_init__(self): - """Display the deprecation notice""" - warnings.warn( - "SSH DSA keys and certificates are deprecated and will be removed in version 0.10 of sshkey-tools", - stacklevel=2, + + def __init__(self, *args, **kwargs): + """DEPRECATED CERTIFICATE CLASS""" + raise _EX.DeprecatedClassCalled( + "DSA certificates are deprecated and have been removed since version 0.10 of sshkey-tools" ) diff --git a/src/sshkey_tools/exceptions.py b/src/sshkey_tools/exceptions.py index c71e508..0cc691c 100644 --- a/src/sshkey_tools/exceptions.py +++ b/src/sshkey_tools/exceptions.py @@ -107,3 +107,8 @@ class InvalidClassCallException(ValueError): """ Raised when trying to instantiate a parent class """ + +class DeprecatedClassCalled(ValueError): + """ + Raised when trying to instantiate a deprecated class + """ \ No newline at end of file diff --git a/src/sshkey_tools/fields.py b/src/sshkey_tools/fields.py index 81fd844..4e70608 100644 --- a/src/sshkey_tools/fields.py +++ b/src/sshkey_tools/fields.py @@ -16,8 +16,6 @@ from . import exceptions as _EX from .keys import ( - DsaPrivateKey, - DsaPublicKey, EcdsaPrivateKey, EcdsaPublicKey, Ed25519PrivateKey, @@ -53,21 +51,18 @@ SUBJECT_PUBKEY_MAP = { RsaPublicKey: "RsaPubkeyField", - DsaPublicKey: "DsaPubkeyField", EcdsaPublicKey: "EcdsaPubkeyField", Ed25519PublicKey: "Ed25519PubkeyField", } CA_SIGNATURE_MAP = { RsaPrivateKey: "RsaSignatureField", - DsaPrivateKey: "DsaSignatureField", EcdsaPrivateKey: "EcdsaSignatureField", Ed25519PrivateKey: "Ed25519SignatureField", } SIGNATURE_TYPE_MAP = { b"rsa": "RsaSignatureField", - b"dss": "DsaSignatureField", b"ecdsa": "EcdsaSignatureField", b"ed25519": "Ed25519SignatureField", } @@ -727,7 +722,6 @@ class PubkeyTypeField(StringField): "ssh-rsa-cert-v01@openssh.com", "rsa-sha2-256-cert-v01@openssh.com", "rsa-sha2-512-cert-v01@openssh.com", - "ssh-dss-cert-v01@openssh.com", "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ecdsa-sha2-nistp521-cert-v01@openssh.com", @@ -867,11 +861,8 @@ class DsaPubkeyField(PublicKeyField): Holds the DSA Public Key for DSA Certificates """ - DEFAULT = None - DATA_TYPE = DsaPublicKey - @staticmethod - def decode(data: bytes) -> Tuple[DsaPublicKey, bytes]: + def decode(data: bytes): """ Decode the certificate field from a byte string starting with the encoded public key @@ -882,12 +873,7 @@ def decode(data: bytes) -> Tuple[DsaPublicKey, bytes]: Returns: Tuple[RsaPublicKey, bytes]: The PublicKey field and remainder of the data """ - p, data = MpIntegerField.decode(data) - q, data = MpIntegerField.decode(data) - g, data = MpIntegerField.decode(data) - y, data = MpIntegerField.decode(data) - - return DsaPublicKey.from_numbers(p=p, q=q, g=g, y=y), data + raise _EX.DeprecatedClassCalled("DSA is deprecated, use RSA or ECDSA instead") class EcdsaPubkeyField(PublicKeyField): @@ -1469,16 +1455,13 @@ class DsaSignatureField(SignatureField): Creates and contains the DSA signature from an DSA Private Key """ - DEFAULT = None - DATA_TYPE = bytes - - def __init__( - self, private_key: DsaPrivateKey = None, signature: bytes = None - ) -> None: - super().__init__(private_key, signature) + def __init__(self, *args, **kwargs) -> None: + raise _EX.DeprecatedClassCalled( + "DSA signatures are deprecated and have been removed" + ) @classmethod - def encode(cls, value: bytes): + def encode(cls, value = None): """ Encodes the signature to a byte string @@ -1488,62 +1471,15 @@ def encode(cls, value: bytes): Returns: bytes: The encoded byte string """ - cls.__validate_type__(value, True) - - r, s = decode_dss_signature(value) - - return BytestringField.encode( - StringField.encode("ssh-dss") - + BytestringField.encode(long_to_bytes(r, 20) + long_to_bytes(s, 20)) - ) + cls() @staticmethod - def decode(data: bytes) -> Tuple[bytes, bytes]: - """ - Decodes a bytestring containing a signature - - Args: - data (bytes): The bytestring starting with the Signature - - Returns: - Tuple[ bytes, bytes ]: signature, remainder of the data - """ - signature, data = BytestringField.decode(data) - - signature = BytestringField.decode(BytestringField.decode(signature)[1])[0] - r = bytes_to_long(signature[:20]) - s = bytes_to_long(signature[20:]) - - signature = encode_dss_signature(r, s) - - return signature, data + def decode(data = None): + DsaSignatureField() @classmethod - def from_decode(cls, data: bytes) -> Tuple["DsaSignatureField", bytes]: - """ - Creates a signature field class from the encoded signature - - Args: - data (bytes): The bytestring starting with the Signature - - Returns: - Tuple[ DsaSignatureField, bytes ]: signature, remainder of the data - """ - signature, data = cls.decode(data) - - return cls(private_key=None, signature=signature), data - - # pylint: disable=unused-argument - def sign(self, data: bytes, **kwargs) -> None: - """ - Signs the provided data with the provided private key - - Args: - data (bytes): The data to be signed - """ - self.value = self.private_key.sign(data) - self.is_signed = True - + def from_decode(cls, data = None): + cls() class EcdsaSignatureField(SignatureField): """ diff --git a/src/sshkey_tools/keys.py b/src/sshkey_tools/keys.py index a5fb829..7bc7d79 100644 --- a/src/sshkey_tools/keys.py +++ b/src/sshkey_tools/keys.py @@ -8,15 +8,12 @@ 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.bindings import _rust as _RustBinding + 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 @@ -34,17 +31,15 @@ PUBKEY_MAP = { _RSAPublicKey: "RsaPublicKey", - _DSAPublicKey: "DsaPublicKey", _EllipticCurvePublicKey: "EcdsaPublicKey", - _Ed25519PublicKey: "Ed25519PublicKey", + _RustBinding.openssl.ed25519.Ed25519PublicKey: "Ed25519PublicKey", } PRIVKEY_MAP = { _RSAPrivateKey: "RsaPrivateKey", - _DSAPrivateKey: "DsaPrivateKey", _EllipticCurvePrivateKey: "EcdsaPrivateKey", # trunk-ignore(gitleaks/generic-api-key) - _Ed25519PrivateKey: "Ed25519PrivateKey", + _RustBinding.openssl.ed25519.Ed25519PrivateKey: "Ed25519PrivateKey", } ECDSA_HASHES = { @@ -599,87 +594,30 @@ 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, + def __init__(self, key = None, comment = None, key_type = None, serialized = None): + raise _EX.DeprecatedClassCalled( + "SSH DSA keys and certificates are deprecated and are removed since version 0.10 of sshkey-tools", ) - self.parameters = key.parameters().parameter_numbers() - - warnings.warn( - "SSH DSA keys and certificates are deprecated and will be removed in version 0.10 of sshkey-tools", - stacklevel=2, - ) - + @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 - + return cls() + 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(), - ) - - warnings.warn( - "SSH DSA keys and certificates are deprecated and will be removed in version 0.10 of sshkey-tools", - stacklevel=2, + def __init__(self, key = None): + raise _EX.DeprecatedClassCalled( + "SSH DSA keys and certificates are deprecated and are removed since version 0.10 of sshkey-tools", ) @classmethod # pylint: disable=invalid-name,too-many-arguments - def from_numbers(cls, p: int, q: int, g: int, y: int, x: int) -> "DsaPrivateKey": + def from_numbers(cls, p, q, g, y, x): """ Creates a new DsaPrivateKey object from parameters and public/private numbers @@ -693,15 +631,8 @@ def from_numbers(cls, p: int, q: int, g: int, y: int, x: int) -> "DsaPrivateKey" 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() - ) - + return cls() + @classmethod def generate(cls) -> "DsaPrivateKey": """ @@ -711,20 +642,7 @@ def generate(cls) -> "DsaPrivateKey": 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()) - + return cls() class EcdsaPublicKey(PublicKey): """ diff --git a/tests/test_certificates.py b/tests/test_certificates.py index 682c0a3..62976a4 100644 --- a/tests/test_certificates.py +++ b/tests/test_certificates.py @@ -16,14 +16,13 @@ import src.sshkey_tools.fields as _FIELD import src.sshkey_tools.keys as _KEY -CERTIFICATE_TYPES = ["rsa", "dsa", "ecdsa", "ed25519"] +CERTIFICATE_TYPES = ["rsa", "ecdsa", "ed25519"] class TestCertificateFields(unittest.TestCase): def setUp(self): self.faker = faker.Faker() self.rsa_key = _KEY.RsaPrivateKey.generate(1024) - self.dsa_key = _KEY.DsaPrivateKey.generate() self.ecdsa_key = _KEY.EcdsaPrivateKey.generate() self.ed25519_key = _KEY.Ed25519PrivateKey.generate() @@ -232,10 +231,6 @@ def test_pubkey_type_field(self): "rsa-sha2-512-cert-v01@openssh.com", b"\x00\x00\x00!rsa-sha2-512-cert-v01@openssh.com", ), - ( - "ssh-dss-cert-v01@openssh.com", - b"\x00\x00\x00\x1cssh-dss-cert-v01@openssh.com", - ), ( "ecdsa-sha2-nistp256-cert-v01@openssh.com", b"\x00\x00\x00(ecdsa-sha2-nistp256-cert-v01@openssh.com", @@ -281,17 +276,14 @@ def test_nonce_field(self): def test_pubkey_class_assignment(self): rsa_field = _FIELD.PublicKeyField.from_object(self.rsa_key.public_key) - dsa_field = _FIELD.PublicKeyField.from_object(self.dsa_key.public_key) ecdsa_field = _FIELD.PublicKeyField.from_object(self.ecdsa_key.public_key) ed25519_field = _FIELD.PublicKeyField.from_object(self.ed25519_key.public_key) self.assertIsInstance(rsa_field, _FIELD.RsaPubkeyField) - self.assertIsInstance(dsa_field, _FIELD.DsaPubkeyField) self.assertIsInstance(ecdsa_field, _FIELD.EcdsaPubkeyField) self.assertIsInstance(ed25519_field, _FIELD.Ed25519PubkeyField) self.assertTrue(rsa_field.validate()) - self.assertTrue(dsa_field.validate()) self.assertTrue(ecdsa_field.validate()) self.assertTrue(ed25519_field.validate()) @@ -316,9 +308,6 @@ def assertPubkeyOutput(self, key_class, *opts): def test_rsa_pubkey_output(self): self.assertPubkeyOutput(_KEY.RsaPrivateKey, 1024) - def test_dsa_pubkey_output(self): - self.assertPubkeyOutput(_KEY.DsaPrivateKey) - def test_ecdsa_pubkey_output(self): self.assertPubkeyOutput(_KEY.EcdsaPrivateKey) @@ -551,12 +540,10 @@ def setUp(self): self.faker = faker.Faker() self.rsa_ca = _KEY.RsaPrivateKey.generate(1024) - self.dsa_ca = _KEY.DsaPrivateKey.generate() self.ecdsa_ca = _KEY.EcdsaPrivateKey.generate() self.ed25519_ca = _KEY.Ed25519PrivateKey.generate() self.rsa_user = _KEY.RsaPrivateKey.generate(1024).public_key - self.dsa_user = _KEY.DsaPrivateKey.generate().public_key self.ecdsa_user = _KEY.EcdsaPrivateKey.generate().public_key self.ed25519_user = _KEY.Ed25519PrivateKey.generate().public_key @@ -581,12 +568,10 @@ def tearDown(self): def test_cert_type_assignment(self): rsa_cert = _CERT.SSHCertificate.create(self.rsa_user) - dsa_cert = _CERT.SSHCertificate.create(self.dsa_user) ecdsa_cert = _CERT.SSHCertificate.create(self.ecdsa_user) ed25519_cert = _CERT.SSHCertificate.create(self.ed25519_user) self.assertIsInstance(rsa_cert, _CERT.RsaCertificate) - self.assertIsInstance(dsa_cert, _CERT.DsaCertificate) self.assertIsInstance(ecdsa_cert, _CERT.EcdsaCertificate) self.assertIsInstance(ed25519_cert, _CERT.Ed25519Certificate)