Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
'securesystemslib.exceptions.CryptoError' raised if the decryption fails.
"""
# Extract the salt, iterations, hmac, initialization vector, and ciphertext
# from 'file_contents'. These five values are delimited by
# '_ENCRYPTION_DELIMITER'. This delimiter is arbitrarily chosen and should
# not occur in the hexadecimal representations of the fields it is
# separating. Raise 'securesystemslib.exceptions.CryptoError', if
# 'file_contents' does not contains the expected data layout.
try:
salt, iterations, hmac, iv, ciphertext = \
file_contents.split(_ENCRYPTION_DELIMITER)
except ValueError:
raise securesystemslib.exceptions.CryptoError('Invalid encrypted file.')
# Ensure we have the expected raw data for the delimited cryptographic data.
salt = binascii.unhexlify(salt.encode('utf-8'))
iterations = int(iterations)
iv = binascii.unhexlify(iv.encode('utf-8'))
ciphertext = binascii.unhexlify(ciphertext.encode('utf-8'))
# Generate derived key from 'password'. The salt and iterations are
# specified so that the expected derived key is regenerated correctly.
# Discard the old "salt" and "iterations" values, as we only need the old
# derived key.
junk_old_salt, junk_old_iterations, symmetric_key = \
_generate_derived_key(password, salt, iterations)
# Verify the hmac to ensure the ciphertext is valid and has not been altered.
# See the encryption routine for why we use the encrypt-then-MAC approach.
'securesystemslib.exceptions.CryptoError' raised if the decryption fails.
"""
# Extract the salt, iterations, hmac, initialization vector, and ciphertext
# from 'file_contents'. These five values are delimited by
# '_ENCRYPTION_DELIMITER'. This delimiter is arbitrarily chosen and should
# not occur in the hexadecimal representations of the fields it is
# separating. Raise 'securesystemslib.exceptions.CryptoError', if 'file_contents'
# does not contains the expected data layout.
try:
salt, iterations, hmac, iv, ciphertext = \
file_contents.split(_ENCRYPTION_DELIMITER)
except ValueError:
raise securesystemslib.exceptions.CryptoError('Invalid encrypted file.')
# Ensure we have the expected raw data for the delimited cryptographic data.
salt = binascii.unhexlify(salt.encode('utf-8'))
iterations = int(iterations)
iv = binascii.unhexlify(iv.encode('utf-8'))
ciphertext = binascii.unhexlify(ciphertext.encode('utf-8'))
# Generate derived key from 'password'. The salt and iterations are
# specified so that the expected derived key is regenerated correctly.
# Discard the old "salt" and "iterations" values, as we only need the old
# derived key.
junk_old_salt, junk_old_iterations, derived_key = \
_generate_derived_key(password, salt, iterations)
# Verify the hmac to ensure the ciphertext is valid and has not been altered.
# See the encryption routine for why we use the encrypt-then-MAC approach.
# An if-clause is not strictly needed here, since 'ed25519' is the only
# currently supported scheme. Nevertheless, include the conditional
# statement to accommodate schemes that might be added in the future.
if scheme == 'ed25519':
try:
nacl_key = nacl.signing.SigningKey(private)
nacl_sig = nacl_key.sign(data)
signature = nacl_sig.signature
# The unit tests expect required libraries to be installed.
except NameError: # pragma: no cover
raise securesystemslib.exceptions.UnsupportedLibraryError('The PyNaCl'
' library and/or its dependencies unavailable.')
except (ValueError, TypeError, nacl.exceptions.CryptoError) as e:
raise securesystemslib.exceptions.CryptoError('An "ed25519" signature'
' could not be created with PyNaCl.' + str(e))
# This is a defensive check for a valid 'scheme', which should have already
# been validated in the check_match() above.
else: #pragma: no cover
raise securesystemslib.exceptions.UnsupportedAlgorithmError('Unsupported'
' signature scheme is specified: ' + repr(scheme))
return signature, scheme
junk_old_salt, junk_old_iterations, symmetric_key = \
_generate_derived_key(password, salt, iterations)
# Verify the hmac to ensure the ciphertext is valid and has not been altered.
# See the encryption routine for why we use the encrypt-then-MAC approach.
# The decryption routine may verify a ciphertext without having to perform
# a decryption operation.
generated_hmac_object = \
cryptography.hazmat.primitives.hmac.HMAC(symmetric_key, hashes.SHA256(),
backend=default_backend())
generated_hmac_object.update(ciphertext)
generated_hmac = binascii.hexlify(generated_hmac_object.finalize())
if not securesystemslib.util.digests_are_equal(generated_hmac.decode(), hmac):
raise securesystemslib.exceptions.CryptoError('Decryption failed.')
# Construct a Cipher object, with the key and iv.
decryptor = Cipher(algorithms.AES(symmetric_key), modes.CTR(iv),
backend=default_backend()).decryptor()
# Decryption gets us the authenticated plaintext.
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
return plaintext
# Generate RSSA-PSS signature. Raise 'securesystemslib.exceptions.CryptoError'
# for the expected PyCrypto exceptions.
try:
pkcs1_pss_signer = Crypto.Signature.PKCS1_PSS.new(rsa_key_object)
signature = pkcs1_pss_signer.sign(sha256_object)
except ValueError: #pragma: no cover
raise securesystemslib.exceptions.CryptoError('The RSA key too small for'
' given hash algorithm.')
except TypeError:
raise securesystemslib.exceptions.CryptoError('Missing required RSA'
' private key.')
except IndexError: # pragma: no cover
raise securesystemslib.exceptions.CryptoError('An RSA signature cannot'
' be generated: ' + str(e))
else:
raise ValueError('The required private key is unset.')
return signature, method
# Verify whether the private key of 'public_key' produced 'signature'.
# Before returning the 'valid_signature' Boolean result, ensure 'RSASSA-PSS'
# was used as the signing method.
valid_signature = False
# Verify the signature with PyCrypto if the signature method is valid,
# otherwise raise 'securesystemslib.exceptions.UnknownMethodError'.
if signature_method == 'RSASSA-PSS':
try:
rsa_key_object = Crypto.PublicKey.RSA.importKey(public_key)
pkcs1_pss_verifier = Crypto.Signature.PKCS1_PSS.new(rsa_key_object)
sha256_object = Crypto.Hash.SHA256.new(data)
valid_signature = pkcs1_pss_verifier.verify(sha256_object, signature)
except (ValueError, IndexError, TypeError):
raise securesystemslib.exceptions.CryptoError('The RSA signature could not'
' be verified.')
else:
raise securesystemslib.exceptions.UnknownMethodError(signature_method)
return valid_signature
else: # pragma: no cover
raise securesystemslib.exceptions.UnsupportedAlgorithmError('Unsupported'
' signature scheme is specified: ' + repr(scheme))
# If the PEM data could not be decrypted, or if its structure could not
# be decoded successfully.
except ValueError:
raise securesystemslib.exceptions.CryptoError('The private key'
' (in PEM format) could not be deserialized.')
# 'TypeError' is raised if a password was given and the private key was
# not encrypted, or if the key was encrypted but no password was
# supplied. Note: A passphrase or password is not used when generating
# 'private_key', since it should not be encrypted.
except TypeError:
raise securesystemslib.exceptions.CryptoError('The private key was'
' unexpectedly encrypted.')
# 'cryptography.exceptions.UnsupportedAlgorithm' is raised if the
# serialized key is of a type that is not supported by the backend, or if
# the key is encrypted with a symmetric cipher that is not supported by
# the backend.
except cryptography.exceptions.UnsupportedAlgorithm: # pragma: no cover
raise securesystemslib.exceptions.CryptoError('The private key is'
' encrypted with an unsupported algorithm.')
return signature, scheme
aes_cipher = Crypto.Cipher.AES.new(symmetric_key,
Crypto.Cipher.AES.MODE_CTR,
counter=stateful_counter_128bit_blocks)
# Use AES-256 to encrypt 'key_data'. The key size determines how many cycle
# repetitions are performed by AES, 14 cycles for 256-bit keys.
try:
ciphertext = aes_cipher.encrypt(key_data)
# PyCrypto does not document the exceptions that may be raised or under what
# circumstances. PyCrypto example given is to call encrypt() without
# checking for exceptions. Avoid propogating the exception trace and only
# raise 'securesystemslib.exceptions.CryptoError', along with the cause of
# encryption failure.
except (ValueError, IndexError, TypeError) as e:
raise securesystemslib.exceptions.CryptoError('The key data cannot be'
' encrypted: ' + str(e))
# Generate the hmac of the ciphertext to ensure it has not been modified.
# The decryption routine may verify a ciphertext without having to perform
# a decryption operation.
salt = derived_key_information['salt']
hmac_object = Crypto.Hash.HMAC.new(symmetric_key, ciphertext,
Crypto.Hash.SHA256)
hmac = hmac_object.hexdigest()
# Store the number of PBKDF2 iterations used to derive the symmetric key so
# that the decryption routine can regenerate the symmetric key successfully.
# The pbkdf2 iterations are allowed to vary for the keys loaded and saved.
iterations = derived_key_information['iterations']
# Return the salt, iterations, hmac, initialization vector, and ciphertext