def _decrypt(file_contents, password): """ The corresponding decryption routine for _encrypt(). '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, read_hmac, iv, ciphertext = \ file_contents.split(_ENCRYPTION_DELIMITER) except ValueError: raise 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. # The decryption routine may verify a ciphertext without having to perform # a decryption operation. generated_hmac_object = hmac.HMAC(symmetric_key, hashes.SHA256(), backend=default_backend()) generated_hmac_object.update(ciphertext) generated_hmac = binascii.hexlify(generated_hmac_object.finalize()) if not util.digests_are_equal(generated_hmac.decode(), read_hmac): raise 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
def create_signature(public_key, private_key, data, scheme): """ <Purpose> Return a (signature, scheme) tuple, where the signature scheme is 'ed25519' and is always generated by PyNaCl (i.e., 'nacl'). The signature returned conforms to 'securesystemslib.formats.ED25519SIGNATURE_SCHEMA', and has the form: '\xae\xd7\x9f\xaf\x95{bP\x9e\xa8YO Z\x86\x9d...' A signature is a 64-byte string. >>> public, private = generate_public_and_private() >>> data = b'The quick brown fox jumps over the lazy dog' >>> scheme = 'ed25519' >>> signature, scheme = \ create_signature(public, private, data, scheme) >>> securesystemslib.formats.ED25519SIGNATURE_SCHEMA.matches(signature) True >>> scheme == 'ed25519' True >>> signature, scheme = \ create_signature(public, private, data, scheme) >>> securesystemslib.formats.ED25519SIGNATURE_SCHEMA.matches(signature) True >>> scheme == 'ed25519' True <Arguments> public: The ed25519 public key, which is a 32-byte string. private: The ed25519 private key, which is a 32-byte string. data: Data object used by create_signature() to generate the signature. scheme: The signature scheme used to generate the signature. <Exceptions> securesystemslib.exceptions.FormatError, if the arguments are improperly formatted. securesystemslib.exceptions.CryptoError, if a signature cannot be created. securesystemslib.exceptions.UnsupportedLibraryError, if the PyNaCl ('nacl') module is unavailable. <Side Effects> nacl.signing.SigningKey.sign() called to generate the actual signature. <Returns> A signature dictionary conformat to 'securesystemslib.format.SIGNATURE_SCHEMA'. ed25519 signatures are 64 bytes, however, the hexlified signature is stored in the dictionary returned. """ if not NACL: # pragma: no cover raise exceptions.UnsupportedLibraryError(NO_NACL_MSG) # Does 'public_key' have the correct format? # This check will ensure 'public_key' conforms to # 'securesystemslib.formats.ED25519PUBLIC_SCHEMA', which must have length 32 # bytes. Raise 'securesystemslib.exceptions.FormatError' if the check fails. formats.ED25519PUBLIC_SCHEMA.check_match(public_key) # Is 'private_key' properly formatted? formats.ED25519SEED_SCHEMA.check_match(private_key) # Is 'scheme' properly formatted? formats.ED25519_SIG_SCHEMA.check_match(scheme) # Signing the 'data' object requires a seed and public key. # nacl.signing.SigningKey.sign() generates the signature. signature = None # 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 = SigningKey(private_key) nacl_sig = nacl_key.sign(data) signature = nacl_sig.signature except (ValueError, TypeError, nacl_exceptions.CryptoError) as e: raise 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 exceptions.UnsupportedAlgorithmError('Unsupported' ' signature scheme is specified: ' + repr(scheme)) return signature, scheme
def create_ecdsa_public_and_private_from_pem(pem, password=None): """ <Purpose> Create public and private ECDSA keys from a private 'pem'. The public and private keys are strings in PEM format: public: '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----', private: '-----BEGIN EC PRIVATE KEY----- ... -----END EC PRIVATE KEY-----'}} >>> junk, private = generate_public_and_private() >>> public, private = create_ecdsa_public_and_private_from_pem(private) >>> securesystemslib.formats.PEMECDSA_SCHEMA.matches(public) True >>> securesystemslib.formats.PEMECDSA_SCHEMA.matches(private) True >>> passphrase = 'secret' >>> encrypted_pem = create_ecdsa_encrypted_pem(private, passphrase) >>> public, private = create_ecdsa_public_and_private_from_pem(encrypted_pem, passphrase) >>> securesystemslib.formats.PEMECDSA_SCHEMA.matches(public) True >>> securesystemslib.formats.PEMECDSA_SCHEMA.matches(private) True <Arguments> pem: A string in PEM format. The private key is extracted and returned in an ecdsakey object. password: (optional) The password, or passphrase, to decrypt the private part of the ECDSA key if it is encrypted. 'password' is not used directly as the encryption key, a stronger encryption key is derived from it. <Exceptions> securesystemslib.exceptions.FormatError, if the arguments are improperly formatted. securesystemslib.exceptions.UnsupportedAlgorithmError, if the ECDSA key pair could not be extracted, possibly due to an unsupported algorithm. securesystemslib.exceptions.UnsupportedLibraryError, if the cryptography module is not available. <Side Effects> None. <Returns> A dictionary containing the ECDSA keys and other identifying information. Conforms to 'securesystemslib.formats.ECDSAKEY_SCHEMA'. """ if not CRYPTO: # pragma: no cover raise exceptions.UnsupportedLibraryError(NO_CRYPTO_MSG) # Does 'pem' have the correct format? # This check will ensure 'pem' conforms to # 'securesystemslib.formats.ECDSARSA_SCHEMA'. formats.PEMECDSA_SCHEMA.check_match(pem) if password is not None: formats.PASSWORD_SCHEMA.check_match(password) password = password.encode('utf-8') else: logger.debug('The password/passphrase is unset. The PEM is expected' ' to be unencrypted.') public = None private = None # Generate the public and private ECDSA keys. The pyca/cryptography library # performs the actual import operation. try: private = load_pem_private_key(pem.encode('utf-8'), password=password, backend=default_backend()) except (ValueError, UnsupportedAlgorithm) as e: raise exceptions.CryptoError('Could not import private' ' PEM.\n' + str(e)) public = private.public_key() # Serialize public and private keys to PEM format. private = private.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()) public = public.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) return public.decode('utf-8'), private.decode('utf-8')
def create_signature(public_key, private_key, data, scheme='ecdsa-sha2-nistp256'): """ <Purpose> Return a (signature, scheme) tuple. >>> requested_scheme = 'ecdsa-sha2-nistp256' >>> public, private = generate_public_and_private(requested_scheme) >>> data = b'The quick brown fox jumps over the lazy dog' >>> signature, scheme = create_signature(public, private, data, requested_scheme) >>> securesystemslib.formats.ECDSASIGNATURE_SCHEMA.matches(signature) True >>> requested_scheme == scheme True <Arguments> public: The ECDSA public key in PEM format. private: The ECDSA private key in PEM format. data: Byte data used by create_signature() to generate the signature returned. scheme: The signature scheme used to generate the signature. For example: 'ecdsa-sha2-nistp256'. <Exceptions> securesystemslib.exceptions.FormatError, if the arguments are improperly formatted. securesystemslib.exceptions.CryptoError, if a signature cannot be created. securesystemslib.exceptions.UnsupportedAlgorithmError, if 'scheme' is not one of the supported signature schemes. securesystemslib.exceptions.UnsupportedLibraryError, if the cryptography module is not available. <Side Effects> None. <Returns> A signature dictionary conformat to 'securesystemslib.format.SIGNATURE_SCHEMA'. ECDSA signatures are XX bytes, however, the hexlified signature is stored in the dictionary returned. """ if not CRYPTO: # pragma: no cover raise exceptions.UnsupportedLibraryError(NO_CRYPTO_MSG) # Do 'public_key' and 'private_key' have the correct format? # This check will ensure that the arguments conform to # 'securesystemslib.formats.PEMECDSA_SCHEMA'. Raise # 'securesystemslib.exceptions.FormatError' if the check fails. formats.PEMECDSA_SCHEMA.check_match(public_key) # Is 'private_key' properly formatted? formats.PEMECDSA_SCHEMA.check_match(private_key) # Is 'scheme' properly formatted? formats.ECDSA_SCHEME_SCHEMA.check_match(scheme) # 'ecdsa-sha2-nistp256' is the only currently supported ECDSA scheme, so this # if-clause isn't strictly needed. Nevertheless, the conditional statement # is included to accommodate multiple schemes that can potentially be added # in the future. if scheme == 'ecdsa-sha2-nistp256': try: private_key = load_pem_private_key(private_key.encode('utf-8'), password=None, backend=default_backend()) signature = private_key.sign(data, ec.ECDSA(hashes.SHA256())) except TypeError as e: raise exceptions.CryptoError('Could not create' ' signature: ' + str(e)) # A defensive check for an invalid 'scheme'. The # ECDSA_SCHEME_SCHEMA.check_match() above should have already validated it. else: #pragma: no cover raise exceptions.UnsupportedAlgorithmError( 'Unsupported' ' signature scheme is specified: ' + repr(scheme)) return signature, scheme
def create_rsa_public_and_private_from_pem(pem, passphrase=None): """ <Purpose> Generate public and private RSA keys from an optionally encrypted PEM. The public and private keys returned conform to 'securesystemslib.formats.PEMRSA_SCHEMA' and have the form: '-----BEGIN RSA PUBLIC KEY----- ... -----END RSA PUBLIC KEY-----' and '-----BEGIN RSA PRIVATE KEY----- ...-----END RSA PRIVATE KEY-----' The public and private keys are returned as strings in PEM format. In case the private key part of 'pem' is encrypted pyca/cryptography's load_pem_private_key() method is passed passphrase. In the default case here, pyca/cryptography will decrypt with a PBKDF1+MD5 strengthened'passphrase', and 3DES with CBC mode for encryption/decryption. Alternatively, key data may be encrypted with AES-CTR-Mode and the passphrase strengthened with PBKDF2+SHA256, although this method is used only with securesystemslib encrypted key files. >>> public, private = generate_rsa_public_and_private(2048) >>> passphrase = 'secret' >>> encrypted_pem = create_rsa_encrypted_pem(private, passphrase) >>> returned_public, returned_private = \ create_rsa_public_and_private_from_pem(encrypted_pem, passphrase) >>> securesystemslib.formats.PEMRSA_SCHEMA.matches(returned_public) True >>> securesystemslib.formats.PEMRSA_SCHEMA.matches(returned_private) True >>> public == returned_public True >>> private == returned_private True <Arguments> pem: A byte string in PEM format, where the private key can be encrypted. It has the form: '-----BEGIN RSA PRIVATE KEY-----\n Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC ...' passphrase: (optional) The passphrase, or password, to decrypt the private part of the RSA key. 'passphrase' is not directly used as the encryption key, instead it is used to derive a stronger symmetric key. <Exceptions> securesystemslib.exceptions.FormatError, if the arguments are improperly formatted. securesystemslib.exceptions.CryptoError, if the public and private RSA keys cannot be generated from 'pem', or exported in PEM format. securesystemslib.exceptions.UnsupportedLibraryError, if the cryptography module is not available. <Side Effects> pyca/cryptography's 'serialization.load_pem_private_key()' called to perform the actual conversion from an encrypted RSA private key to PEM format. <Returns> A (public, private) tuple containing the RSA keys in PEM format. """ if not CRYPTO: # pragma: no cover raise exceptions.UnsupportedLibraryError(NO_CRYPTO_MSG) # Does 'encryped_pem' have the correct format? # This check will ensure 'pem' has the appropriate number # of objects and object types, and that all dict keys are properly named. # Raise 'securesystemslib.exceptions.FormatError' if the check fails. formats.PEMRSA_SCHEMA.check_match(pem) # If passed, does 'passphrase' have the correct format? if passphrase is not None: formats.PASSWORD_SCHEMA.check_match(passphrase) passphrase = passphrase.encode('utf-8') # Generate a pyca/cryptography key object from 'pem'. The generated # pyca/cryptography key contains the required export methods needed to # generate the PEM-formatted representations of the public and private RSA # key. try: private_key = load_pem_private_key(pem.encode('utf-8'), passphrase, backend=default_backend()) # pyca/cryptography's expected exceptions for 'load_pem_private_key()': # ValueError: If the PEM data could not be decrypted. # (possibly because the passphrase is wrong)." # TypeError: If a password was given and the private key was not encrypted. # Or if the key was encrypted but no password was supplied. # UnsupportedAlgorithm: If the private key (or if the key is encrypted with # an unsupported symmetric cipher) is not supported by the backend. except (ValueError, TypeError, UnsupportedAlgorithm) as e: # Raise 'securesystemslib.exceptions.CryptoError' and pyca/cryptography's # exception message. Avoid propogating pyca/cryptography's exception trace # to avoid revealing sensitive error. raise exceptions.CryptoError( 'RSA (public, private) tuple' ' cannot be generated from the encrypted PEM string: ' + str(e)) # Export the public and private halves of the pyca/cryptography RSA key # object. The (public, private) tuple returned contains the public and # private RSA keys in PEM format, as strings. # Extract the public & private halves of the RSA key and generate their # PEM-formatted representations. Return the key pair as a (public, private) # tuple, where each RSA is a string in PEM format. private_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()) # Need to generate the public key from the private one before serializing # to PEM format. public_key = private_key.public_key() public_pem = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo) return public_pem.decode(), private_pem.decode()
def create_rsa_encrypted_pem(private_key, passphrase): """ <Purpose> Return a string in PEM format (TraditionalOpenSSL), where the private part of the RSA key is encrypted using the best available encryption for a given key's backend. This is a curated (by cryptography.io) encryption choice and the algorithm may change over time. c.f. cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization/ #cryptography.hazmat.primitives.serialization.BestAvailableEncryption >>> public, private = generate_rsa_public_and_private(2048) >>> passphrase = 'secret' >>> encrypted_pem = create_rsa_encrypted_pem(private, passphrase) >>> securesystemslib.formats.PEMRSA_SCHEMA.matches(encrypted_pem) True <Arguments> private_key: The private key string in PEM format. passphrase: The passphrase, or password, to encrypt the private part of the RSA key. <Exceptions> securesystemslib.exceptions.FormatError, if the arguments are improperly formatted. securesystemslib.exceptions.CryptoError, if the passed RSA key cannot be deserialized by pyca cryptography. ValueError, if 'private_key' is unset. securesystemslib.exceptions.UnsupportedLibraryError, if the cryptography module is not available. <Returns> A string in PEM format (TraditionalOpenSSL), where the private RSA key is encrypted. Conforms to 'securesystemslib.formats.PEMRSA_SCHEMA'. """ if not CRYPTO: # pragma: no cover raise exceptions.UnsupportedLibraryError(NO_CRYPTO_MSG) # This check will ensure 'private_key' has the appropriate number # of objects and object types, and that all dict keys are properly named. # Raise 'securesystemslib.exceptions.FormatError' if the check fails. formats.PEMRSA_SCHEMA.check_match(private_key) # Does 'passphrase' have the correct format? formats.PASSWORD_SCHEMA.check_match(passphrase) # 'private_key' may still be a NULL string after the # 'securesystemslib.formats.PEMRSA_SCHEMA' so we need an additional check if len(private_key): try: private_key = load_pem_private_key(private_key.encode('utf-8'), password=None, backend=default_backend()) except ValueError: raise exceptions.CryptoError( 'The private key' ' (in PEM format) could not be deserialized.') else: raise ValueError('The required private key is unset.') encrypted_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.BestAvailableEncryption( passphrase.encode('utf-8'))) return encrypted_pem.decode()
def verify_rsa_signature(signature, signature_scheme, public_key, data): """ <Purpose> Determine whether the corresponding private key of 'public_key' produced 'signature'. verify_signature() will use the public key, signature scheme, and 'data' to complete the verification. >>> public, private = generate_rsa_public_and_private(2048) >>> data = b'The quick brown fox jumps over the lazy dog' >>> scheme = 'rsassa-pss-sha256' >>> signature, scheme = create_rsa_signature(private, data, scheme) >>> verify_rsa_signature(signature, scheme, public, data) True >>> verify_rsa_signature(signature, scheme, public, b'bad_data') False <Arguments> signature: A signature, as a string. This is the signature returned by create_rsa_signature(). signature_scheme: A string that indicates the signature scheme used to generate 'signature'. Currently supported RSA signature schemes are defined in `securesystemslib.keys.RSA_SIGNATURE_SCHEMES`. public_key: The RSA public key, a string in PEM format. data: Data used by securesystemslib.keys.create_signature() to generate 'signature'. 'data' (a string) is needed here to verify 'signature'. <Exceptions> securesystemslib.exceptions.FormatError, if 'signature', 'signature_scheme', 'public_key', or 'data' are improperly formatted. securesystemslib.exceptions.UnsupportedAlgorithmError, if the signature scheme used by 'signature' is not one supported by securesystemslib.keys.create_signature(). securesystemslib.exceptions.CryptoError, if the private key cannot be decoded or its key type is unsupported. securesystemslib.exceptions.UnsupportedLibraryError, if the cryptography module is not available. <Side Effects> pyca/cryptography's RSAPublicKey.verifier() called to do the actual verification. <Returns> Boolean. True if the signature is valid, False otherwise. """ if not CRYPTO: # pragma: no cover raise exceptions.UnsupportedLibraryError(NO_CRYPTO_MSG) # Does 'public_key' have the correct format? # This check will ensure 'public_key' conforms to # 'securesystemslib.formats.PEMRSA_SCHEMA'. Raise # 'securesystemslib.exceptions.FormatError' if the check fails. formats.PEMRSA_SCHEMA.check_match(public_key) # Does 'signature_scheme' have the correct format? formats.RSA_SCHEME_SCHEMA.check_match(signature_scheme) # Does 'signature' have the correct format? formats.PYCACRYPTOSIGNATURE_SCHEMA.check_match(signature) # What about 'data'? formats.DATA_SCHEMA.check_match(data) # Verify the RSASSA-PSS signature with pyca/cryptography. try: public_key_object = serialization.load_pem_public_key( public_key.encode('utf-8'), backend=default_backend()) digest_obj = digest_from_rsa_scheme(signature_scheme, 'pyca_crypto') # verify() raises 'cryptography.exceptions.InvalidSignature' if the # signature is invalid. 'salt_length' is set to the digest size of the # hashing algorithm. try: if signature_scheme.startswith('rsassa-pss'): public_key_object.verify( signature, data, padding.PSS(mgf=padding.MGF1(digest_obj.algorithm), salt_length=digest_obj.algorithm.digest_size), digest_obj.algorithm) elif signature_scheme.startswith('rsa-pkcs1v15'): public_key_object.verify(signature, data, padding.PKCS1v15(), digest_obj.algorithm) # The RSA_SCHEME_SCHEMA.check_match() above should have validated 'scheme'. # This is a defensive check check.. else: # pragma: no cover raise exceptions.UnsupportedAlgorithmError( 'Unsupported' ' signature scheme is specified: ' + repr(signature_scheme)) return True except InvalidSignature: return False # Raised by load_pem_public_key(). except (ValueError, UnsupportedAlgorithm) as e: raise exceptions.CryptoError( 'The PEM could not be' ' decoded successfully, or contained an unsupported key type: ' + str(e))
def create_rsa_signature(private_key, data, scheme='rsassa-pss-sha256'): """ <Purpose> Generate a 'scheme' signature. The signature, and the signature scheme used, is returned as a (signature, scheme) tuple. The signing process will use 'private_key' to generate the signature of 'data'. RFC3447 - RSASSA-PSS http://www.ietf.org/rfc/rfc3447.txt >>> public, private = generate_rsa_public_and_private(2048) >>> data = 'The quick brown fox jumps over the lazy dog'.encode('utf-8') >>> scheme = 'rsassa-pss-sha256' >>> signature, scheme = create_rsa_signature(private, data, scheme) >>> securesystemslib.formats.NAME_SCHEMA.matches(scheme) True >>> scheme == 'rsassa-pss-sha256' True >>> securesystemslib.formats.PYCACRYPTOSIGNATURE_SCHEMA.matches(signature) True <Arguments> private_key: The private RSA key, a string in PEM format. data: Data (string) used by create_rsa_signature() to generate the signature. scheme: The signature scheme used to generate the signature. <Exceptions> securesystemslib.exceptions.FormatError, if 'private_key' is improperly formatted. ValueError, if 'private_key' is unset. securesystemslib.exceptions.CryptoError, if the signature cannot be generated. securesystemslib.exceptions.UnsupportedLibraryError, if the cryptography module is not available. <Side Effects> pyca/cryptography's 'RSAPrivateKey.signer()' called to generate the signature. <Returns> A (signature, scheme) tuple, where the signature is a string and the scheme is one of the supported RSA signature schemes. For example: 'rsassa-pss-sha256'. """ if not CRYPTO: # pragma: no cover raise exceptions.UnsupportedLibraryError(NO_CRYPTO_MSG) # Does the arguments have the correct format? # If not, raise 'securesystemslib.exceptions.FormatError' if any of the # checks fail. formats.PEMRSA_SCHEMA.check_match(private_key) formats.DATA_SCHEMA.check_match(data) formats.RSA_SCHEME_SCHEMA.check_match(scheme) # Signing 'data' requires a private key. Currently supported RSA signature # schemes are defined in `securesystemslib.keys.RSA_SIGNATURE_SCHEMES`. signature = None # Verify the signature, but only if the private key has been set. The # private key is a NULL string if unset. Although it may be clearer to # explicitly check that 'private_key' is not '', we can/should check for a # value and not compare identities with the 'is' keyword. Up to this point # 'private_key' has variable size and can be an empty string. if not len(private_key): raise ValueError('The required private key is unset.') try: # 'private_key' (in PEM format) must first be converted to a # pyca/cryptography private key object before a signature can be # generated. private_key_object = load_pem_private_key(private_key.encode('utf-8'), password=None, backend=default_backend()) digest_obj = digest_from_rsa_scheme(scheme, 'pyca_crypto') if scheme.startswith('rsassa-pss'): # Generate an RSSA-PSS signature. Raise # 'securesystemslib.exceptions.CryptoError' for any of the expected # exceptions raised by pyca/cryptography. signature = private_key_object.sign( data, padding.PSS(mgf=padding.MGF1(digest_obj.algorithm), salt_length=digest_obj.algorithm.digest_size), digest_obj.algorithm) elif scheme.startswith('rsa-pkcs1v15'): # Generate an RSA-PKCS1v15 signature. Raise # 'securesystemslib.exceptions.CryptoError' for any of the expected # exceptions raised by pyca/cryptography. signature = private_key_object.sign(data, padding.PKCS1v15(), digest_obj.algorithm) # The RSA_SCHEME_SCHEMA.check_match() above should have validated 'scheme'. # This is a defensive check check.. else: # pragma: no cover raise 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 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 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 UnsupportedAlgorithm: # pragma: no cover raise exceptions.CryptoError( 'The private key is' ' encrypted with an unsupported algorithm.') return signature, scheme