from typing import Callable
import hashlib
import hmac


def salted_hmac(
    salt: str, value: str, key: str, *, algorithm: Callable = hashlib.sha1
) -> hmac.HMAC:
    """
    Generate a salted hmac given a secret key, a variable salt and the value to
    hash.
    :param salt: str
    :param value: str
    :param key: str
    :param algorithm:
    :return: hmac.HMAC
    """
    # We need to generate a derived key from our base key.  We can do this by
    # passing the salt and our base key through a pseudo-random function.
    derived_key: bytes = algorithm(salt.encode() + key.encode()).digest()
    # If len(salt + key) > block size of the hash algorithm, the above
    # line is redundant and could be replaced by derived_key = salt + key,
    # since the hmac module does the same thing for keys longer than the block
    # size. However, we should ensure that we *always* do this.
    return hmac.new(derived_key, msg=value.encode(), digestmod=algorithm)