Beispiel #1
0
def key_request(IP: str, port: int) -> Optional[RSA_key]:
    """Request the TTP's public key.
    
    PARAMETERS
    ==========
    IP: A string containing the IP address of the TTP.
    port: The port the TTP is listening on, as an integer.

    RETURNS
    =======
    On success, return an RSA_key object. If there was a communications error,
      return None.
    """
    sock = create_socket(IP, port)
    if sock is None:
        return None
    count = send(sock, b'k')
    if count != 1:
        return close_sock(sock)
    ttp_N = receive(sock, 128)
    if len(ttp_N) != 128:
        return close_sock(sock)
    ttp_d = receive(sock, 128)
    if len(ttp_d) != 128:
        return close_sock(sock)

    close_sock(sock)
    return RSA_key(pubkey=(bytes_to_int(ttp_N), bytes_to_int(ttp_d)))
def key_request(IP: str, port: int) -> Optional[RSA_key]:
    """Request the TTP's public key.
    
    PARAMETERS
    ==========
    IP: A string containing the IP address of the TTP.
    port: The port the TTP is listening on, as an integer.

    RETURNS
    =======
    On success, return an RSA_key object. If there was a communications error,
      return None.
    """
    sock = create_socket(IP, port)
    k_byte = 'k'.encode('utf-8')
    sentlen = send(sock, k_byte)
    if sentlen != 1:
        sock.close()
        return None
    ttp_n = receive(sock, 128)
    ttp_d = receive(sock, 128)
    if (len(ttp_d) != 128) or len(ttp_n) != 128:
        sock.close()
        return None
    sock.close()
    rsakey = RSA_key(pubkey=(bytes_to_int(ttp_n), bytes_to_int(ttp_d)))
    return rsakey
def sign_request( IP: str, port: int, server_name: str, server_key: RSA_key ) -> \
        Optional[tuple[int,int]]:
    """Sign the server's public key, via the TTP.
    
    PARAMETERS
    ==========
    IP: A string containing the IP address of the TTP.
    port: The port the TTP is listening on, as an integer.
    server_name: The server's name, as a string.
    server_key: The server's RSA key, as an RSA_key object.

    RETURNS
    =======
    On success, return (ttp_N, ttp_sig) as integers; the former is the TTP's
       RSA modulus, the latter the TTP's signature of the public key. If the 
       TTP could not be contacted, or any other error occurred, return None.
    """
    sock = create_socket(IP, port)
    if sock == None:
        return None

    sentlen = send(sock, b's')
    if sentlen != 1:
        sock.close()
        return None

    name = server_name.encode('utf-8')
    nameLength = len(name)
    nameLengthByte = int_to_bytes(nameLength, 1)
    sentlen = send(sock, nameLengthByte)
    if sentlen != 1:
        sock.close()
        return None

    sentlen = send(sock, name)
    if sentlen != len(name):
        sock.close()
        return None

    if server_key.N == None or server_key.e == None:
        sock.close()
        return None
    N_bytes = int_to_bytes(server_key.N, 128)
    sentlen = send(sock, N_bytes)
    if sentlen != 128:
        sock.close()
        return None
    e_bytes = int_to_bytes(server_key.e, 128)
    sentlen = send(sock, e_bytes)
    if sentlen != 128:
        sock.close()
        return None
    ttp_n = receive(sock, 128)
    ttp_sig = receive(sock, 128)
    if (len(ttp_sig) != 128) or len(ttp_n) != 128:
        sock.close()
        return None
    return (bytes_to_int(ttp_n), bytes_to_int(ttp_sig))
Beispiel #4
0
def sign_request( IP: str, port: int, server_name: str, server_key: RSA_key ) -> \
        Optional[tuple[int,int]]:
    """Sign the server's public key, via the TTP.
    
    PARAMETERS
    ==========
    IP: A string containing the IP address of the TTP.
    port: The port the TTP is listening on, as an integer.
    server_name: The server's name, as a string.
    server_key: The server's RSA key, as an RSA_key object.

    RETURNS
    =======
    On success, return (ttp_N, ttp_sig) as integers; the former is the TTP's
       RSA modulus, the latter the TTP's signature of the public key. If the 
       TTP could not be contacted, or any other error occurred, return None.
    """

    sock = create_socket(IP, port)
    if sock is None:
        return None

    count = send(sock, b's')
    if count != 1:
        return close_sock(sock)

    server_name_length = len(server_name.encode())
    server_name_length_bytes = int_to_bytes(server_name_length, 1)

    count = send(sock, server_name_length_bytes)
    if count != 1:
        return close_sock(sock)

    count = send(sock, server_name.encode())
    if count != server_name_length:
        return close_sock(sock)

    N_bytes = int_to_bytes(server_key.N, 128)
    count = send(sock, N_bytes)
    if count != 128:
        return close_sock(sock)

    e_bytes = int_to_bytes(server_key.e, 128)
    count = send(sock, e_bytes)
    if count != 128:
        return close_sock(sock)

    ttp_N = receive(sock, 128)
    if len(ttp_N) != 128:
        return close_sock(sock)

    ttp_sig = receive(sock, 128)
    if len(ttp_sig) != 128:
        return close_sock(sock)

    close_sock(sock)
    return (bytes_to_int(ttp_N), bytes_to_int(ttp_sig))
