kmip/services/server/crypto/engine.py
def _encrypt_symmetric(
            self,
            encryption_algorithm,
            encryption_key,
            plain_text,
            cipher_mode=None,
            padding_method=None,
            iv_nonce=None):
        """
        Encrypt data using symmetric encryption.

        Args:
            encryption_algorithm (CryptographicAlgorithm): An enumeration
                specifying the symmetric encryption algorithm to use for
                encryption.
            encryption_key (bytes): The bytes of the symmetric key to use for
                encryption.
            plain_text (bytes): The bytes to be encrypted.
            cipher_mode (BlockCipherMode): An enumeration specifying the
                block cipher mode to use with the encryption algorithm.
                Required in the general case. Optional if the encryption
                algorithm is RC4 (aka ARC4). If optional, defaults to None.
            padding_method (PaddingMethod): An enumeration specifying the
                padding method to use on the data before encryption. Required
                if the cipher mode is for block ciphers (e.g., CBC, ECB).
                Optional otherwise, defaults to None.
            iv_nonce (bytes): The IV/nonce value to use to initialize the mode
                of the encryption algorithm. Optional, defaults to None. If
                required and not provided, it will be autogenerated and
                returned with the cipher text.

        Returns:
            dict: A dictionary containing the encrypted data, with at least
                the following key/value fields:
                * cipher_text - the bytes of the encrypted data
                * iv_nonce - the bytes of the IV/counter/nonce used if it
                    was needed by the encryption scheme and if it was
                    automatically generated for the encryption

        Raises:
            InvalidField: Raised when the algorithm is unsupported or the
                encryption key is incompatible with the algorithm.
            CryptographicFailure: Raised when the key generation process
                fails.
        """

        # Set up the algorithm
        algorithm = self._symmetric_key_algorithms.get(
            encryption_algorithm,
            None
        )
        if algorithm is None:
            raise exceptions.InvalidField(
                "Encryption algorithm '{0}' is not a supported symmetric "
                "encryption algorithm.".format(encryption_algorithm)
            )
        try:
            algorithm = algorithm(encryption_key)
        except Exception as e:
            self.logger.exception(e)
            raise exceptions.CryptographicFailure(
                "Invalid key bytes for the specified encryption algorithm."
            )

        # Set up the cipher mode if needed
        return_iv_nonce = False
        if encryption_algorithm == enums.CryptographicAlgorithm.RC4:
            mode = None
        else:
            if cipher_mode is None:
                raise exceptions.InvalidField("Cipher mode is required.")
            mode = self._modes.get(cipher_mode, None)
            if mode is None:
                raise exceptions.InvalidField(
                    "Cipher mode '{0}' is not a supported mode.".format(
                        cipher_mode
                    )
                )
            if hasattr(mode, 'initialization_vector') or \
                    hasattr(mode, 'nonce'):
                if iv_nonce is None:
                    iv_nonce = os.urandom(algorithm.block_size // 8)
                    return_iv_nonce = True
                mode = mode(iv_nonce)
            else:
                mode = mode()

        # Pad the plain text if needed (separate methods for testing purposes)
        if cipher_mode in [
                enums.BlockCipherMode.CBC,
                enums.BlockCipherMode.ECB
        ]:
            plain_text = self._handle_symmetric_padding(
                self._symmetric_key_algorithms.get(encryption_algorithm),
                plain_text,
                padding_method
            )

        # Encrypt the plain text
        cipher = ciphers.Cipher(algorithm, mode, backend=default_backend())
        encryptor = cipher.encryptor()
        cipher_text = encryptor.update(plain_text) + encryptor.finalize()

        if return_iv_nonce:
            return {
                'cipher_text': cipher_text,
                'iv_nonce': iv_nonce
            }
        else:
            return {'cipher_text': cipher_text}
def _encrypt_symmetric(
            self,
            encryption_algorithm,
            encryption_key,
            plain_text,
            cipher_mode=None,
            padding_method=None,
            iv_nonce=None):
        """
        Encrypt data using symmetric encryption.

        Args:
            encryption_algorithm (CryptographicAlgorithm): An enumeration
                specifying the symmetric encryption algorithm to use for
                encryption.
            encryption_key (bytes): The bytes of the symmetric key to use for
                encryption.
            plain_text (bytes): The bytes to be encrypted.
            cipher_mode (BlockCipherMode): An enumeration specifying the
                block cipher mode to use with the encryption algorithm.
                Required in the general case. Optional if the encryption
                algorithm is RC4 (aka ARC4). If optional, defaults to None.
            padding_method (PaddingMethod): An enumeration specifying the
                padding method to use on the data before encryption. Required
                if the cipher mode is for block ciphers (e.g., CBC, ECB).
                Optional otherwise, defaults to None.
            iv_nonce (bytes): The IV/nonce value to use to initialize the mode
                of the encryption algorithm. Optional, defaults to None. If
                required and not provided, it will be autogenerated and
                returned with the cipher text.

        Returns:
            dict: A dictionary containing the encrypted data, with at least
                the following key/value fields:
                * cipher_text - the bytes of the encrypted data
                * iv_nonce - the bytes of the IV/counter/nonce used if it
                    was needed by the encryption scheme and if it was
                    automatically generated for the encryption

        Raises:
            InvalidField: Raised when the algorithm is unsupported or the
                encryption key is incompatible with the algorithm.
            CryptographicFailure: Raised when the key generation process
                fails.
        """

        # Set up the algorithm
        algorithm = self._symmetric_key_algorithms.get(
            encryption_algorithm,
            None
        )
        if algorithm is None:
            raise exceptions.InvalidField(
                "Encryption algorithm '{0}' is not a supported symmetric "
                "encryption algorithm.".format(encryption_algorithm)
            )
        try:
            algorithm = algorithm(encryption_key)
        except Exception as e:
            self.logger.exception(e)
            raise exceptions.CryptographicFailure(
                "Invalid key bytes for the specified encryption algorithm."
            )

        # Set up the cipher mode if needed
        return_iv_nonce = False
        if encryption_algorithm == enums.CryptographicAlgorithm.RC4:
            mode = None
        else:
            if cipher_mode is None:
                raise exceptions.InvalidField("Cipher mode is required.")
            mode = self._modes.get(cipher_mode, None)
            if mode is None:
                raise exceptions.InvalidField(
                    "Cipher mode '{0}' is not a supported mode.".format(
                        cipher_mode
                    )
                )
            if hasattr(mode, 'initialization_vector') or \
                    hasattr(mode, 'nonce'):
                if iv_nonce is None:
                    iv_nonce = os.urandom(algorithm.block_size // 8)
                    return_iv_nonce = True
                mode = mode(iv_nonce)
            else:
                mode = mode()

        # Pad the plain text if needed (separate methods for testing purposes)
        if cipher_mode in [
                enums.BlockCipherMode.CBC,
                enums.BlockCipherMode.ECB
        ]:
            plain_text = self._handle_symmetric_padding(
                self._symmetric_key_algorithms.get(encryption_algorithm),
                plain_text,
                padding_method
            )

        # Encrypt the plain text
        cipher = ciphers.Cipher(algorithm, mode, backend=default_backend())
        encryptor = cipher.encryptor()
        cipher_text = encryptor.update(plain_text) + encryptor.finalize()

        if return_iv_nonce:
            return {
                'cipher_text': cipher_text,
                'iv_nonce': iv_nonce
            }
        else:
            return {'cipher_text': cipher_text}
Encrypt data using symmetric encryption.

        Args:
            encryption_algorithm (CryptographicAlgorithm): An enumeration
                specifying the symmetric encryption algorithm to use for
                encryption.
            encryption_key (bytes): The bytes of the symmetric key to use for
                encryption.
            plain_text (bytes): The bytes to be encrypted.
            cipher_mode (BlockCipherMode): An enumeration specifying the
                block cipher mode to use with the encryption algorithm.
                Required in the general case. Optional if the encryption
                algorithm is RC4 (aka ARC4). If optional, defaults to None.
            padding_method (PaddingMethod): An enumeration specifying the
                padding method to use on the data before encryption. Required
                if the cipher mode is for block ciphers (e.g., CBC, ECB).
                Optional otherwise, defaults to None.
            iv_nonce (bytes): The IV/nonce value to use to initialize the mode
                of the encryption algorithm. Optional, defaults to None. If
                required and not provided, it will be autogenerated and
                returned with the cipher text.

        Returns:
            dict: A dictionary containing the encrypted data, with at least
                the following key/value fields:
                * cipher_text - the bytes of the encrypted data
                * iv_nonce - the bytes of the IV/counter/nonce used if it
                    was needed by the encryption scheme and if it was
                    automatically generated for the encryption

        Raises:
            InvalidField: Raised when the algorithm is unsupported or the
                encryption key is incompatible with the algorithm.
            CryptographicFailure: Raised when the key generation process
                fails.