docs: def generate_key_lists(master_secrets,  # type: Sequence[Union[bytes, str]]
                         num_identifier,  # type: int
                         key_size=DEFAULT_KEY_SIZE,  # type: int
                         salt=None,  # type: Optional[bytes]
                         info=None,  # type: Optional[bytes]
                         kdf='HKDF',  # type: str
                         hash_algo='SHA256'  # type: str
                         ):
      # type: (...) -> Tuple[Tuple[bytes, ...], ...]
      """
      Generates a derived key for each identifier for each master secret using a key derivation function (KDF).
  
      The only supported key derivation function for now is 'HKDF'.
  
      The previous key usage can be reproduced by setting kdf to 'legacy'.
      This is highly discouraged, as this strategy will map the same n-grams in different identifier
      to the same bits in the Bloom filter and thus does not lead to good results.
  
      :param master_secrets: a list of master secrets (either as bytes or strings)
      :param num_identifier: the number of identifiers
      :param key_size: the size of the derived keys
      :param salt: salt for the KDF as bytes
      :param info: optional context and application specific information as bytes
      :param kdf: the key derivation function algorithm to use
      :param hash_algo: the hashing algorithm to use (ignored if `kdf` is not 'HKDF')
      :return: The derived keys.
               First dimension is of size num_identifier, second dimension is the same as master_secrets.
               A key is represented as bytes.
      """
      keys = []
      try:
          for key in master_secrets:
              if isinstance(key, bytes):
                  keys.append(key)
              else:
                  keys.append(key.encode('UTF-8'))
      except AttributeError:
          raise TypeError("provided 'master_secrets' have to be either of type bytes or strings.")
      if kdf == 'HKDF':
          key_lists = [hkdf(key, num_identifier,
                            hash_algo=hash_algo, salt=salt,
                            info=info, key_size=key_size)
                       for key in keys]
          # regroup such that we get a tuple of keys for each identifier
          return tuple(zip(*key_lists))
      if kdf == 'legacy':
          return tuple(tuple(keys) for _ in range(num_identifier))
      raise ValueError('kdf: "{}" is not supported.'.format(kdf))