kmip/services/server/crypto/engine.py
def derive_key(self,
                   derivation_method,
                   derivation_length,
                   derivation_data=None,
                   key_material=None,
                   hash_algorithm=None,
                   salt=None,
                   iteration_count=None,
                   encryption_algorithm=None,
                   cipher_mode=None,
                   padding_method=None,
                   iv_nonce=None):
        """
        Derive key data using a variety of key derivation functions.

        Args:
            derivation_method (DerivationMethod): An enumeration specifying
                the key derivation method to use. Required.
            derivation_length (int): An integer specifying the size of the
                derived key data in bytes. Required.
            derivation_data (bytes): The non-cryptographic bytes to be used
                in the key derivation process (e.g., the data to be encrypted,
                hashed, HMACed). Required in the general case. Optional if the
                derivation method is Hash and the key material is provided.
                Optional, defaults to None.
            key_material (bytes): The bytes of the key material to use for
                key derivation. Required in the general case. Optional if
                the derivation_method is HASH and derivation_data is provided.
                Optional, defaults to None.
            hash_algorithm (HashingAlgorithm): An enumeration specifying the
                hashing algorithm to use with the key derivation method.
                Required in the general case, optional if the derivation
                method specifies encryption. Optional, defaults to None.
            salt (bytes): Bytes representing a randomly generated salt.
                Required if the derivation method is PBKDF2. Optional,
                defaults to None.
            iteration_count (int): An integer representing the number of
                iterations to use when deriving key material. Required if
                the derivation method is PBKDF2. Optional, defaults to None.
            encryption_algorithm (CryptographicAlgorithm): An enumeration
                specifying the symmetric encryption algorithm to use for
                encryption-based key derivation. Required if the derivation
                method specifies encryption. Optional, defaults to None.
            cipher_mode (BlockCipherMode): An enumeration specifying the
                block cipher mode to use with the encryption algorithm.
                Required in in the general case if the derivation method
                specifies encryption and the encryption algorithm is
                specified. Optional if the encryption algorithm is RC4 (aka
                ARC4). Optional, defaults to None.
            padding_method (PaddingMethod): An enumeration specifying the
                padding method to use on the data before encryption. Required
                in in the general case if the derivation method specifies
                encryption and the encryption algorithm is specified. 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. Required in the general case if
                the derivation method specifies encryption and the encryption
                algorithm is specified. Optional, defaults to None. If
                required and not provided, it will be autogenerated.

        Returns:
            bytes: the bytes of the derived data

        Raises:
            InvalidField: Raised when cryptographic data and/or settings are
                unsupported or incompatible with the derivation method.

        Example:
            >>> engine = CryptographyEngine()
            >>> result = engine.derive_key(
            ...     derivation_method=enums.DerivationMethod.HASH,
            ...     derivation_length=16,
            ...     derivation_data=b'abc',
            ...     hash_algorithm=enums.HashingAlgorithm.MD5
            ... )
            >>> result
            b'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'
        """
        if derivation_method == enums.DerivationMethod.ENCRYPT:
            result = self.encrypt(
                encryption_algorithm=encryption_algorithm,
                encryption_key=key_material,
                plain_text=derivation_data,
                cipher_mode=cipher_mode,
                padding_method=padding_method,
                iv_nonce=iv_nonce
            )
            return result.get('cipher_text')
        else:
            # Handle key derivation functions that use hash algorithms

            # Set up the hashing algorithm
            if hash_algorithm is None:
                raise exceptions.InvalidField("Hash algorithm is required.")
            hashing_algorithm = self._encryption_hash_algorithms.get(
                hash_algorithm,
                None
            )
            if hashing_algorithm is None:
                raise exceptions.InvalidField(
                    "Hash algorithm '{0}' is not a supported hashing "
                    "algorithm.".format(hash_algorithm)
                )

            if derivation_method == enums.DerivationMethod.HMAC:
                df = hkdf.HKDF(
                    algorithm=hashing_algorithm(),
                    length=derivation_length,
                    salt=salt,
                    info=derivation_data,
                    backend=default_backend()
                )
                derived_data = df.derive(key_material)
                return derived_data
            elif derivation_method == enums.DerivationMethod.HASH:
                if None not in [derivation_data, key_material]:
                    raise exceptions.InvalidField(
                        "For hash-based key derivation, specify only "
                        "derivation data or key material, not both."
                    )
                elif derivation_data is not None:
                    hashing_data = derivation_data
                elif key_material is not None:
                    hashing_data = key_material
                else:
                    raise exceptions.InvalidField(
                        "For hash-based key derivation, derivation data or "
                        "key material must be specified."
                    )

                df = hashes.Hash(
                    algorithm=hashing_algorithm(),
                    backend=default_backend()
                )
                df.update(hashing_data)
                derived_data = df.finalize()
                return derived_data
            elif derivation_method == enums.DerivationMethod.PBKDF2:
                if salt is None:
                    raise exceptions.InvalidField(
                        "For PBKDF2 key derivation, salt must be specified."
                    )
                if iteration_count is None:
                    raise exceptions.InvalidField(
                        "For PBKDF2 key derivation, iteration count must be "
                        "specified."
                    )

                df = pbkdf2.PBKDF2HMAC(
                    algorithm=hashing_algorithm(),
                    length=derivation_length,
                    salt=salt,
                    iterations=iteration_count,
                    backend=default_backend()
                )
                derived_data = df.derive(key_material)
                return derived_data
            elif derivation_method == enums.DerivationMethod.NIST800_108_C:
                df = kbkdf.KBKDFHMAC(
                    algorithm=hashing_algorithm(),
                    mode=kbkdf.Mode.CounterMode,
                    length=derivation_length,
                    rlen=4,
                    llen=None,
                    location=kbkdf.CounterLocation.BeforeFixed,
                    label=None,
                    context=None,
                    fixed=derivation_data,
                    backend=default_backend()
                )
                derived_data = df.derive(key_material)
                return derived_data
            else:
                raise exceptions.InvalidField(
                    "Derivation method '{0}' is not a supported key "
                    "derivation method.".format(derivation_method)
                )
