예제 #1
0
def handle_incoming_message_thread(recv):
    conn, addr = recv
    client_packet = proto.ClientPacket()
    try:
        client_packet.ParseFromString(conn.recv(TCP_BUFFER_SIZE))
        message_request = client_packet.messageRequest
        sender, message = get_decrypted_message(message_request)
        print("Sender: ", sender, " says:", message)
        message_response = proto.ClientPacket()
        message_response.messageResponse.success = True
        conn.send(message_response.SerializeToString())
        return
    except google.protobuf.message.DecodeError:
        print("Received an invalid proto!!")
예제 #2
0
def send_message_thread(message_args):
    global me
    global PIECE_SIZE
    if not logged_in:
        print("Please login first!!")
        return
    part_counter = 0
    receiver, message = message_args.split(" ", 1)
    receiver.replace(" ", "")
    message.strip()
    # Fetch userlist for freshness, maybe someone logged out.
    if not server_list_thread(True):
        print(
            "Unable to check freshness of the user, hoping for the best and sending a message!!"
        )
    if not chat_users.has_key(receiver):
        print("User", receiver, "not registered with the server!!")
        return
    client_packet = get_encrypted_message(receiver, message)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # Let's just assume our message is smaller than TCP_BUFFER_SIZE for now.
    sock.connect(chat_users[receiver])
    sock.send(client_packet.SerializeToString())
    message_response = proto.ClientPacket()
    message_response.ParseFromString(sock.recv(TCP_BUFFER_SIZE))
    if message_response.messageResponse.success:
        print("Message sent!!")
    else:
        print("Message send failure!!")
    sock.close()
예제 #3
0
def signup_thread(args):
    if ip == None or port == None:
        print(
            "Server information not provided!! Please set server info with connect command or check help."
        )
        return
    username, password = args.split(" ", 1)
    username.replace(" ", "")  # No spaces in username.
    password.replace(" ", "")  # No spaces in password.
    tls_state = setup_tls_with_server()
    if tls_state == None:
        return
    server_request = proto.ServerPacket()
    server_request.signupRequest.username = username
    server_request.signupRequest.password = password
    send_tls_packet(tls_state, server_request)
    client_packet = proto.ClientPacket()
    decrypted_packet = get_tls_packet(tls_state)
    if decrypted_packet == None:
        return
    client_packet.ParseFromString(decrypted_packet)
    server_signup_response = client_packet.signupResponse
    if server_signup_response.success:
        print("User", username, " signed up successfully!!")
    else:
        print("User", username, " signup FAILURE!!")
    tls_state[0].close()
예제 #4
0
def logout_thread():
    global username
    global password
    global logged_in
    if not logged_in:
        print("Please be logged in to  logout :P")
        return
    logged_in = False
    tls_state = setup_tls_with_server()
    if tls_state == None:
        return
    server_request = proto.ServerPacket()
    server_request.logoutRequest.username = username
    server_request.logoutRequest.password = password
    send_tls_packet(tls_state, server_request)
    client_packet = proto.ClientPacket()
    decrypted_packet = get_tls_packet(tls_state)
    if decrypted_packet == None:
        return
    client_packet.ParseFromString(decrypted_packet)
    server_logout_response = client_packet.logoutResponse
    if server_logout_response.success:
        print("Signout successful!!")
    else:
        print("Signout failure!!")
    tls_state[0].close()
예제 #5
0
def get_encrypted_message(dst, message):
    lookup = False
    ephemeral_key = None
    # Lookup state with dst
    if not kdf_sending_chain.has_key(dst):
        # Need to fetch identity key and prekey from server.
        prekey_response = fetch_prekey(dst)
        ik_dst = serialization.load_pem_public_key(str(
            prekey_response.identityKey),
                                                   backend=default_backend())
        dh1 = session_identity_key.exchange(ec.ECDH(), ik_dst)
        opk_dst = serialization.load_pem_public_key(str(
            prekey_response.preKey),
                                                    backend=default_backend())
        ephemeral_key = ec.generate_private_key(ec.SECP384R1(),
                                                default_backend())
        dh2 = ephemeral_key.exchange(ec.ECDH(), opk_dst)
        # chain_position = 0
        kdf_sending_chain[dst] = (dh1 + dh2, 0)
        lookup = True
    # Now we have a KDF chain for the sender!
    kdf_checkpoint = kdf_sending_chain[dst]
    secret, chain_position = kdf_sending_chain[dst]
    # Gen ck(n+1)
    hasher = hmac.HMAC(secret, hashes.SHA256(), backend=default_backend())
    hasher.update(hex(0))
    hmac0 = hasher.finalize()
    hasher = hmac.HMAC(secret, hashes.SHA256(), backend=default_backend())
    hasher.update(hex(1))
    hmac1 = hasher.finalize()
    derived_random = HKDF(
        algorithm=hashes.SHA256(),
        length=80,  # 32 message key, 32 hmac key, 16 IV
        salt=None,
        info=None,
        backend=default_backend()).derive(hmac1)
    symmetric_key_ephemeral = derived_random[0:32]
    hmac_key = derived_random[32:64]
    iv = derived_random[64:80]
    ct, cth = encrypt_and_hash(symmetric_key_ephemeral, hmac_key, iv, message)
    # Update KDF chain for next message.
    kdf_sending_chain[dst] = (hmac0, chain_position + 1)
    client_packet = proto.ClientPacket()
    serialized_identity_public_key = session_identity_key.public_key(
    ).public_bytes(encoding=serialization.Encoding.PEM,
                   format=serialization.PublicFormat.SubjectPublicKeyInfo)
    client_packet.messageRequest.identityKey = serialized_identity_public_key
    if ephemeral_key != None:
        serialized_ephemeral_key = ephemeral_key.public_key().public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo)
        client_packet.messageRequest.senderEphemeral = serialized_ephemeral_key
        client_packet.messageRequest.preKey = prekey_response.preKey
    client_packet.messageRequest.chainPosition = chain_position
    client_packet.messageRequest.payload = ct
    client_packet.messageRequest.oneDoesNotSimplyMAC = cth
    return client_packet
