Skip to content

Commit

Permalink
Better handle missing native dependencies in securesystemslib.keys
Browse files Browse the repository at this point in the history
When functions in securesystemslib.keys require non-python dependencies
guard there use with a check for the presence of the required dependency
and return meaningful error messages when the dependency is missing.

Signed-off-by: Joshua Lock <[email protected]>
  • Loading branch information
joshuagl committed Jan 6, 2020
1 parent 1de19f7 commit 70e6310
Showing 1 changed file with 69 additions and 2 deletions.
71 changes: 69 additions & 2 deletions securesystemslib/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -100,8 +101,9 @@

try:
import securesystemslib.ecdsa_keys

USE_ECDSA = True
except ImportError: #pragma: no cover
USE_ECDSA = False
pass

import securesystemslib.exceptions
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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)

Expand Down Expand Up @@ -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)
Expand All @@ -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)

Expand Down Expand Up @@ -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'.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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'.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 70e6310

Please sign in to comment.