import socket
import json
import base64

# Fill in the right target here
HOST = "localhost"  # TODO
# HOST = "localhost"
PORT = 20204  # TODO


def parse_list_string(string_list):
    # Remove brackets and split
    return [item.strip().strip("'\"") for item in string_list.strip("[]").split(",")]


def decode_hash(hash_encode):
    ddata = {}
    for key, value in hash_encode.items():
        ddata[key] = base64.b64decode(value).hex()
    return ddata


def search_password(target_pass, rainbow_dict):
    for key, value in rainbow_dict.items():
        if value == target_pass:
            return key
    return None


def crack_hash(target):
    rainbow_dict = None
    with open("rainbow_table.json", "r") as f:
        rainbow_dict = json.load(f)
    hash_dict = decode_hash(rainbow_dict)
    return search_password(target, hash_dict)


def get_flag():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    s.connect((HOST, PORT))
    sf = s.makefile("rw")  # we use a file abstraction for the sockets
    print(sf.readline().rstrip("\n"))
    print("GET_SECRET Initiated")
    sf.write("GET_SECRET\n")
    sf.flush()
    print(sf.readline().rstrip("\n"))
    print("inserted Username admin")
    sf.write("admin\n")
    sf.flush()
    print(sf.readline().rstrip("\n"))
    print("inserted password 'rand123'")
    sf.write("ran123\n")
    sf.flush()
    output = sf.readline().rstrip("\n").split("Passwords do not match hashes ")[1]
    pos_pas = parse_list_string(output)
    password = crack_hash(pos_pas[0])
    print(f"Password found {password}")
    print(sf.readline().rstrip("\n"))
    sf.write("admin\n")
    sf.flush()
    print(sf.readline().rstrip("\n"))
    print(f"inserted password '{password}'")
    sf.write(f"{password}\n")
    sf.flush()
    print(sf.readline().rstrip("\n"))
    print(sf.readline().rstrip("\n"))
    sf.close()
    s.close()


if __name__ == "__main__":
    get_flag()
