import typing from hashlib import new as hashlib_new from redshift_connector import InterfaceError if typing.TYPE_CHECKING: from hashlib import _Hash class ExtensibleDigest: """ Encodes user/password/salt information in the following way: SHA2(SHA2(password + user) + salt). """ @staticmethod def encode(client_nonce: bytes, password: bytes, salt: bytes, algo_name: str, server_nonce: bytes) -> bytes: """ Encodes user/password/salt information in the following way: SHA2(SHA2(password + user) + salt). :param client_nonce: The client nonce :type client_nonce: bytes :param password: The connecting user's password :type password: bytes :param salt: salt sent by the server :type salt: bytes :param algo_name: Algorithm name such as "SHA256" etc. :type algo_name: str :param server_nonce: random number generated by server :type server_nonce: bytes :return: the digest :rtype: bytes """ try: hl1: "_Hash" = hashlib_new(name=algo_name) except ImportError: raise InterfaceError("Unable to encode password with extensible hashing: {}".format(algo_name)) hl1.update(password) hl1.update(salt) pass_digest1: bytes = hl1.digest() # SHA2(user + password) hl2: "_Hash" = hashlib_new(name=algo_name) hl2.update(pass_digest1) hl2.update(server_nonce) hl2.update(client_nonce) pass_digest2 = hl2.digest() # SHA2(SHA2(password + user) + salt) return pass_digest2