# Copyright (c) 2023 Airbyte, Inc., all rights reserved. """Hashing utils for Airbyte.""" from __future__ import annotations import hashlib from collections.abc import Mapping HASH_SEED = "Airbyte:" """Additional seed for randomizing one-way hashed strings.""" def one_way_hash( obj: Mapping[str, str] | list[str] | object, /, ) -> str: """Return a one-way hash of the given string. To ensure a unique domain of hashes, we prepend a seed to the string before hashing. """ string_to_hash: str if isinstance(obj, Mapping): # Recursively sort and convert nested dictionaries to tuples of key-value pairs string_to_hash = str(sorted((k, one_way_hash(v)) for k, v in obj.items())) elif isinstance(obj, list): # Recursively hash elements of the list string_to_hash = str([one_way_hash(item) for item in obj]) else: # Convert the object to a string string_to_hash = str(obj) return hashlib.sha256((HASH_SEED + str(string_to_hash)).encode()).hexdigest()