def derive_key(self,
                   derivation_method,
                   derivation_length,
                   derivation_data=None,
                   key_material=None,
                   hash_algorithm=None,
                   salt=None,
                   iteration_count=None,
                   encryption_algorithm=None,
                   cipher_mode=None,
                   padding_method=None,
                   iv_nonce=None):
        if derivation_method == enums.DerivationMethod.ENCRYPT:
            result = self.encrypt(
                encryption_algorithm=encryption_algorithm,
                encryption_key=key_material,
                plain_text=derivation_data,
                cipher_mode=cipher_mode,
                padding_method=padding_method,
                iv_nonce=iv_nonce
            )
            return result.get('cipher_text')
        else:
            # Handle key derivation functions that use hash algorithms

            # Set up the hashing algorithm
            if hash_algorithm is None:
                raise exceptions.InvalidField("Hash algorithm is required.")
            hashing_algorithm = self._encryption_hash_algorithms.get(
                hash_algorithm,
                None
            )
            if hashing_algorithm is None:
                raise exceptions.InvalidField(
                    "Hash algorithm '{0}' is not a supported hashing "
                    "algorithm.".format(hash_algorithm)
                )

            if derivation_method == enums.DerivationMethod.HMAC:
                df = hkdf.HKDF(
                    algorithm=hashing_algorithm(),
                    length=derivation_length,
                    salt=salt,
                    info=derivation_data,
                    backend=default_backend()
                )
                derived_data = df.derive(key_material)
                return derived_data
            elif derivation_method == enums.DerivationMethod.HASH:
                if None not in [derivation_data, key_material]:
                    raise exceptions.InvalidField(
                        "For hash-based key derivation, specify only "
                        "derivation data or key material, not both."
                    )
                elif derivation_data is not None:
                    hashing_data = derivation_data
                elif key_material is not None:
                    hashing_data = key_material
                else:
                    raise exceptions.InvalidField(
                        "For hash-based key derivation, derivation data or "
                        "key material must be specified."
                    )

                df = hashes.Hash(
                    algorithm=hashing_algorithm(),
                    backend=default_backend()
                )
                df.update(hashing_data)
                derived_data = df.finalize()
                return derived_data
            elif derivation_method == enums.DerivationMethod.PBKDF2:
                if salt is None:
                    raise exceptions.InvalidField(
                        "For PBKDF2 key derivation, salt must be specified."
                    )
                if iteration_count is None:
                    raise exceptions.InvalidField(
                        "For PBKDF2 key derivation, iteration count must be "
                        "specified."
                    )

                df = pbkdf2.PBKDF2HMAC(
                    algorithm=hashing_algorithm(),
                    length=derivation_length,
                    salt=salt,
                    iterations=iteration_count,
                    backend=default_backend()
                )
                derived_data = df.derive(key_material)
                return derived_data
            elif derivation_method == enums.DerivationMethod.NIST800_108_C:
                df = kbkdf.KBKDFHMAC(
                    algorithm=hashing_algorithm(),
                    mode=kbkdf.Mode.CounterMode,
                    length=derivation_length,
                    rlen=4,
                    llen=None,
                    location=kbkdf.CounterLocation.BeforeFixed,
                    label=None,
                    context=None,
                    fixed=derivation_data,
                    backend=default_backend()
                )
                derived_data = df.derive(key_material)
                return derived_data
            else:
                raise exceptions.InvalidField(
                    "Derivation method '{0}' is not a supported key "
                    "derivation method.".format(derivation_method)
                )
