Exemple #1
0
def notify_all_online_clients_about_new_list(client_dict, s,
                                             new_client_Details, username):
    clientList = []
    new_client_temp = ClientDetailsInTransit(username, new_client_Details.port,
                                             new_client_Details.ip)
    clientList.append(new_client_temp)

    for client in client_dict:
        clientDetails = client_dict[client]
        if clientDetails.is_authenticated and client != username:
            byte_clientList = pickle.dumps(clientList)
            shared_key = clientDetails.key
            shared_nonce = clientDetails.nonce
            encrypted_clientList = encrypt_with_shared_key(
                shared_key, byte_clientList, shared_nonce)
            message_transit_dict = {
                'message_type': 'NEW_CLIENT_NOTIFICATION',
                'message': encrypted_clientList,
                'hmac': 0
            }
            data = pickle.dumps(message_transit_dict)
            s.sendto(data, (clientDetails.ip, clientDetails.port))
def process_client_messages(data, client_dict, address, s, s_key, nonce):
    # obtain the original Message Dict sent by the client
    message_dict = pickle.loads(data)
    message_type = message_dict['message_type']
    # iff message type is Req to talk
    # iff the message is from a source which is in client dict then send back a nonce to the sender
    # set next message expected to SESSION_KEY_FROM_SERVER from the sender of this request
    if message_type == 'REQ_TO_TALK':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        if username is not None:
            client_details = client_dict[username]
            client_details.set_next_messages_expected(
                'SESSION_KEY_FROM_SERVER')
            cookie = os.urandom(16)
            client_details.set_cookie(cookie)
            client_dict[username] = client_details
            send_message_to_client('NONCE', cookie, s, address, 0)
        else:
            client_details = Client_Details()
            client_details.set_ip(address[0])
            client_details.set_port(address[1])
            client_details.set_next_messages_expected(
                'SESSION_KEY_FROM_SERVER')
            client_details.set_cookie(10)
            client_dict['new_client'] = client_details
            send_message_to_client('NONCE', 10, s, address, 0)

    # iff message type is NONCE
    # Check if the message is from a source recoginizable to the client
    # if the message type is an expected message from a client at the source
    # then send a MESSAGE_REQ to the server

    elif message_type == 'NONCE':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        if username is not None:
            client_details = client_dict[username]
            if is_message_type_ok(message_type, client_details):
                request_dict = {
                    'CLIENT_KEY_REQUIRED_FOR': username,
                    'NONCE': message_dict['message']
                }
                send_encrypted_message_to_server('MESSAGE_REQ', request_dict,
                                                 s, s_key, nonce)
                #send_message("MESSAGE_REQ","",username,s)
                #client_details.set_next_messages_expected('DH-KEY-C')
                client_dict[username] = client_details

    # iff the message type is DH-KEY-C
    # iff the message type is in the expected list of messages from the source then
    # decrypt the DH-KEY of the client from the payload if the message
    # compute the diffie hellman shared key
    # Encrypt a random number and send it back to the client
    elif message_type == 'DH-KEY-C':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        if username is not None:
            client_details = client_dict[username]
            if is_message_type_ok(message_type, client_details):

                #decrypt_message using common key
                encrypted_sender_dh_key = message_dict['message']
                common_key = client_details.key
                common_nonce = client_details.nonce
                d1 = client_details.dh_key

                byte_dh_key = decrypt_with_common_key(common_key,
                                                      encrypted_sender_dh_key,
                                                      common_nonce)

                #verify the hmac for integrity check
                if not verify_hmac_with_common_key(common_key, byte_dh_key,
                                                   message_dict['hmac']):
                    print "Hmac verification failed"
                    return

                # convert back to the format
                d2_pubkey = pickle.loads(byte_dh_key)

                shared_key_with_client = d1.gen_shared_key(d2_pubkey)

                shared_nonce = client_details.nonce_client

                #encrypt a random number and store it in the cookie
                random_number = os.urandom(16)
                client_details.set_cookie(random_number)

                encrypted_random_number = encrypt_with_shared_key(
                    shared_key_with_client, random_number, shared_nonce)
                h_mac = get_hmac_from_shared_key(shared_key_with_client,
                                                 random_number)
                send_message_to_client("CLIENT_CHALLENGE",
                                       encrypted_random_number, s, address,
                                       h_mac)
                client_details.set_next_messages_expected(
                    'CLIENT_RESPONSE_CHALLENGE')
                client_details.set_key(shared_key_with_client)
                client_details.set_nonce(shared_nonce)
                client_dict[username] = client_details

    # if the message type is SESSION_KEY_FROM_SERVER
    # iff the message type is expected from the client then
    # Obtain the ticket from the message and decrypt the ticket
    # Check if the nonce inside the ticket is the same as the nonce it sent
    # to the sender of this message
    # then encrypt the Diffie hellman public key and send it back to the client
    # also compute the shared diffie hellman key from the public key the sender of this
    # message sent
    elif message_type == 'SESSION_KEY_FROM_SERVER':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        if username is not None:
            client_details = client_dict[username]
            if is_message_type_ok(message_type, client_details):

                # decrypt the message from the message_dict
                response_dict = message_dict['message']
                encrypted_ticket = response_dict['COMMON_KEY_TICKET']
                byte_ticket = decrypt_with_shared_key(s_key, encrypted_ticket,
                                                      nonce)
                ticket = get_original_message_from_byte(byte_ticket)
                common_key = ticket['common_key']
                common_nonce = ticket['common_nonce']
                client_name = ticket['key_for']
                nonce_for_verification = ticket['NONCE_FOR_VERIFICATION']

                if nonce_for_verification != client_details.cookie:
                    print "Nonce sent to Client not same as not recieved inside ticket"
                    return

                if client_name != username:
                    return

                d1 = pyDH.DiffieHellman(5)
                d1_pubkey = d1.gen_public_key()

                decoded_key = pickle.dumps(d1_pubkey)

                # encrypt the Public key of the diffie hellman exchange with common key and nonce in the ticket
                encrypted_dh_key = encrypt_with_common_key(
                    common_key, decoded_key, common_nonce)
                h_mac = get_hmac_from_common_key(common_key, decoded_key)
                send_message_to_client("DH-KEY-C", encrypted_dh_key, s,
                                       address, h_mac)

                #decrypt the diffie hellman key sent by the client using the common key in the ticket
                encrypted_sender_dh_key = response_dict['DH-KEY-C']
                byte_dh_key = decrypt_with_common_key(common_key,
                                                      encrypted_sender_dh_key,
                                                      common_nonce)

                #convert back to the format
                d2_pubkey = pickle.loads(byte_dh_key)

                shared_key_with_client = d1.gen_shared_key(d2_pubkey)

                shared_nonce = response_dict['NONCE']

                client_details.set_next_messages_expected("CLIENT_CHALLENGE")
                client_details.set_key(shared_key_with_client)
                client_details.set_nonce(shared_nonce)
                client_dict[username] = client_details

    # if the message type is CLIENT_CHALLENGE
    # iff it is in the list of expected messages for the sender of this message
    # then decrypt the challenge ,verify the hmac
    # encrypt the incoming challenge number and  new number and send it back to the sender of this message
    # also store the new number so that it can be used to verify when the sends back the challenge
    elif message_type == 'CLIENT_CHALLENGE':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        if username is not None:
            client_details = client_dict[username]
            if is_message_type_ok(message_type, client_details):

                key = client_details.key
                nonce = client_details.nonce
                decrypted_challenge = decrypt_with_shared_key(
                    key, message_dict['message'], nonce)

                # verify the hmac
                if not verify_hmac_with_shared_key(key, decrypted_challenge,
                                                   message_dict['hmac']):
                    print "Hmac verification failed while decrypting the challenge"
                    return

                #generate random number
                random_number = os.urandom(16)
                client_details.set_cookie(random_number)

                response_dict = {
                    'CHALLENGE': random_number,
                    "RESPONSE": decrypted_challenge
                }
                byte_data = pickle.dumps(response_dict)

                encrypted_data = encrypt_with_shared_key(key, byte_data, nonce)
                h_mac = get_hmac_from_shared_key(key, byte_data)
                send_message_to_client("CLIENT_RESPONSE_CHALLENGE",
                                       encrypted_data, s, address, h_mac)
                client_details.set_next_messages_expected("CLIENT_RESPONSE")
                client_dict[username] = client_details

    # if the message type is CLIENT_RESPONSE_CHALLENGE
    # iff it is in the list of expected messages for the sender of this message
    # then decrypt the message ,verify the hmac
    # Verify that the incoming message has the challenge which this client had sent to the sender

    # Create a new dictionary with the recieved challenge from the sender of this message and also the
    # original message stored in the temp message
    # encrypt this dictinary with the shared key and send it back
    elif message_type == 'CLIENT_RESPONSE_CHALLENGE':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        if username is not None:
            client_details = client_dict[username]
            if is_message_type_ok(message_type, client_details):
                key = client_details.key
                nonce = client_details.nonce

                byte_challage_response_dict = decrypt_with_shared_key(
                    key, message_dict['message'], nonce)

                if not verify_hmac_with_shared_key(
                        key, byte_challage_response_dict,
                        message_dict['hmac']):
                    print "Hmac vertification failed while recieving Client Response Challege"
                    return

                challenge_response_dict = get_original_message_from_byte(
                    byte_challage_response_dict)
                if (client_details.cookie !=
                        challenge_response_dict['RESPONSE']):
                    print "Response not correct"
                    return

                #new challenge response dict - send back the challenge and the message originally sent
                new_challeng_response_dict = {
                    'CHALLENGE_RESPONSE': challenge_response_dict['CHALLENGE'],
                    'CONV': client_details.temp_message
                }
                byte_new_challenge_response_dict = pickle.dumps(
                    new_challeng_response_dict)
                encrypted_new_challenge_response_dict = encrypt_with_shared_key(
                    key, byte_new_challenge_response_dict, nonce)
                h_mac = get_hmac_from_shared_key(
                    key, byte_new_challenge_response_dict)
                send_message_to_client("CLIENT_RESPONSE",
                                       encrypted_new_challenge_response_dict,
                                       s, address, h_mac)

                client_details.set_next_messages_expected("CONV")
                client_details.set_temp_message('')
                client_details.set_is_authenticated(True)
                #print "Setting authenticated to true"
                client_dict[username] = client_details
    # if the message type is CLIENT_RESPONSE
    # iff it is in the expected message type for the sender of this message then
    # decrypt the message
    # verify the hmac
    # Check that the message contains the challenge number which this client had sent to the server
    # Also display the CONV message on the screen
    elif message_type == 'CLIENT_RESPONSE':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        if username is not None:
            client_details = client_dict[username]
            if is_message_type_ok(message_type, client_details):

                key = client_details.key
                nonce = client_details.nonce

                decrypted_response = decrypt_with_shared_key(
                    key, message_dict['message'], nonce)
                if not verify_hmac_with_shared_key(key, decrypted_response,
                                                   message_dict['hmac']):
                    print "Hmac verification failed when recieving client resonse"
                    return

                challenge_response_dict = get_original_message_from_byte(
                    decrypted_response)

                if (challenge_response_dict['CHALLENGE_RESPONSE'] !=
                        client_details.cookie):
                    print "Challenge Verification Failed"
                    return

                client_details.set_next_messages_expected("CONV")
                client_details.set_is_authenticated(True)
                #print "Setting authenticated to true"

                print "Message From " + username + " : " + challenge_response_dict[
                    'CONV']

                client_dict[username] = client_details

    # iff the message type is CONV then
    # iff it is in the expected list of messages
    # Decrypt the message and verify the hmac
    # Print the message on the screen
    elif message_type == 'CONV':
        #print "Recieved " + message_type + "\n"
        username = user_name_from_address(address, client_dict)
        clientDetails = client_dict[username]
        if not is_message_type_ok(message_type, clientDetails):
            return
        decrypted_message = decrypt_with_shared_key(clientDetails.key,
                                                    message_dict['message'],
                                                    clientDetails.nonce)

        if not verify_hmac_with_shared_key(
                clientDetails.key, decrypted_message, message_dict['hmac']):
            print "Hmac vertification failed for the message recieved"
            return
        print "Message From : " + username + ' : ' + decrypted_message + '\n'
