Cryptopals zestaw 5 ćwiczenie 37

przez | 22 września 2021

Zgodnie z tradycją, w poprzednim zadaniu zapoznaliśmy się z jakąś super technologią a teraz będziemy poznawali sposób w w jaki można spróbować obejść jej zabezpieczenia. Ostatnio przyglądaliśmy się protokołowi SRP i to on będzie naszym dzisiejszym celem, wykorzystana technika będzie podobna do tych które poznaliśmy przy okazji ćwiczeń związanych z protokołem Diffiego-Hellmana, ale to chyba nie powinno być wielkim zaskoczeniem.

Nasze zadanie jest bardzo proste – musimy sprawdzić jak na zachowanie algorytmu generowania klucza po stronie serwera wpłynie przesłanie mu wartości A (klucz publiczny klienta) o wartościach 0, N, 2*N, 3*N itd., gdzie N to bardzo duża liczba pierwsza używana w tym protokole. Samo zadanie da się rozwiązać bez napisania choćby jednej linii kodu, wystarczy przeanalizować formułę użytą do obliczania klucza po stronie serwera. Sam kod przydaje się jedynie do potwierdzenia czy mieliśmy rację.

Klucz po stronie serwera obliczany jest według formuły:

S = (A * vu)b % N

Właściwe to nie musimy rozumieć co oznaczają wartość v,u,b czy N, żeby wiedzieć, że dla A=0 wartość S to 0, ponieważ dowolna wartość wymnożona przez 0 daje 0. W przypadku kiedy A jest z kolei wielokrotnością N możemy potrzebować dodatkowej chwili zastanowienia będziemy wiedzieli:

  1. Wielokrotność N wymnożona przez dowolną wartość da w wyniku również wielokrotność N.
  2. Wielokrotności wartości N podzielone modulo N dają w wyniku 0.

Jeżeli wiemy, że wartość S po stronie serwera wynosi 0 niezależnie od wartości pozostałych zmiennych to beż żadnych problemów jesteśmy w stanie odgadnąć wartość K potrzebną do uwierzytelnienia się na serwerze.

Poniżej kod sprawdzający czy wyciągnięte wnioski są prawidłowe (w tym wypadku sprawdzamy wartość A = N).

def s5challenge37():
    print("Challenge 37")
    config = {
        'N': 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff,
        'g': 2,
        'k': 3,
        'I': '[email protected]',
        'P': 'superpassword',
        'host': '127.0.0.1',
        'port': 40038
    }
    server_handle = threading.Thread(target=server36, args=(config,))
    server_handle.start()
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_a:
        socket_a.connect((config["host"], config["port"]))
        # Send I, A=g**a % N (a la Diffie Hellman)
        a = random.randrange(1, config["N"])
        A = config["N"] #power_mod(config["g"], a, config["N"])
        session_init_data = json.dumps(
            {
                "I": config['I'],
                "A": A
            }
        ).encode()
        socket_a.sendall(session_init_data)
        resp = wait_and_recv_data(socket_a, 4096)
        print("Client received: ", resp)
        json_data = json.loads(resp)
        # Compute string uH = SHA256(A|B), u = integer of uH
        B = json_data['B']
        SALT = json_data['salt']
        uH = hashlib.sha256((str(A)+str(B)).encode())
        u = int(uH.hexdigest(),16)
        # Generate string xH=SHA256(salt|password)
        # Convert xH to integer x somehow (put 0x on hexdigest)
        # Generate S = (B - k * g**x)**(a + u * x) % N
        # Generate K = SHA256(S)
        data_to_hash = str(SALT)+config['P']
        xH = hashlib.sha256(data_to_hash.encode())
        x = int(xH.hexdigest(), 16)
        S = 0
        K = hashlib.sha256(str(S).encode())
        print("CLIENT::S: ", S)
        print("CLIENT::K: ", K.hexdigest())
        hmac_obj = hmac.new(K.digest(), str(SALT).encode(), hashlib.sha256)
        socket_a.sendall(hmac_obj.digest())
        resp = wait_and_recv_data(socket_a, 4096)
        print("CLIENT::Srv response: ", resp)

    server_handle.join()

Kod dostępny w repozytorium: https://gitlab.com/akoltys/cryptopals .

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *