diff --git a/securesystemslib/keys.py b/securesystemslib/keys.py index 00f98e39d..dc860c682 100755 --- a/securesystemslib/keys.py +++ b/securesystemslib/keys.py @@ -70,8 +70,9 @@ # signatures. try: import securesystemslib.pyca_crypto_keys - + USE_PYCA = True except ImportError: #pragma: no cover + USE_PYCA = False pass # Import the PyNaCl library, if available. It is recommended this library be @@ -100,8 +101,9 @@ try: import securesystemslib.ecdsa_keys - + USE_ECDSA = True except ImportError: #pragma: no cover + USE_ECDSA = False pass import securesystemslib.exceptions @@ -200,6 +202,10 @@ def generate_rsa_key(bits=_DEFAULT_RSA_KEY_BITS, scheme='rsassa-pss-sha256'): Conforms to 'securesystemslib.formats.RSAKEY_SCHEMA'. """ + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support RSA keys') + # Does 'bits' have the correct format? This check will ensure 'bits' # conforms to 'securesystemslib.formats.RSAKEYBITS_SCHEMA'. 'bits' must be # an integer object, with a minimum value of 2048. Raise @@ -287,6 +293,11 @@ def generate_ecdsa_key(scheme='ecdsa-sha2-nistp256'): Conforms to 'securesystemslib.formats.ECDSAKEY_SCHEMA'. """ + # If the ecdsa module wasn't imported, we can't proceed with this method + if not USE_ECDSA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support ECDSA keys') + # Does 'scheme' have the correct format? # This check will ensure 'scheme' is properly formatted and is a supported # ECDSA signature scheme. Raise 'securesystemslib.exceptions.FormatError' if @@ -723,6 +734,10 @@ def create_signature(key_dict, data): sig = None if keytype == 'rsa': + # If the ecdsa module wasn't imported, we can't handle this type of key + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support RSA keys') if scheme in RSA_SIGNATURE_SCHEMES: private = private.replace('\r\n', '\n') sig, scheme = securesystemslib.pyca_crypto_keys.create_rsa_signature( @@ -733,12 +748,20 @@ def create_signature(key_dict, data): ' RSA signature scheme specified: ' + repr(scheme)) elif keytype == 'ed25519': + if not USE_PYNACL: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The nacl module is required to support ed25519 signing') public = binascii.unhexlify(public.encode('utf-8')) private = binascii.unhexlify(private.encode('utf-8')) sig, scheme = securesystemslib.ed25519_keys.create_signature( public, private, data, scheme) elif keytype == 'ecdsa-sha2-nistp256': + # If the ecdsa module wasn't imported, we can't handle this type of key + if not USE_ECDSA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support ECDSA keys') + sig, scheme = securesystemslib.ecdsa_keys.create_signature( public, private, data, scheme) @@ -864,6 +887,9 @@ def verify_signature(key_dict, signature, data): if keytype == 'rsa': + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support RSA keys') if scheme in RSA_SIGNATURE_SCHEMES: valid_signature = securesystemslib.pyca_crypto_keys.verify_rsa_signature(sig, scheme, public, data) @@ -884,6 +910,10 @@ def verify_signature(key_dict, signature, data): elif keytype == 'ecdsa-sha2-nistp256': if scheme == 'ecdsa-sha2-nistp256': + if not USE_ECDSA: # pragma: no cover + raise securesystemlib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support ECDSA keys') + valid_signature = securesystemslib.ecdsa_keys.verify_signature(public, scheme, sig, data) @@ -957,6 +987,10 @@ def import_rsakey_from_private_pem(pem, scheme='rsassa-pss-sha256', password=Non Conforms to 'securesystemslib.formats.RSAKEY_SCHEMA'. """ + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support RSA keys') + # Does 'pem' have the correct format? # This check will ensure 'pem' conforms to # 'securesystemslib.formats.PEMRSA_SCHEMA'. @@ -1051,6 +1085,10 @@ def import_rsakey_from_public_pem(pem, scheme='rsassa-pss-sha256'): Conforms to 'securesystemslib.formats.RSAKEY_SCHEMA'. """ + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support RSA keys') + # Does 'pem' have the correct format? # This check will ensure arguments has the appropriate number # of objects and object types, and that all dict keys are properly named. @@ -1127,6 +1165,10 @@ def import_rsakey_from_pem(pem, scheme='rsassa-pss-sha256'): Conforms to 'securesystemslib.formats.RSAKEY_SCHEMA'. """ + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support RSA keys') + # Does 'pem' have the correct format? # This check will ensure arguments has the appropriate number # of objects and object types, and that all dict keys are properly named. @@ -1323,6 +1365,10 @@ def encrypt_key(key_object, password): 'securesystemslib.formats.ENCRYPTEDKEY_SCHEMA'. """ + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to encrypt keys') + # Does 'key_object' have the correct format? # This check will ensure 'key_object' has the appropriate number # of objects and object types, and that all dict keys are properly named. @@ -1338,6 +1384,7 @@ def encrypt_key(key_object, password): # Generate an encrypted string of 'key_object' using AES-256-CTR-Mode, where # 'password' is strengthened with PBKDF2-HMAC-SHA256. + encrypted_key = securesystemslib.pyca_crypto_keys.encrypt_key(key_object, password) return encrypted_key @@ -1399,6 +1446,10 @@ def decrypt_key(encrypted_key, passphrase): RSAKEY_SCHEMA, ED25519KEY_SCHEMA). """ + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to decrypt keys') + # Does 'encrypted_key' have the correct format? # This check ensures 'encrypted_key' has the appropriate number # of objects and object types, and that all dict keys are properly named. @@ -1471,6 +1522,10 @@ def create_rsa_encrypted_pem(private_key, passphrase): Conforms to 'securesystemslib.formats.PEMRSA_SCHEMA'. """ + if not USE_PYCA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to RSA encryption') + # Does 'private_key' have the correct format? # This check will ensure 'private_key' has the appropriate number # of objects and object types, and that all dict keys are properly named. @@ -1701,6 +1756,10 @@ def import_ecdsakey_from_private_pem(pem, scheme='ecdsa-sha2-nistp256', password Conforms to 'securesystemslib.formats.ECDSAKEY_SCHEMA'. """ + if not USE_ECDSA: # pragma: no cover + raise securesystemlib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support ECDSA keys') + # Does 'pem' have the correct format? # This check will ensure 'pem' conforms to # 'securesystemslib.formats.ECDSARSA_SCHEMA'. @@ -1800,6 +1859,10 @@ def import_ecdsakey_from_public_pem(pem, scheme='ecdsa-sha2-nistp256'): Conforms to 'securesystemslib.formats.ECDSAKEY_SCHEMA'. """ + if not USE_ECDSA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support ECDSA keys') + # Does 'pem' have the correct format? # This check will ensure arguments has the appropriate number # of objects and object types, and that all dict keys are properly named. @@ -1875,6 +1938,10 @@ def import_ecdsakey_from_pem(pem, scheme='ecdsa-sha2-nistp256'): Conforms to 'securesystemslib.formats.ECDSAKEY_SCHEMA'. """ + if not USE_ECDSA: # pragma: no cover + raise securesystemslib.exceptions.UnsupportedLibraryError( + 'The cryptography module is required to support ECDSA keys') + # Does 'pem' have the correct format? # This check will ensure arguments has the appropriate number # of objects and object types, and that all dict keys are properly named.