def send_input_msg(s, client_dict, s_key, nonce, username, kill_flag):
    try:
        while (1):

            if len(kill_flag) == 1:
                sys.exit(0)

            raw_answer = raw_input("\nEnter the message :")
            answer_list = raw_answer.split(" ")
            input_length = len(answer_list)
            command = answer_list[0]
            # If the command is list then
            # send an encrypted message to the server asking to list all the online clients
            if command == 'list':
                send_encrypted_message_to_server('LIST', command, s, s_key,
                                                 nonce)

            # If the command is send
            # check if the second input in the user input is a username in the client list , else ignore
            # iff the username is a valid client who is online check if the client has been authenticated
            # authenticated here implies that a session key has been established with the client in question
            # if authenticated then directly send the CONV message
            # if not then send a REQ_TO_TALK message to the client
            elif command == 'send':
                client_name = answer_list[1]

                if client_name == username:
                    continue

                if client_name in client_dict:
                    clientDetails = client_dict[client_name]
                    ts = ""
                    for string in answer_list[2:input_length]:
                        ts = ts + " " + string
                    if clientDetails.is_authenticated:
                        encrypted_message = encrypt_with_shared_key(
                            clientDetails.key, ts, clientDetails.nonce)
                        h_mac = get_hmac_from_shared_key(clientDetails.key, ts)
                        send_message_to_client(
                            "CONV", encrypted_message, s,
                            (clientDetails.ip, clientDetails.port), h_mac)
                    else:
                        send_message_to_client(
                            "REQ_TO_TALK", "", s,
                            (clientDetails.ip, clientDetails.port), 0)
                        clientDetails.set_next_messages_expected('NONCE')
                        # store the input message in the temp message attribute for later use (after the session key exchange)
                        clientDetails.set_temp_message(ts)
                        client_dict[client_name] = clientDetails
            # if the command is logout then send the logout message to the server
            elif command == 'logout':
                send_encrypted_message_to_server('LOGOUT', command, s, s_key,
                                                 nonce)
                # remove all client related details and exit
                for client in client_dict:
                    client_dict[client] = Client_Details()

                kill_flag.append(1)
                print "Logging Out"
                sys.exit(0)
    except socket.error, msg:
        print "Error while sending input"
        sys.exit()