예제 #6
0
def login_thread(username, password):
    global listen_port
    global session_identity_key
    global pre_keys
    global logged_in
    session_identity_key = ec.generate_private_key(ec.SECP384R1(),
                                                   default_backend())
    serialized_identity_public_key = session_identity_key.public_key(
    ).public_bytes(encoding=serialization.Encoding.PEM,
                   format=serialization.PublicFormat.SubjectPublicKeyInfo)
    server_packet = proto.ServerPacket()
    server_packet.loginRequest.username = username
    server_packet.loginRequest.password = password
    server_packet.loginRequest.identityKey = serialized_identity_public_key
    # Add N oneTimePreKeys.
    for i in range(PREKEY_SIZE):
        pk = ec.generate_private_key(ec.SECP384R1(), default_backend())
        pk_pub = pk.public_key().public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo)
        pre_keys.append(pk)
        server_packet.loginRequest.oneTimePreKeys.append(pk_pub)
    # Wait for listen port information
    while listen_port == 0:
        time.sleep(1)
    server_packet.loginRequest.port = listen_port
    tls_state = setup_tls_with_server()
    if tls_state == None:
        return
    send_tls_packet(tls_state, server_packet)
    try:
        data = get_tls_packet(tls_state)
        if data == None:
            print("Failed to register with Server!! Please try again...")
            return
        client_packet = proto.ClientPacket()
        client_packet.ParseFromString(data)
        if (client_packet.loginResponse.acknowledge):
            print("Registered with Server!")
            global registered
            registered = True
            tls_state[0].close()
        else:
            print("Received response from Server ACK was unset!!")
    except socket.timeout:
        print("Failed to register with Server!! Please try again...")
        logged_in = False
        tls_state[0].close()
    except google.protobuf.message.DecodeError:
        print("Received an invalid proto as response!! Please try again...")
        logged_in = False
        tls_state[0].close()
    logged_in = True
    tls_state[0].close()
    server_list_thread(True)
예제 #7
0
def handle_signup(signupRequest, tls_state):
    # Storing password in a dictionary, not written to disk, so any comprimise of
    # RAM is as bad as comprimising a salted hash, if we were to use such a system.
    print "Signup request:", signupRequest.username
    success = True
    if not password_store.has_key(signupRequest.username):
        password_store[signupRequest.username] = signupRequest.password
    else:
        success = False
    client_packet = proto.ClientPacket()
    client_packet.signupResponse.success = success
    send_tls_packet(tls_state, client_packet)
예제 #8
0
def handle_list_thread(listRequest, tls_state):
    global registered_users
    print "List request!!"
    client_packet = proto.ClientPacket()
    i = 0
    connectedUsers = client_packet.listResponse.connectedUsers
    for user, details in registered_users.iteritems():
        connectedUsers.add()
        connectedUsers[i].username = user
        connectedUsers[i].userIP = "TEEHEE"
        connectedUsers[i].listenPort = 0
        i = i + 1
    send_tls_packet(tls_state, client_packet)
예제 #9
0
def handle_identity_request(identityRequest, tls_state):
    success = False
    client_packet = proto.ClientPacket()
    response = client_packet.identityResponse
    for user, ik in identity_key_store.items():
        if ik == identityRequest.identityKey:
            response.identityKey = ik
            response.username = user
            response.userIP, response.port = registered_users[user]
            success = True
            break
    response.success = success
    send_tls_packet(tls_state, client_packet)
예제 #10
0
def handle_prekey_request(prekeyRequest, tls_state):
    success = False
    client_packet = proto.ClientPacket()
    response = client_packet.prekeyResponse
    if registered_users.has_key(prekeyRequest.username):
        success = True
        response.username = prekeyRequest.username
        response.identityKey = identity_key_store[prekeyRequest.username]
        response.preKey = pre_key_store[prekeyRequest.username].pop()
        response.userIP, response.port = registered_users[
            prekeyRequest.username]
    response.success = success
    send_tls_packet(tls_state, client_packet)
