def handle(self): """ Handle requests from the clients. :return: """ global auth_dict, nonce_dict, crypto_service, password_hash_dict, user_addr_dict, chatting_service msg = self.request[0] sock = self.request[1] # get auth instance for client if self.client_address not in auth_dict: try: _, msg_parts = PacketOrganiser.process_packet(msg) except: return if msg_parts[0] != c.GREETING: return # new client, create an auth entry in the auth dictionary auth_dict[self.client_address] = Authentication( self.client_address, crypto_service, password_hash_dict) else: auth = auth_dict[self.client_address] if not PacketOrganiser.isValidTimeStampSeconds( auth.timestamp, c.KEEP_ALIVE_TIME): auth_dict.pop(self.client_address) cur_auth = auth_dict[self.client_address] assert isinstance(cur_auth, Authentication) rep = None if not cur_auth.is_auth(): rep = cur_auth.process_request(msg, user_addr_dict) else: # get decrypted msg dec_msg = crypto_service.sym_decrypt(cur_auth.dh_key, msg) n, msg_ps = PacketOrganiser.process_packet(dec_msg) auth_dict[ self. client_address].timestamp = PacketOrganiser.get_new_timestamp( ) # update timestamp rep = chatting_service.get_response(self.client_address, msg_ps) if rep is not None: rep = PacketOrganiser.prepare_packet(rep, n) rep = crypto_service.sym_encrypt(cur_auth.dh_key, rep) try: if rep is not None: sys.stdout.flush() sock.sendto(rep, self.client_address) elif cur_auth.is_auth(): cur_auth.loginfailures += 1 except socket.error: print(c.FAIL_MSG_FWD) return
def _step_1_dh_key_establish(self, sock, chl, k, ind, username): """ DH contribution exchange :param sock: :param chl: :param k: :param ind: :return: """ ans = self.ra.compute_answer(chl, k) dh_pri_key = self.crypto_service.get_dh_pri_key() dh_pub_key = self.crypto_service.get_dh_pub_key(dh_pri_key) msg_to_send_parts = [dh_pub_key, username, ""] nonce = PacketOrganiser.genRandomNumber() msg_to_send = PacketOrganiser.prepare_packet(msg_to_send_parts, nonce=nonce, add_time=False) enc_msg_to_send = self.crypto_service.rsa_encrypt(msg_to_send) auth_1_msg_parts = [ans, ind, enc_msg_to_send] auth_1_msg = PacketOrganiser.prepare_packet(auth_1_msg_parts, add_time=False) sock.sendto(auth_1_msg, self.server_addr) recv_msg = util.get_one_response(sock, self.server_addr) # print("Receive msg from {}, length: {}".format(self.server_addr, len(recv_msg))) _, msg_sign = PacketOrganiser.process_packet(recv_msg) if msg_sign[0] == c.MSG_RESPONSE_WRONG_CR: print(c.WRONG_CR_MSG) return elif msg_sign[0] == c.MSG_RESPONSE_USER_EXISTS: print(c.USER_ALREADY_LOGIN_MSG) return else: msg, sign, _ = msg_sign if not self.crypto_service.rsa_verify(msg, sign): # TODO for testing raise Exception(c.STEP_ONE_FAIL_MSG) _, pub_enc_salt = PacketOrganiser.process_packet(msg) other_pub_key, enc_salt, _ = pub_enc_salt other_pub_key = int(other_pub_key) self.dh_key = self.crypto_service.get_dh_secret( dh_pri_key, other_pub_key) dec_salt_pack = self.crypto_service.sym_decrypt( self.dh_key, enc_salt) n1, salt_parts = PacketOrganiser.process_packet(dec_salt_pack) salt = salt_parts[0] if n1 == nonce: return salt
def handle(self): """ Handle requests from the clients. :return: """ global auth_dict, nonce_dict, crypto_service, password_hash_dict, user_addr_dict, chatting_service msg = self.request[0] sock = self.request[1] # get auth instance for client if self.client_address not in auth_dict: try: _, msg_parts = PacketOrganiser.process_packet(msg) except: return if msg_parts[0] != c.GREETING: return # new client, create an auth entry in the auth dictionary auth_dict[self.client_address] = Authentication(self.client_address, crypto_service, password_hash_dict) else: auth = auth_dict[self.client_address] if not PacketOrganiser.isValidTimeStampSeconds(auth.timestamp,c.KEEP_ALIVE_TIME): auth_dict.pop(self.client_address) cur_auth = auth_dict[self.client_address] assert isinstance(cur_auth, Authentication) rep = None if not cur_auth.is_auth(): rep = cur_auth.process_request(msg, user_addr_dict) else: # get decrypted msg dec_msg = crypto_service.sym_decrypt(cur_auth.dh_key, msg) n, msg_ps = PacketOrganiser.process_packet(dec_msg) auth_dict[self.client_address].timestamp = PacketOrganiser.get_new_timestamp() # update timestamp rep = chatting_service.get_response(self.client_address, msg_ps) if rep is not None: rep = PacketOrganiser.prepare_packet(rep, n) rep = crypto_service.sym_encrypt(cur_auth.dh_key, rep) try: if rep is not None: sys.stdout.flush() sock.sendto(rep, self.client_address) elif cur_auth.is_auth(): cur_auth.loginfailures += 1 except socket.error: print(c.FAIL_MSG_FWD) return
def _step_2_password_verification(self, sock, password, salt): """ Verify password. :param sock: :param password: :param salt: :return: """ pw_hash = self.crypto_service.compute_pw_hash(password, salt) nonce = PacketOrganiser.genRandomNumber() msg = PacketOrganiser.prepare_packet(pw_hash, nonce) auth_2_msg = self.crypto_service.sym_encrypt(self.dh_key, msg) sock.sendto(auth_2_msg, self.server_addr) # step 3 recv_msg = util.get_one_response(sock, self.server_addr) # print("Receive msg from {}: {}".format(self.server_addr, recv_msg)) dec_msg = self.crypto_service.sym_decrypt(self.dh_key, recv_msg) n, msg_parts = PacketOrganiser.process_packet(dec_msg) if n != nonce: raise Exception(c.STEP_THREE_NONCE_FAIL_MSG) auth_result = msg_parts[0] if auth_result == c.AUTH_SUCCESS: self.auth_success = True elif auth_result == c.MSG_RESPONSE_WRONG_CR: print(c.WRONG_CR_MSG) return self.auth_success
def _step_1_dh_key_establish(self, sock, chl, k, ind, username): """ DH contribution exchange :param sock: :param chl: :param k: :param ind: :return: """ ans = self.ra.compute_answer(chl, k) dh_pri_key = self.crypto_service.get_dh_pri_key() dh_pub_key = self.crypto_service.get_dh_pub_key(dh_pri_key) msg_to_send_parts = [dh_pub_key, username, ""] nonce = PacketOrganiser.genRandomNumber() msg_to_send = PacketOrganiser.prepare_packet(msg_to_send_parts, nonce=nonce, add_time=False) enc_msg_to_send = self.crypto_service.rsa_encrypt(msg_to_send) auth_1_msg_parts = [ans, ind, enc_msg_to_send] auth_1_msg = PacketOrganiser.prepare_packet(auth_1_msg_parts, add_time=False) sock.sendto(auth_1_msg, self.server_addr) recv_msg = util.get_one_response(sock, self.server_addr) # print("Receive msg from {}, length: {}".format(self.server_addr, len(recv_msg))) _, msg_sign = PacketOrganiser.process_packet(recv_msg) if msg_sign[0] == c.MSG_RESPONSE_WRONG_CR: print(c.WRONG_CR_MSG) return elif msg_sign[0] == c.MSG_RESPONSE_USER_EXISTS: print(c.USER_ALREADY_LOGIN_MSG) return else: msg, sign, _ = msg_sign if not self.crypto_service.rsa_verify(msg, sign): # TODO for testing raise Exception(c.STEP_ONE_FAIL_MSG) _, pub_enc_salt = PacketOrganiser.process_packet(msg) other_pub_key, enc_salt, _ = pub_enc_salt other_pub_key = int(other_pub_key) self.dh_key = self.crypto_service.get_dh_secret(dh_pri_key, other_pub_key) dec_salt_pack = self.crypto_service.sym_decrypt(self.dh_key, enc_salt) n1, salt_parts = PacketOrganiser.process_packet(dec_salt_pack) salt = salt_parts[0] if n1 == nonce: return salt
def _stage_1_dh_key_exchange(self, request, user_addr_dict): """ check the challenge answer, decrypt the client DH public key and send DH public key back :param request: request from client :param user_addr_dict: dictionary which keep tracking of the username and corresponding IP address and port :return: """ try: _, request_parts = PacketOrganiser.process_packet(request) c_ans, ind, enc_client_msg = request_parts except: return None c_ans = int(c_ans) ind = int(ind) #k = self.ra.getMaskSize() # TODO flaw when mask size changed if self.ra.challengeComm.is_challenge_matched(self.masksize, ind, c_ans): dec_msg = self.crypto_service.rsa_decrypt(enc_client_msg) n1, dec_msg_parts = PacketOrganiser.process_packet(dec_msg) dec_dh_pub_client, username, _ = dec_msg_parts if username in user_addr_dict: # prevent duplicate login self.stage = c.AUTH_STAGE_INIT return PacketOrganiser.prepare_packet(c.MSG_RESPONSE_USER_EXISTS, nonce=n1) if username not in self.pw_dict: self.stage = c.AUTH_STAGE_INIT return PacketOrganiser.prepare_packet(c.MSG_RESPONSE_WRONG_CR, nonce=n1) self.username = username dec_dh_pub_client = int(dec_dh_pub_client) dh_pri_key = self.crypto_service.get_dh_pri_key() dh_pub_server = self.crypto_service.get_dh_pub_key(dh_pri_key) self.dh_key = self.crypto_service.get_dh_secret(dh_pri_key, dec_dh_pub_client) # compose response: public key, K{N1, salt}, sign whole message salt = self.pw_dict[self.username][1] # get salt from username salt_pack = PacketOrganiser.prepare_packet(salt, nonce=n1, add_time=False) enc_salt = self.crypto_service.sym_encrypt(self.dh_key, salt_pack) msg = PacketOrganiser.prepare_packet([dh_pub_server, enc_salt, ""], add_time=False) sign = self.crypto_service.rsa_sign(msg) signed_msg = PacketOrganiser.prepare_packet([msg, sign, ""], add_time=False) self.stage = c.AUTH_STAGE_2 return signed_msg
def _step_0_get_challenge(self, sock): """ Challenge step. :param sock: :return: """ # send greeting to the server # print("Get Username: {}, Password: {}".format(username, password)) msg_to_send = PacketOrganiser.prepare_packet(c.GREETING, add_time=False) sock.sendto(msg_to_send, self.server_addr) recv_msg = util.get_one_response(sock, self.server_addr) # print("Receive msg from {}: {}".format(self.server_addr, recv_msg)) _, recv_msg_parts = PacketOrganiser.process_packet(recv_msg) # chl, k, ind = recv_msg_parts return recv_msg_parts
def _stage_2_pw_check(self, request, user_addr_dict): """ Stage 2 is to check if the password is correct :param request: Request is the incoming message which contains the password. :param user_addr_dict: The user_add_dict is the dictionary which has each user and associated address stored. :return: The method returns a encrypted response message """ # decrypt the message and check the password hash dec_request = self.crypto_service.sym_decrypt(self.dh_key, request) n, request_parts = PacketOrganiser.process_packet(dec_request) pw_hash = request_parts[0] if pw_hash != self.pw_dict[self.username][0]: msg = PacketOrganiser.prepare_packet(c.MSG_RESPONSE_WRONG_CR, nonce=n) enc_msg = self.crypto_service.sym_encrypt(self.dh_key, msg) self.stage = c.AUTH_STAGE_INIT self.loginfailures += 1 else: msg = PacketOrganiser.prepare_packet(c.AUTH_SUCCESS, nonce=n) enc_msg = self.crypto_service.sym_encrypt(self.dh_key, msg) self.stage = c.AUTH_STAGE_FINISHED user_addr_dict[self.username] = self.addr return enc_msg
def run_client(server_ip, server_port): """ Main function to start the client. server_ip: IP address of the server server_port: port number which server uses to communicate """ global server_auth, user_addr_dict, active_users g = 2 p = util.load_df_param_from_file(c.DH_CONFIG_PATH) crypto_service = CryptoService(rsa_pub_path=c.PUB_KEY_PATH, p=p, g=g) server_addr = (server_ip, server_port) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) client_port = server_port + 1 local_ip = socket.gethostbyname(socket.gethostname()) client_addr = (local_ip, client_port) # try to find a available local port port_found = False while not port_found: try: sock.bind(client_addr) port_found = True except socket.error: client_addr = (client_addr[0], client_addr[1] + 1) continue server_auth = ClientServerAuthentication(client_addr, server_addr, crypto_service) try: server_auth.authenticate_with_server(sock) except socket.error: print Consts.FAIL_GRE_MSG return chat_service = ClientChattingService(active_users, server_auth) # start a background to handle user input t_listen = ListenThread(sock, server_addr) t_listen.start() # start a background to resend message t_resend = ResendThread(sock, request_cache) t_resend.start() sys.stdout.write(Consts.PROMPT) sys.stdout.flush() while True: try: # listening to the server and display the message recv_msg, r_addr = sock.recvfrom(20480) if r_addr == server_addr and recv_msg: dec_msg = crypto_service.sym_decrypt(server_auth.dh_key, recv_msg) n, msg_ps = PacketOrganiser.process_packet(dec_msg) # first check if it's a client/client authentication # response from server if n in request_cache: # check the type of request cache = request_cache[n] request_type = cache[c.CACHE_TYPE_IND] if request_type == c.MSG_TYPE_LOGOUT: # process logout confirmation if msg_ps[0] == c.MSG_RESPONSE_OK: request_cache.pop(n) break elif request_type == c.MSG_TYPE_START_NEW_CHAT: # process the auth response from server cur_auth = cache[c.CACHE_AUTH_IND] assert isinstance(cur_auth, ClientClientAuthentication) b_addr = cur_auth.start_authenticate(sock, msg_ps, server_auth.username) user_addr_dict[cur_auth.username] = b_addr addr_auths[b_addr] = cur_auth request_cache.pop(n) elif request_type == c.MSG_TYPE_LIST: # process the user list form server chat_service.process_message(msg_ps) request_cache.pop(n) elif request_type == c.ERR_CLIENT_DOWN: print(c.ERR_CLIENT_DOWN) request_cache.pop(n) elif r_addr in addr_auths: #Reply or chat request from client cur_auth = addr_auths[r_addr] dec_msg = crypto_service.sym_decrypt(cur_auth.dh_key, recv_msg) n, dec_msg_parts = PacketOrganiser.process_packet(dec_msg) type = dec_msg_parts[0] if cur_auth.auth_success: if type == c.MSG_RESPONSE_OK: if n in request_cache: cache = request_cache[n] request_type = cache[c.CACHE_TYPE_IND] if request_type == c.MSG_TYPE_MSG: request_cache.pop(n) continue elif type == c.MSG_TYPE_MSG: # display user message msg_hmac = dec_msg_parts[1] # check the HMAC msg, sign = PacketOrganiser.divide_signature(msg_hmac) if CryptoService.verify_hmac_sign(cur_auth.dh_key, msg, sign): util.display_user_message(msg, cur_auth.username) # send message confirmation back util.send_confirmation(sock, crypto_service, cur_auth.dh_key, n, r_addr) else: # deal with peer auth success msg if type == c.MSG_RESPONSE_OK: if n in request_cache: cache = request_cache[n] request_type = cache[c.CACHE_TYPE_IND] if request_type == c.MSG_TYPE_PUB_KEY: # verify nonce if n != cur_auth.last_nonce: continue else: cur_auth.auth_success = True request_cache.pop(n) # check the HMAC msg_hmac = dec_msg_parts[1] msg, sign = PacketOrganiser.divide_signature(msg_hmac) if CryptoService.verify_hmac_sign(cur_auth.dh_key, msg, sign): # display user message util.display_user_message(msg, cur_auth.username) # send message confirmation back util.send_confirmation(sock, crypto_service, cur_auth.dh_key, n, r_addr) elif type == c.MSG_TYPE_PUB_KEY: # finish peer authentication on Alice side b_pub_key = int(dec_msg_parts[1]) cur_auth.dh_key = crypto_service.get_dh_secret(cur_auth.pri_key, b_pub_key) cur_auth.auth_success = True cur_auth.last_nonce = n # send confirmation and first message to Bob hmac = CryptoService.generate_hmac_sign(cur_auth.dh_key, cur_auth.first_msg) first_msg_hmac = cur_auth.first_msg + hmac conf_msg_parts = [c.MSG_RESPONSE_OK, first_msg_hmac, ""] conf_msg = PacketOrganiser.prepare_packet(conf_msg_parts, n) enc_conf_msg = crypto_service.sym_encrypt(cur_auth.dh_key, conf_msg) # add to request cache # a hack here (TYPE_MSG instead of RESPONSE_OK) to make the confirmation work util.add_to_request_cache(request_cache, n, c.MSG_TYPE_MSG, cur_auth.dh_key, conf_msg, r_addr) sock.sendto(enc_conf_msg, r_addr) else: # the r_addr not in user_addr_dict, this can be a TTB # handle TTB from Alice _, msg_ps = PacketOrganiser.process_packet(recv_msg) signed_ttb, enc_inside_msg, _ = msg_ps ttb = signed_ttb[:-c.RSA_SIGN_LENGTH] sign = signed_ttb[-c.RSA_SIGN_LENGTH:] if not crypto_service.rsa_verify(ttb, sign): raise Exception(c.WARNING_TTB_INVALID) dec_ttb = crypto_service.sym_decrypt(server_auth.dh_key, ttb) _, ttb_parts = PacketOrganiser.process_packet(dec_ttb) # a_username, a_addr, k_ab a_username_ttb, a_addr, k_ab = ttb_parts a_addr = util.str_to_addr(a_addr) # decrypt inside message with k_ab dec_inside_msg = crypto_service.sym_decrypt(k_ab, enc_inside_msg) _, inside_msg_parts = PacketOrganiser.process_packet(dec_inside_msg) a_username, a_pub_key, _ = inside_msg_parts # print("username_ttb: {}, a_username: {}".format(a_username_ttb, a_username)) if a_username_ttb != a_username: raise Exception(c.WARNING_TTB_USERNAME_INVALID) new_auth = ClientClientAuthentication(a_username, crypto_service) pri_key = crypto_service.get_dh_pri_key() pub_key = crypto_service.get_dh_pub_key(pri_key) new_auth.dh_key = crypto_service.get_dh_secret(pri_key, int(a_pub_key)) nonce = util.get_good_nonce(request_cache) new_auth.last_nonce = nonce # send pub key to Alice msg_parts = [c.MSG_TYPE_PUB_KEY, pub_key, ""] plain_msg = PacketOrganiser.prepare_packet(msg_parts, nonce) enc_msg = crypto_service.sym_encrypt(k_ab, plain_msg) sock.sendto(enc_msg, a_addr) # add new auth to dict addr_auths[a_addr] = new_auth user_addr_dict[a_username] = a_addr util.add_to_request_cache(request_cache, nonce, c.MSG_TYPE_PUB_KEY, k_ab, plain_msg, a_addr) # add to request cache except socket.error: # sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # sock.bind(client_addr) continue except KeyboardInterrupt: # when seeing ctrl-c terminate the client t_listen.stop() t_listen.join() t_resend.stop() t_resend.join() print c.BYE server_auth.logout(sock) sock.close() return except: pass t_listen.stop() t_listen.join() t_resend.stop() t_resend.join() print c.BYE server_auth.logout(sock) sock.close()
def run_client(server_ip, server_port): """ Main function to start the client. server_ip: IP address of the server server_port: port number which server uses to communicate """ global server_auth, user_addr_dict, active_users g = 2 p = util.load_df_param_from_file(c.DH_CONFIG_PATH) crypto_service = CryptoService(rsa_pub_path=c.PUB_KEY_PATH, p=p, g=g) server_addr = (server_ip, server_port) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) client_port = server_port + 1 local_ip = socket.gethostbyname(socket.gethostname()) client_addr = (local_ip, client_port) # try to find a available local port port_found = False while not port_found: try: sock.bind(client_addr) port_found = True except socket.error: client_addr = (client_addr[0], client_addr[1] + 1) continue server_auth = ClientServerAuthentication(client_addr, server_addr, crypto_service) try: server_auth.authenticate_with_server(sock) except socket.error: print Consts.FAIL_GRE_MSG return chat_service = ClientChattingService(active_users, server_auth) # start a background to handle user input t_listen = ListenThread(sock, server_addr) t_listen.start() # start a background to resend message t_resend = ResendThread(sock, request_cache) t_resend.start() sys.stdout.write(Consts.PROMPT) sys.stdout.flush() while True: try: # listening to the server and display the message recv_msg, r_addr = sock.recvfrom(20480) if r_addr == server_addr and recv_msg: dec_msg = crypto_service.sym_decrypt(server_auth.dh_key, recv_msg) n, msg_ps = PacketOrganiser.process_packet(dec_msg) # first check if it's a client/client authentication # response from server if n in request_cache: # check the type of request cache = request_cache[n] request_type = cache[c.CACHE_TYPE_IND] if request_type == c.MSG_TYPE_LOGOUT: # process logout confirmation if msg_ps[0] == c.MSG_RESPONSE_OK: request_cache.pop(n) break elif request_type == c.MSG_TYPE_START_NEW_CHAT: # process the auth response from server cur_auth = cache[c.CACHE_AUTH_IND] assert isinstance(cur_auth, ClientClientAuthentication) b_addr = cur_auth.start_authenticate( sock, msg_ps, server_auth.username) user_addr_dict[cur_auth.username] = b_addr addr_auths[b_addr] = cur_auth request_cache.pop(n) elif request_type == c.MSG_TYPE_LIST: # process the user list form server chat_service.process_message(msg_ps) request_cache.pop(n) elif request_type == c.ERR_CLIENT_DOWN: print(c.ERR_CLIENT_DOWN) request_cache.pop(n) elif r_addr in addr_auths: #Reply or chat request from client cur_auth = addr_auths[r_addr] dec_msg = crypto_service.sym_decrypt(cur_auth.dh_key, recv_msg) n, dec_msg_parts = PacketOrganiser.process_packet(dec_msg) type = dec_msg_parts[0] if cur_auth.auth_success: if type == c.MSG_RESPONSE_OK: if n in request_cache: cache = request_cache[n] request_type = cache[c.CACHE_TYPE_IND] if request_type == c.MSG_TYPE_MSG: request_cache.pop(n) continue elif type == c.MSG_TYPE_MSG: # display user message msg_hmac = dec_msg_parts[1] # check the HMAC msg, sign = PacketOrganiser.divide_signature(msg_hmac) if CryptoService.verify_hmac_sign( cur_auth.dh_key, msg, sign): util.display_user_message(msg, cur_auth.username) # send message confirmation back util.send_confirmation(sock, crypto_service, cur_auth.dh_key, n, r_addr) else: # deal with peer auth success msg if type == c.MSG_RESPONSE_OK: if n in request_cache: cache = request_cache[n] request_type = cache[c.CACHE_TYPE_IND] if request_type == c.MSG_TYPE_PUB_KEY: # verify nonce if n != cur_auth.last_nonce: continue else: cur_auth.auth_success = True request_cache.pop(n) # check the HMAC msg_hmac = dec_msg_parts[1] msg, sign = PacketOrganiser.divide_signature( msg_hmac) if CryptoService.verify_hmac_sign( cur_auth.dh_key, msg, sign): # display user message util.display_user_message( msg, cur_auth.username) # send message confirmation back util.send_confirmation( sock, crypto_service, cur_auth.dh_key, n, r_addr) elif type == c.MSG_TYPE_PUB_KEY: # finish peer authentication on Alice side b_pub_key = int(dec_msg_parts[1]) cur_auth.dh_key = crypto_service.get_dh_secret( cur_auth.pri_key, b_pub_key) cur_auth.auth_success = True cur_auth.last_nonce = n # send confirmation and first message to Bob hmac = CryptoService.generate_hmac_sign( cur_auth.dh_key, cur_auth.first_msg) first_msg_hmac = cur_auth.first_msg + hmac conf_msg_parts = [ c.MSG_RESPONSE_OK, first_msg_hmac, "" ] conf_msg = PacketOrganiser.prepare_packet( conf_msg_parts, n) enc_conf_msg = crypto_service.sym_encrypt( cur_auth.dh_key, conf_msg) # add to request cache # a hack here (TYPE_MSG instead of RESPONSE_OK) to make the confirmation work util.add_to_request_cache(request_cache, n, c.MSG_TYPE_MSG, cur_auth.dh_key, conf_msg, r_addr) sock.sendto(enc_conf_msg, r_addr) else: # the r_addr not in user_addr_dict, this can be a TTB # handle TTB from Alice _, msg_ps = PacketOrganiser.process_packet(recv_msg) signed_ttb, enc_inside_msg, _ = msg_ps ttb = signed_ttb[:-c.RSA_SIGN_LENGTH] sign = signed_ttb[-c.RSA_SIGN_LENGTH:] if not crypto_service.rsa_verify(ttb, sign): raise Exception(c.WARNING_TTB_INVALID) dec_ttb = crypto_service.sym_decrypt(server_auth.dh_key, ttb) _, ttb_parts = PacketOrganiser.process_packet( dec_ttb) # a_username, a_addr, k_ab a_username_ttb, a_addr, k_ab = ttb_parts a_addr = util.str_to_addr(a_addr) # decrypt inside message with k_ab dec_inside_msg = crypto_service.sym_decrypt( k_ab, enc_inside_msg) _, inside_msg_parts = PacketOrganiser.process_packet( dec_inside_msg) a_username, a_pub_key, _ = inside_msg_parts # print("username_ttb: {}, a_username: {}".format(a_username_ttb, a_username)) if a_username_ttb != a_username: raise Exception(c.WARNING_TTB_USERNAME_INVALID) new_auth = ClientClientAuthentication(a_username, crypto_service) pri_key = crypto_service.get_dh_pri_key() pub_key = crypto_service.get_dh_pub_key(pri_key) new_auth.dh_key = crypto_service.get_dh_secret( pri_key, int(a_pub_key)) nonce = util.get_good_nonce(request_cache) new_auth.last_nonce = nonce # send pub key to Alice msg_parts = [c.MSG_TYPE_PUB_KEY, pub_key, ""] plain_msg = PacketOrganiser.prepare_packet(msg_parts, nonce) enc_msg = crypto_service.sym_encrypt(k_ab, plain_msg) sock.sendto(enc_msg, a_addr) # add new auth to dict addr_auths[a_addr] = new_auth user_addr_dict[a_username] = a_addr util.add_to_request_cache(request_cache, nonce, c.MSG_TYPE_PUB_KEY, k_ab, plain_msg, a_addr) # add to request cache except socket.error: # sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # sock.bind(client_addr) continue except KeyboardInterrupt: # when seeing ctrl-c terminate the client t_listen.stop() t_listen.join() t_resend.stop() t_resend.join() print c.BYE server_auth.logout(sock) sock.close() return except: pass t_listen.stop() t_listen.join() t_resend.stop() t_resend.join() print c.BYE server_auth.logout(sock) sock.close()