def derive_key ( self , derivation_method , derivation_length , derivation_data = None , key_material = None , hash_algorithm = None , salt = None , iteration_count = None , encryption_algorithm = None , cipher_mode = None , padding_method = None , iv_nonce = None ) : if derivation_method == enums . DerivationMethod . ENCRYPT : result = self . encrypt ( encryption_algorithm = encryption_algorithm , encryption_key = key_material , plain_text = derivation_data , cipher_mode = cipher_mode , padding_method = padding_method , iv_nonce = iv_nonce ) return result . get ( 'cipher_text' ) else : # Handle key derivation functions that use hash algorithms # Set up the hashing algorithm if hash_algorithm is None : raise exceptions . InvalidField ( "Hash algorithm is required." ) hashing_algorithm = self . _encryption_hash_algorithms . get ( hash_algorithm , None ) if hashing_algorithm is None : raise exceptions . InvalidField ( "Hash algorithm '{0}' is not a supported hashing " "algorithm." . format ( hash_algorithm ) ) if derivation_method == enums . DerivationMethod . HMAC : df = hkdf . HKDF ( algorithm = hashing_algorithm ( ) , length = derivation_length , salt = salt , info = derivation_data , backend = default_backend ( ) ) derived_data = df . derive ( key_material ) return derived_data elif derivation_method == enums . DerivationMethod . HASH : if None not in [ derivation_data , key_material ] : raise exceptions . InvalidField ( "For hash-based key derivation, specify only " "derivation data or key material, not both." ) elif derivation_data is not None : hashing_data = derivation_data elif key_material is not None : hashing_data = key_material else : raise exceptions . InvalidField ( "For hash-based key derivation, derivation data or " "key material must be specified." ) df = hashes . Hash ( algorithm = hashing_algorithm ( ) , backend = default_backend ( ) ) df . update ( hashing_data ) derived_data = df . finalize ( ) return derived_data elif derivation_method == enums . DerivationMethod . PBKDF2 : if salt is None : raise exceptions . InvalidField ( "For PBKDF2 key derivation, salt must be specified." ) if iteration_count is None : raise exceptions . InvalidField ( "For PBKDF2 key derivation, iteration count must be " "specified." ) df = pbkdf2 . PBKDF2HMAC ( algorithm = hashing_algorithm ( ) , length = derivation_length , salt = salt , iterations = iteration_count , backend = default_backend ( ) ) derived_data = df . derive ( key_material ) return derived_data elif derivation_method == enums . DerivationMethod . NIST800_108_C : df = kbkdf . KBKDFHMAC ( algorithm = hashing_algorithm ( ) , mode = kbkdf . Mode . CounterMode , length = derivation_length , rlen = 4 , llen = None , location = kbkdf . CounterLocation . BeforeFixed , label = None , context = None , fixed = derivation_data , backend = default_backend ( ) ) derived_data = df . derive ( key_material ) return derived_data else : raise exceptions . InvalidField ( "Derivation method '{0}' is not a supported key " "derivation method." . format ( derivation_method ) )
Derive key data using a variety of key derivation functions.

        Args:
            derivation_method (DerivationMethod): An enumeration specifying
                the key derivation method to use. Required.
            derivation_length (int): An integer specifying the size of the
                derived key data in bytes. Required.
            derivation_data (bytes): The non-cryptographic bytes to be used
                in the key derivation process (e.g., the data to be encrypted,
                hashed, HMACed). Required in the general case. Optional if the
                derivation method is Hash and the key material is provided.
                Optional, defaults to None.
            key_material (bytes): The bytes of the key material to use for
                key derivation. Required in the general case. Optional if
                the derivation_method is HASH and derivation_data is provided.
                Optional, defaults to None.
            hash_algorithm (HashingAlgorithm): An enumeration specifying the
                hashing algorithm to use with the key derivation method.
                Required in the general case, optional if the derivation
                method specifies encryption. Optional, defaults to None.
            salt (bytes): Bytes representing a randomly generated salt.
                Required if the derivation method is PBKDF2. Optional,
                defaults to None.
            iteration_count (int): An integer representing the number of
                iterations to use when deriving key material. Required if
                the derivation method is PBKDF2. Optional, defaults to None.
            encryption_algorithm (CryptographicAlgorithm): An enumeration
                specifying the symmetric encryption algorithm to use for
                encryption-based key derivation. Required if the derivation
                method specifies encryption. Optional, defaults to None.
            cipher_mode (BlockCipherMode): An enumeration specifying the
                block cipher mode to use with the encryption algorithm.
                Required in in the general case if the derivation method
                specifies encryption and the encryption algorithm is
                specified. Optional if the encryption algorithm is RC4 (aka
                ARC4). Optional, defaults to None.
            padding_method (PaddingMethod): An enumeration specifying the
                padding method to use on the data before encryption. Required
                in in the general case if the derivation method specifies
                encryption and the encryption algorithm is specified. 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. Required in the general case if
                the derivation method specifies encryption and the encryption
                algorithm is specified. Optional, defaults to None. If
                required and not provided, it will be autogenerated.

        Returns:
            bytes: the bytes of the derived data

        Raises:
            InvalidField: Raised when cryptographic data and/or settings are
                unsupported or incompatible with the derivation method.

        Example:
            >>> engine = CryptographyEngine()
            >>> result = engine.derive_key(
            ...     derivation_method=enums.DerivationMethod.HASH,
            ...     derivation_length=16,
            ...     derivation_data=b'abc',
            ...     hash_algorithm=enums.HashingAlgorithm.MD5
            ... )
            >>> result
            b'\x90\x01P\x98<\xd2O\xb0\xd6\x96?}(\xe1\x7fr'
Derive key data using a variety of key derivation functions .