def send_encrypted_message_to_server(message_type, message, s, s_key, nonce):
    s_message_dict = {'message_type': message_type, 'message': message}
    data = pickle.dumps(s_message_dict)
    encrypted_data = encrypt_with_shared_key(s_key, data, nonce)
    s.sendto(encrypted_data, (HOST, PORT))
Exemple #5
0
def respond_to_authenticated_clients(s, client_dict, address, message):
    username = user_name_from_address(address, client_dict)
    if username is not None:
        # decrypt message
        client_details = client_dict[username]
        key = client_details.key
        nonce = client_details.nonce

        decrypted_message = decrypt_with_shared_key(key, message, nonce)

        message_dict = pickle.loads(decrypted_message)

        msg = message_dict['message']

        # If message_type is of 'LIST" prepare a list of Online Clients
        # Encrypt the client list and send to the sender
        if message_dict['message_type'] == 'LIST':

            clientList = getCdtListFromDict(client_dict)

            byte_clientList = pickle.dumps(clientList)
            encrypted_clientList = encrypt_with_shared_key(
                key, byte_clientList, nonce)

            message_transit_dict = {
                'message_type': 'LIST_ANSWER',
                'message': encrypted_clientList,
                'hmac': 0
            }

            data = pickle.dumps(message_transit_dict)
            #data_encrypted = encrypt_with_shared_key(key,data,nonce)
            s.sendto(data, address)
            return client_dict

        # If message type is MESSAGE_REQ
        # Compute  a common shared key and common nonce for encryption between the clients
        # Create dictionary for the client requesting the MESSAGE_REQ with common key, The username of the client which the sending client is requesting to talk to and the
        # common nonce used for encryption
        # Encrypt the above dictionary

        # Create a Dictionary for the ticket to the 2nd Client with common key,common nonce for encryption and the Nonce used for verification which it had sent to Client1
        # Encrypt the above dictionary
        # Put the above encrypted dictionaries in one more dictionary called Response Dict and treat it as message payload
        # Prepare a message transit dictionary with Message Type as SESSION_KEY_FROM_SERVER , Response Dict as  Message and send to the Requesting Client
        elif message_dict['message_type'] == 'MESSAGE_REQ':
            common_key = os.urandom(16)
            common_nonce = os.urandom(16)
            repsonse_for_client_requesting = {
                'common_key': common_key,
                'key_for': msg['CLIENT_KEY_REQUIRED_FOR'],
                'common_nonce': common_nonce
            }
            byte_resonse_for_requested_client_dict = pickle.dumps(
                repsonse_for_client_requesting)
            encrypted_response_for_client_requesting = encrypt_with_shared_key(
                key, byte_resonse_for_requested_client_dict, nonce)

            ticket_to_requested_client = {
                'common_key': common_key,
                'key_for': username,
                'common_nonce': common_nonce,
                'NONCE_FOR_VERIFICATION': msg['NONCE']
            }
            if msg['CLIENT_KEY_REQUIRED_FOR'] not in client_dict:
                return client_dict

            requested_client_details = client_dict[
                msg['CLIENT_KEY_REQUIRED_FOR']]
            if not requested_client_details.is_authenticated:
                return client_dict
            ckey = requested_client_details.key
            cnonce = requested_client_details.nonce
            byte_ticket_to_requested_client = pickle.dumps(
                ticket_to_requested_client)
            encrypted_ticket_to_requested_client = encrypt_with_shared_key(
                ckey, byte_ticket_to_requested_client, cnonce)

            response_dict = {
                'COMMON_KEY_RESPONSE':
                encrypted_response_for_client_requesting,
                'COMMON_KEY_TICKET': encrypted_ticket_to_requested_client
            }

            message_transit_dict = {
                'message_type': 'SESSION_KEY_FROM_SERVER',
                'message': response_dict,
                'hmac': 0
            }

            data = pickle.dumps(message_transit_dict)

            s.sendto(data, address)
            return client_dict

        # If message type is LOGOUT then
        # Re instantiate the Client Details object for the client in Client Dict
        # Send the information that this client has logged out to all the online clients
        elif message_dict['message_type'] == 'LOGOUT':
            # set authenticated to false and set the key to 0
            # client_details = client_dict[username]
            # client_details.set_is_authenticated(False)
            # client_details.set_key(0)
            # client_dict[username] = client_details
            client_dict[username] = Client_Details()

            clientList = getCdtListFromDict(client_dict)
            #print len(clientList)

            for client in client_dict:
                clientDetails = client_dict[client]
                if clientDetails.is_authenticated:
                    print "sending logout message to " + client
                    encrypted_message = encrypt_with_shared_key(
                        clientDetails.key, username, clientDetails.nonce)
                    message_transit_dict = {
                        'message_type': 'LOGOUT_NOTIFICATION',
                        'message': encrypted_message,
                        'hmac': 0
                    }
                    data = pickle.dumps(message_transit_dict)
                    s.sendto(data, (clientDetails.ip, clientDetails.port))

            return client_dict