Beispiel #5
0
def client_protocol( ip: str, port: int, dh: DH_params, ttp_key: RSA_key, \
        username: str, pw: str, s: bytes, file_bytes: bytes ) -> \
        Optional[tuple[int,int]]:
    """Generate the shared key and send the file, from the client side.
       IMPORTANT: don't forget to send 'p'!

    PARAMETERS
    ==========
    ip: The IP address to connect to, as a string.
    port: The port to connect to, as an int.
    dh: A DH_params object.
    ttp_key: An RSA_key object.
    username: The username to register, as a string.
    pw: The password, as a string.
    s: The salt, a bytes object 16 bytes long. Must match what the server sends
       back.
    file_bytes: The plaintext to send to the server, as a bytes object.

    RETURNS
    =======
    If successful, return a tuple of the form (a, K_client), where both a and
       K_client are integers. If not, return None.
    """
    sock = create_socket(ip, port)
    if sock is None:
        return None

    count = send(sock, b'p')
    if count != 1:
        return close_sock(sock)

    encoded_username = username.encode()
    encoded_username_length = len(encoded_username)

    count = send(sock, int_to_bytes(encoded_username_length, 1))
    if count != 1:
        return close_sock(sock)

    count = send(sock, encoded_username)
    if count != encoded_username_length:
        return close_sock(sock)

    encoded_server_name_length_bytes = receive(sock, 1)
    if len(encoded_server_name_length_bytes) != 1:
        return close_sock(sock)
    encoded_server_name_length = bytes_to_int(encoded_server_name_length_bytes)

    server_cert = receive(sock, (encoded_server_name_length + 384))
    if len(server_cert) != (encoded_server_name_length + 384):
        return close_sock(sock)

    ttp_sig_rec = server_cert[-128:]
    server_cert = server_cert[:-128]

    server_name_bytes = server_cert[:-256]
    server_N_bytes = server_cert[-256:-128]
    server_e_bytes = server_cert[-128:]

    server_N = bytes_to_int(server_N_bytes)
    server_e = bytes_to_int(server_e_bytes)
    server_name = server_name_bytes.decode()
    server_key = RSA_key(pubkey=(server_N, server_e))

    digest = hashes.Hash(hashes.SHA3_512())
    digest.update(server_cert)
    t = digest.finalize()

    digest = hashes.Hash(hashes.SHA3_512())
    digest.update(t)
    t_prime = digest.finalize()

    S = bytes_to_int(t + t_prime) - ttp_key.N

    ttp_sig = ttp_key.sign(S)

    if ttp_sig_rec != ttp_sig:
        return close_sock(sock)

    #COPIED FROM A2 BELOW
    a = int.from_bytes(os.urandom(63), byteorder="big")

    A = calc_A(dh.N, dh.g, a)
    #A = int_to_bytes(A, 64)
    enc_A = server_key.encrypt(A)
    enc_A_bytes = int_to_bytes(A, 128)

    send(sock, enc_A_bytes)  #3
    print("Client: A = " + str(bytes_to_int(A)))
    s = receive(sock, 16)  #4
    print("Client: Recieved " + s.hex())
    B = receive(sock, 64)  #5
    print("Client: Recieved " + s.hex())

    u = calc_u(A, B)
    x = calc_x(s, pw)
    v = calc_A(dh.N, dh.g, x)

    #where is k? I already calculated it.......
    byteN = dh.N
    byteG = dh.g
    if type(byteN) == int:
        byteN = int_to_bytes(byteN, 64)
    if type(byteG) == int:
        byteG = int_to_bytes(byteG, 64)
    byteK = hash_bytes(byteN + byteG)
    k = int.from_bytes(byteK, "big")

    K_client = calc_K_client(N, B, k, v, a, u, x)

    M1 = calc_M1(A, B, K_client)
    send(sock, M1)  #6
    print("Client: M1 = " + M1.hex())

    M2 = receive(sock, 32)  #7
    print("Client: Recieved " + M2.hex())
    M2check = calc_M2(A, M1, K_client)
    if M2 != M2check:
        return close_sock(sock)

    K_client_bytes = int_to_bytes(K_client, 64)
    AES_key = K_client_bytes[:32]
    HMAC_key = K_client_bytes[32:]
    encrypted_file_bytes = pad_encrypt_then_HMAC(
        file_bytes, AES_key, HMAC_key
    )  #this might now work, might need to break up file and only pad final block

    encrypted_file_bytes_length = len(encrypted_file_bytes)
    encrypted_file_bytes_length_bytes = int_to_bytes(
        encrypted_file_bytes_length, 4)

    count = send(sock, encrypted_file_bytes_length_bytes)
    if count != 4:
        return close_sock(sock)

    count = send(sock, encrypted_file_bytes)
    if count != encrypted_file_bytes_length:
        return close_sock(sock)

    close_sock(sock)
    return (a, K_client)