예제 #11
0
def handle_logout(logoutRequest, tls_state):
    if not password_store.has_key(logoutRequest.username):
        print "Unidentified username!!"
        return
    if password_store[logoutRequest.username] != logoutRequest.password:
        print "Unauthorized logout for user:"******"using", logoutRequest.password
        return
    if not registered_users.has_key(logoutRequest.username):
        print "User", logoutRequest.username, "already logged out!!"
        return
    # delete things stored at login.
    del registered_users[logoutRequest.username]
    del identity_key_store[logoutRequest.username]
    del pre_key_store[logoutRequest.username]
    print "Successful logout!! Sending response..."
    client_packet = proto.ClientPacket()
    client_packet.logoutResponse.success = True
    send_tls_packet(tls_state, client_packet)
예제 #12
0
def handle_login(loginRequest, addr, tls_state):
    if not password_store.has_key(loginRequest.username):
        print "Unidentified username!!"
        return
    if password_store[loginRequest.username] != loginRequest.password:
        print "Unauthorized login for user:"******"using", loginRequest.password
        return
    print "New connection from:", loginRequest.username, "listening at:", loginRequest.port
    registered_users[loginRequest.username] = (addr[0], loginRequest.port)
    identity_key_store[loginRequest.username] = loginRequest.identityKey
    pre_key_store[loginRequest.username] = []
    for prekey in loginRequest.oneTimePreKeys:
        pre_key_store[loginRequest.username].append(prekey)
    print "Got identity key:", identity_key_store[loginRequest.username]
    print "Got", len(pre_key_store[loginRequest.username]), "prekeys"
    client_packet = proto.ClientPacket()
    client_packet.loginResponse.acknowledge = True
    send_tls_packet(tls_state, client_packet)
예제 #13
0
def fetch_prekey(username):
    tls_state = setup_tls_with_server()
    if tls_state == None:
        return
    server_request = proto.ServerPacket()
    username.replace(" ", "")
    server_request.prekeyRequest.username = username
    send_tls_packet(tls_state, server_request)
    client_packet = proto.ClientPacket()
    decrypted_packet = get_tls_packet(tls_state)
    if decrypted_packet == None:
        return
    client_packet.ParseFromString(decrypted_packet)
    prekey_response = client_packet.prekeyResponse
    if prekey_response.success:
        print("Successful fetch!!")
        chat_users[prekey_response.username] = (prekey_response.userIP,
                                                prekey_response.port)
    else:
        print("Failed fetching prekey for:", username)
    tls_state[0].close()
    return prekey_response
예제 #14
0
def fetch_identity(identity_pubkey):
    tls_state = setup_tls_with_server()
    if tls_state == None:
        return
    server_request = proto.ServerPacket()
    identity_pubkey.replace(" ", "")
    server_request.identityRequest.identityKey = identity_pubkey
    send_tls_packet(tls_state, server_request)
    client_packet = proto.ClientPacket()
    decrypted_packet = get_tls_packet(tls_state)
    if decrypted_packet == None:
        return
    client_packet.ParseFromString(decrypted_packet)
    identity_response = client_packet.identityResponse
    if identity_response.success:
        print("Successful identity lookup!!")
        visited = []
        for ik, user in identity_keys.items():
            if user == identity_response.username:
                if ik != identity_response.identityKey:
                    # Identity key updated, delete old kdf chain.
                    del kdf_sending_chain[identity_response.username]
                    del kdf_receiving_chain[identity_response.username]
                    visited.append(ik)
                else:
                    # We just fetched an IK for a user we already had, this shouldn't be possible.
                    print("Weird pkf, but ok.")
        for ik in visited:
            # Delete old ik associated to this identity.
            del identity_keys[ik]
        # Save the new ik to this username
        identity_keys[
            identity_response.identityKey] = identity_response.username
        chat_users[identity_response.username] = (identity_response.userIP,
                                                  identity_response.port)
    else:
        print("Failed to fetch identity for:", identity_pubkey)
    tls_state[0].close()
    return identity_response
예제 #15
0
def server_list_thread(quiet):
    global chat_users
    server_packet = proto.ServerPacket()
    server_packet.listRequest.askForList = True
    tls_state = setup_tls_with_server()
    if tls_state == None:
        return
    send_tls_packet(tls_state, server_packet)
    try:
        data = get_tls_packet(tls_state)
        if data == None:
            tls_state[0].close()
            return False
        client_packet = proto.ClientPacket()
        client_packet.ParseFromString(data)
        users_active = []
        for user in client_packet.listResponse.connectedUsers:
            users_active.append(user.username)
            if not chat_users.has_key(user.username):
                chat_users[user.username] = ()
        for u in set(chat_users.keys()) - set(users_active):
            del chat_users[u]
        if not quiet:
            print("Users registered:", chat_users.keys())
    except socket.timeout:
        if not quiet:
            print("Failed to fetch list!! Please try again...")
            tls_state[0].close()
            return False
    except google.protobuf.message.DecodeError:
        if not quiet:
            print(
                "Received an invalid proto as response!! Please try again...")
            tls_state[0].close()
            return False
    tls_state[0].close()