Beispiel #6
0
        def server_loop(IP,
                        port,
                        dh,
                        key,
                        server_name,
                        output_file,
                        verbose=False):

            database = dict()  # for tracking registered users

            if verbose:
                print(f"Server: Retrieving a signature of our key.",
                      flush=True)
            result = sign_request(*ttp_addr, server_name, key)
            if result is None:
                print(f"Server: Could not get a signature. Quitting.",
                      flush=True)
                return

            ttp_N, ttp_sig = result
            if verbose:
                print(f"Server: Finished all preparations, ready to listen.",
                      flush=True)

            sock = create_socket(IP, port, listen=True)
            if sock is None:
                if verbose:
                    print(f"Server: Could not create socket, exiting.",
                          flush=True)
                return

            if verbose:
                print(f"Server: Beginning connection loop.", flush=True)
            while True:

                (client, client_address) = sock.accept()
                if verbose:
                    print(f"Server: Got connection from {client_address}.",
                          flush=True)

                mode = receive(client, 1)
                if len(mode) != 1:
                    if verbose:
                        print(
                            f"Server: Socket error with client, closing it and waiting for another connection.",
                            flush=True)
                    client.shutdown(socket.SHUT_RDWR)
                    client.close()
                    continue

                if mode == b'q':
                    if verbose:
                        print(f"Server: Asked to quit. Shutting down.",
                              flush=True)
                    client.shutdown(socket.SHUT_RDWR)
                    client.close()
                    sock.shutdown(socket.SHUT_RDWR)
                    sock.close()
                    return

                elif mode == b'r':
                    if verbose:
                        print(f"Server: Asked to register by the Client.",
                              flush=True)

                    temp = server_register(client, dh.N, dh.g, database)
                    if (temp is None) and verbose:
                        print(
                            f"Server: Registration failed, closing socket and waiting for another connection.",
                            flush=True)
                    elif temp is not None:
                        if verbose:
                            print(
                                f"Server: Registration complete, current users: {[x for x in temp]}.",
                                flush=True)
                        database = temp

                elif mode == b'p':
                    if verbose:
                        print(f"Server: Asked to share a file by a Client.",
                              flush=True)

                    temp = server_protocol(client, dh, key, server_name,
                                           ttp_sig, database)
                    if (temp is None) and verbose:
                        print(
                            f"Server: Protocol failed, closing socket and waiting for another connection.",
                            flush=True)
                    elif (type(temp) == tuple) and (len(temp) == 5):
                        if verbose:
                            print(
                                f"Server: Protocol complete, negotiated shared key for {temp[0]}.",
                                flush=True)
                            print(
                                f"Server:  AES key is {temp[2].hex()}, HMAC key is {temp[3].hex()}.",
                                flush=True)

                        # write out the file
                        output_file.write(temp[4])
                        output_file.close()
Beispiel #7
0
        def ttp_loop(IP, port, key, verbose=False):

            database = dict()  # for tracking signed keys

            sock = create_socket(IP, port, listen=True)
            if sock is None:
                if verbose:
                    print(f"TTP: Could not create socket, exiting.",
                          flush=True)
                return

            if verbose:
                print(f"TTP: Beginning connection loop.", flush=True)
            while True:

                (client, client_address) = sock.accept()
                if verbose:
                    print(f"TTP: Got connection from {client_address}.",
                          flush=True)

                mode = receive(client, 1)
                if len(mode) != 1:
                    if verbose:
                        print(
                            f"TTP: Socket error with client, closing it and waiting for another connection.",
                            flush=True)
                    client.shutdown(socket.SHUT_RDWR)
                    client.close()
                    continue

                if mode == b'q':
                    if verbose:
                        print(f"TTP: Asked to quit by client. Shutting down.",
                              flush=True)
                    client.shutdown(socket.SHUT_RDWR)
                    client.close()
                    sock.shutdown(socket.SHUT_RDWR)
                    sock.close()
                    return

                elif mode == b's':
                    if verbose:
                        print(f"TTP: Asked to sign by a Server.", flush=True)

                    temp = ttp_sign(client, key, database)
                    if (temp is None) and verbose:
                        print(
                            f"TTP: Signing failed, closing socket and waiting for another connection.",
                            flush=True)
                    elif type(temp) is dict:
                        if verbose:
                            print(
                                f"TTP: Signing complete, current Servers: {[x for x in temp]}.",
                                flush=True)
                        database = temp

                elif mode == b'k':
                    if verbose:
                        print(f"TTP: Asked for our public key.", flush=True)

                    ttp_sendkey(client, key)
Beispiel #8
0
    # finally, the quitting routine
    result = None  # reset this value

    if args.quit:
        if client_thr is not None:
            if args.verbose:
                print(f"Quit: Waiting for the client to complete first.",
                      flush=True)
            client_thr.join()

        if args.verbose:
            print("Quit: Attempting to kill the server.", flush=True)

        # no need for threading here
        sock = create_socket(*server_addr)
        if sock is None:
            if args.verbose:
                print(
                    f"Quit: Could not connect to the server to send the kill signal.",
                    flush=True)
        else:
            count = send(sock, b'q')
            if count != 1:
                if args.verbose:
                    print(f"Quit: Socket error when sending the signal.",
                          flush=True)
            elif args.verbose:
                print(f"Quit: Signal sent successfully.", flush=True)

            sock.shutdown(socket.SHUT_RDWR)
def client_protocol( ip: str, port: int, dh: DH_params, ttp_key: RSA_key, \
        username: str, pw: str, s: bytes, file_bytes: bytes ) -> \
        Optional[tuple[int,int]]:
    """Generate the shared key and send the file, from the client side.
       IMPORTANT: don't forget to send 'p'!

    PARAMETERS
    ==========
    ip: The IP address to connect to, as a string.
    port: The port to connect to, as an int.
    dh: A DH_params object.
    ttp_key: An RSA_key object.
    username: The username to register, as a string.
    pw: The password, as a string.
    s: The salt, a bytes object 16 bytes long. Must match what the server sends
       back.
    file_bytes: The plaintext to send to the server, as a bytes object.

    RETURNS
    =======
    If successful, return a tuple of the form (a, K_client), where both a and
       K_client are integers. If not, return None.
    """
    try:
        sock = create_socket(ip, port)
        # if sock==None:
        #     return None
        p = 'p'.encode('utf-8')
        send(sock, p)
        usernameUTF = username.encode('utf-8')
        send(sock, int_to_bytes(len(usernameUTF), 1))
        send(sock, usernameUTF)

        serverNameLen1 = receive(sock, 1)
        serverNameLen = bytes_to_int(serverNameLen1)
        serverNameBytes = receive(sock, serverNameLen)
        serverName = serverNameBytes.decode('utf-8')
        servN_bytes = receive(sock, 128)
        serve_bytes = receive(sock, 128)

        servN = bytes_to_int(servN_bytes)
        serve = bytes_to_int(serve_bytes)
        server_key = RSA_key(pubkey=(servN, serve))

        ttpSig_bytes = receive(sock, 128)
        NameNe = serverNameBytes + servN_bytes + serve_bytes
        ttpSign = bytes_to_int(ttpSig_bytes)
        digest = hashes.Hash(hashes.SHA3_512())
        digest.update(NameNe)
        t = digest.finalize()
        digest = hashes.Hash(hashes.SHA3_512())
        digest.update(t)
        tdash = digest.finalize()
        tFinal = bytes_to_int(t + tdash)
        verSig = pow(tFinal, ttp_key.d, ttp_key.N)

        # verify
        if (verSig != ttpSign):
            sock.close()
            return None
        N = dh.N
        g = dh.g
        a = random.randint(0, N - 1)
        A = calc_A(N, g, a)
        encA = server_key.encrypt(A)
        encABytes = int_to_bytes(encA, 128)
        sentLen = send(sock, encABytes)

        salt = receive(sock, 16)

        if salt != s:
            sock.close()
            return None
        B = receive(sock, 64)
        # calc u
        u = calc_u(A, B)

        k = calc_u(N, g)

        # calc x
        x = calc_x(s, pw)

        # calc v
        v = pow(g, x, N)
        # calc K_client
        k_client = calc_K_client(N, B, k, v, a, u, x)
        # calc M1 and send
        M1 = calc_M1(A, B, k_client)
        sentLen = send(sock, M1)
        if sentLen < len(M1):
            sock.close()
            return None

        M2 = receive(sock, 32)
        clientM2 = calc_M2(A, M1, k_client)
        if (M2 == clientM2):
            k_client_bytes = int_to_bytes(k_client, 64)
            aesKey = k_client_bytes[:32]
            hmacKey = k_client_bytes[32:]
            cyphertext = pad_encrypt_then_HMAC(file_bytes, aesKey, hmacKey)
            cypherLen = int_to_bytes(len(cyphertext), 4)
            send(sock, cypherLen)
            send(sock, cyphertext)
            sock.close()
            return (A, k_client)
        sock.close()
        return None
    except:
        return None