Пример #1
0
def receiveMessages(sock, username, sip, sport, A, password, a):
  while(1):
    try:
      # try to receive messages from the server
      msg = sock.recv(40960)  # changed here akshay
      if msg != '':
        msg1 = pickle.loads(msg)
        #print("Received message:%s" %(msg1))
        status = progress[username]
        if(status == 1):
          if(msg1 == 'ERROR'):
            global EXIT_IN_ERROR
            EXIT_IN_ERROR = True
            sys.exit()
          value = find_value_from_hash(msg1)
          send_message(sock, value, sip, sport)
          progress[username] = 2
      
        if(status == 2):
          challenge_pk_data = {}
          data_for_kas = {}
          final_to_server = {}
          global shared_key
          shared_key = compute_shared_key(A, msg1, username, password, a)
          final_kas = util.MD5_HASH(shared_key)
          challenge = util.get_random_number()
          global NONCE_SENT
          NONCE_SENT = challenge
          data_for_kas.update({'CHALLENGE': challenge , 'PK_CLIENT': CLIENT_PUBLIC_KEY_STR})
          Kas_encrypted_data = util.encrypt_message_KAS(data_for_kas, final_kas, GENERATED_IV)
          # add IV here 
          challenge_pk_data.update({'CHALLENGE_PK': Kas_encrypted_data, 'CHALLENGE': challenge, 'IV': GENERATED_IV})
          data_to_server = util.encrypt_message_PSK(challenge_pk_data, SERVER_KEY)
          send_message(sock, data_to_server, sip, sport)
          progress[username] = 3

        if(status == 3):
          hash_shared_key = util.MD5_HASH(shared_key)
          nonce = util.decrypt_using_Kas(msg1, hash_shared_key, GENERATED_IV)
          incremented_nonce = long(nonce) + 1
          if incremented_nonce == NONCE_SENT:
            print ("Login Success !")
            return True
          else:
            print("Authentication pending!")
            return False

      else:
        print("Connection with server is broken...")
        sys.exit()
    except KeyboardInterrupt:
      sock.close()
    # handling socket errors
    except socket.error, s_error:
      sock.close()
      error_code = s_error[0]
      error_message = s_error[1]
      print('Error in reading messages: ', error_code, ' - ', error_message)
    except Exception as e:
      print('Error occured:', e)
      sock.close()
      sys.exit()
Пример #2
0
def non_blocking_listen(server, current_username):
  global USERNAME_TO_PORT
  global CHAT_NONCE
  global shared_key
  global g
  global p 
  global a
  global df_keys
  global message_tracker 
  global IV_tracker
  global df_progress
  global port_tracker

  udp_socket = create_udp_socket()
  udp_socket.bind(server.getsockname())
  read_sockets = [server, sys.stdin, udp_socket]
  write_sockets = []
  message_queue = {}
  timeout = 30
  try:
    while(read_sockets):
      #print("Waiting for read/write event...")
      readable, writable, exceptional = select.select(read_sockets, write_sockets, read_sockets, timeout)

      for s in readable:
        if s == sys.stdin:
          command = s.readline().strip()
          if command.lower() == 'list' or command.lower() == 'logout':
            global ACTION_NONCE
            ACTION_NONCE = util.get_random_number()
            message = {}
            message.update({'ACTION': command.upper()})
            message.update({'username': current_username})
            message.update({'NONCE': ACTION_NONCE})
            try:
              final_kas = util.MD5_HASH(shared_key)
              to_send = util.encrypt_message_KAS(message, final_kas, GENERATED_IV)
            except Exception as e:
              print "An error occured while encrypting the text message for ACTION. ", message, "! %s" %e
            send_message(server, to_send, sip, sport)
          
          # you are A
          if command.split(" ")[0] == "send":
            chat_text = command.split(" ")[1:]
            sender_username = chat_text[0]
            message_tracker[sender_username] = ' '.join(chat_text)

            #udp_socket.sendto(' '.join(chat_text[1:]),('localhost',int(USERNAME_TO_PORT[sender_username])))

            # update
            CHAT_NONCE = util.get_random_number()
            message = {}
            message.update({'ACTION': 'CHAT'})
            message.update({'A': current_username})
            message.update({'B': sender_username})
            message.update({'NONCE': CHAT_NONCE})
            try:
              final_kas = util.MD5_HASH(shared_key)
              to_send = util.encrypt_message_KAS(message, final_kas, GENERATED_IV)
            except Exception as e:
              print "An error occured while encrypting the text message for ACTION. ", message, "! %s" %e
            send_message(server, to_send, sip, sport)
            # update ends 

        if s is server and s != sys.stdin:
          data = s.recv(40960)
          if data:
            pickled_data = pickle.loads(data)
            #print("Received data - %s from %s" %(pickled_data, s.getpeername()))

            hash_shared_key = util.MD5_HASH(shared_key)
            response = util.decrypt_using_Kas(pickled_data, hash_shared_key, GENERATED_IV)
            d = ast.literal_eval(response)
            
            valid = False
            if(str(d['ACTION']).strip() == 'LIST'):
              list_message = d['MESSAGE']
              list_of_users = []
              if type(list_message) == str:
                print list_message
              else:
                print "~~~~~~~~~~~~~ Online Users ~~~~~~~~~~~~~"
                for item in list_message:
                  username =  item[0]
                  portip = item[1]
                  port = portip.split(":")[1]
                  USERNAME_TO_PORT.update({username:int(port)})
                  print username
                print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
              valid = True
              
            if(str(d['ACTION']).strip() == 'LOGOUT'):
              received_nonce = d['MESSAGE']
              if(long(received_nonce) + 1 == ACTION_NONCE):
                print "Confirming logout"
                valid = True
            
            if valid:
              challenge_nonce = d['NONCE']
              decrement_nonce = long(challenge_nonce) - 1
              try:
                final_kas = util.MD5_HASH(shared_key)
                to_send = util.encrypt_message_KAS(decrement_nonce, final_kas, GENERATED_IV)
              except Exception as e:
                print "An error occured while encrypting the text message for ACTION. ", message, "! %s" %e
              send_message(server, to_send, sip, sport)

              if(str(d['ACTION']).strip() == 'LOGOUT'):
                server.close()
                for s in read_sockets:
                  if s != sys.stdin:
                    s.close()
                for s in write_sockets:
                  s.close()
                #sys.exit()
            #message_queue[s].put(pickled_data)

            # update starts 

            # you are A
            if(str(d['ACTION']).strip() == 'CHAT'):
              ticket = d['TICKET']
              b_port = d['B_PORT']
              b_ip = d['B_IP']
              b_pk = d['B_PK']
              b_iv = d['B_IV']
              b = d['B']
              IV_tracker[b] = b_iv
              port_tracker[b] = int(b_port)
              nonce = d['NONCE']
              new_challenge = d['CHALLENGE']


              if(long(nonce) + 1 == long(CHAT_NONCE)):
                message = {}
                message.update({'TICKET': ticket})
                message.update({'NONCE': new_challenge})
                a = random.randint(1, 9)
                A = (g**a) % p
                message.update({'A': A})
                message.update({'g': g})
                message.update({'p': p})

                try:
                  msg = util.encrypt_with_PSK(message, b_pk)
                  #pickled_msg = pickle.dumps(msg)
                except Exception as e:
                  print "An error occured while encrypting the text message - ", message, "! %s" %e

                protocol_identity = {}
                protocol_identity.update({'CIPHER': msg})
                protocol_identity.update({'PROTOCOL': 'PUBLIC_KEY'})

                pickled_msg = pickle.dumps(protocol_identity)
                udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 18000)
                udp_socket.sendto(pickled_msg,('localhost',int(b_port)))

              # update ends 

          else:
            print("Connection closed")
            if s in write_sockets:
              write_sockets.remove(s)
            read_sockets.remove(s)
            close_socket(s)
            del message_queue[s]

        elif s == udp_socket:

          # update begins 

          msg = s.recvfrom(30000)
          if msg:
            pickled_data = pickle.loads(msg[0])

            protocol = pickled_data['PROTOCOL']
            cipher = pickled_data['CIPHER']
            
            if(protocol == 'PUBLIC_KEY'):
              # You are user B
              cipher2, e_iv , e_sym_key = extract_cipher_data(cipher)
              decrypted_data = decrypt(cipher2, e_iv, e_sym_key)
              
              if(decrypted_data.has_key('A')):
                A = long(decrypted_data['A'])
                g = long(decrypted_data['g'])
                p = long(decrypted_data['p'])

                ticket = decrypted_data['TICKET']
                nonce = decrypted_data['NONCE']
                
                b = random.randint(100, 999)
                B = (g**b) % p
                b_shared_key = (A**b) % p

                hash_shared_key = util.MD5_HASH(shared_key)
                response = util.decrypt_using_Kas(ticket, hash_shared_key, GENERATED_IV)
                d = ast.literal_eval(response)
                message = {}
                message.update({'B': B})
                # B's username 
                message.update({'username': current_username})
                a_pk = d['A_PK']
                a_ip = d['A_IP']
                a_port = d['A_PORT']
                # A's username
                username = d['A']
                ticket_nonce = d['NONCE']

                if long(nonce) == long(ticket_nonce):
                  df_keys[username] = str(b_shared_key)
                  df_progress[current_username] = (2, username)
                  try:
                    msg = util.encrypt_with_PSK(message, a_pk)
                    #pickled_msg = pickle.dumps(msg)
                  except Exception as e:
                    print "An error occured while encrypting the text message - ", message, "! %s" %e

                  protocol_identity = {}
                  protocol_identity.update({'PROTOCOL': 'PUBLIC_KEY'})
                  protocol_identity.update({'CIPHER': msg})
                  pickled_msg = pickle.dumps(protocol_identity)
                  #udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 20000)
                  udp_socket.sendto(pickled_msg,('localhost',int(a_port)))

              else:
                # you are user A
                if(decrypted_data.has_key('B')):
                  B = long(decrypted_data['B'])
                  # B's username 
                  username = decrypted_data['username']

                  ds_shared_key = (B ** a) % p
                  df_keys[username] = str(ds_shared_key)

                  B_IV = IV_tracker[username]
                  B_port = port_tracker[username]

                  message_to_send = message_tracker[username]
                  hmac_msg = util.get_hmac(message_to_send, B_IV)
                  to_send_dict = {}
                  to_send_dict.update({'MESSAGE': message_to_send})
                  to_send_dict.update({'HMAC': hmac_msg})

                  try:
                    final_kas = util.MD5_HASH(df_keys[username])

                    to_send = util.encrypt_message_KAS(to_send_dict, final_kas, B_IV)
                  except Exception as e:
                    print "An error occured while encrypting the text message for CHAT. ", message, "! %s" %e

                  protocol_identity = {}
                  protocol_identity.update({'PROTOCOL': 'SESSION_KEY'})
                  protocol_identity.update({'CIPHER': to_send})
                  pickled_msg = pickle.dumps(protocol_identity)
                  udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 20000)
                  udp_socket.sendto(pickled_msg,('localhost',int(B_port)))
                  
            if(protocol == 'SESSION_KEY'):
              # you are user B 
              progress_tuple = df_progress[current_username]
              
              if (progress_tuple[0] == 2):
                b_username = progress_tuple[1]
                hash_shared_key = util.MD5_HASH(str(df_keys[b_username]))

                response = util.decrypt_using_Kas(cipher, hash_shared_key, GENERATED_IV)
                d = ast.literal_eval(response)
                msg_received = d['MESSAGE']
                msg_hmac = d['HMAC']
                util.verify_with_hmac(msg_received, msg_hmac, GENERATED_IV)
                print msg_received
                del df_progress[current_username]

            # update ends

      for s in writable:
        try:
          next_msg = message_queue[s].get_nowait()
          to_send = pickle.dumps(next_msg)
        except Queue.Empty:
          print("Queue Empty")
          write_sockets.remove(s)
        else:
          print("Sending message - %s to %s" %(to_send, s.getpeername())) 
          s.send(to_send)

      for s in exceptional:
        print("Exceptional condition occurred for user - %s" %(s.getpeername()))
        read_sockets.remove(s)
        if s in write_sockets:
          write_sockets.remove(s)
        close_socket(s)
        del message_queue[s]
  except KeyboardInterrupt:
    "Inside KeyboardInterrupt!!!!!!!!"
    server.close()
    for s in read_sockets:
      if s != sys.stdin:
        s.close()
    for s in write_sockets:
      s.close()
    sys.exit()
  except:
    print 'Closing client .....'
    server.close()
    for s in read_sockets:
      if s != sys.stdin:
        s.close()
    for s in write_sockets:
      s.close()
    sys.exit()
Пример #3
0
def non_blocking_listen(server):
  server.listen(5)
  read_sockets = [server]
  write_sockets = []
  message_queue = {}
  timeout = 30
  load_client_vault()
  try:
    while(read_sockets):
      readable, writable, exceptional = select.select(read_sockets, write_sockets, read_sockets, timeout)

      for s in readable:
        if s is server:
          conn, client_address = s.accept()
          print("Received connection - %s from %s" %(conn, client_address))
          conn.setblocking(0)
          read_sockets.append(conn)
          message_queue[conn] = Queue.Queue()
          client_progress[conn] = (1,)
        else:
          data = s.recv(40960)
          if data:
            pickled_data = pickle.loads(data)
            status = client_progress[s]

            if(status[0] == 1):
              #A, username = parse_data(pickled_data)
              cipher, e_iv , e_sym_key = extract_cipher_data(pickled_data)
              decrypted_data = decrypt(cipher, e_iv, e_sym_key)
              A = str(decrypted_data["A"])
              username = str(decrypted_data["username"])
              if(not logged_users.has_key(username)):
                num = util.get_random_challenge()
                hashed_num = util.get_hash(num)
                message_queue[s].put(hashed_num)
                # num is added so u can check in the next step that value sent by client is same as num 
                client_progress[s] = (2, A, username, num)
              else:
                print 'User: %s is already logged in!' %(username)
                message_queue[s].put('ERROR')

            if(status[0] == 2):
              salt = util.get_random_number() #Salt
              user_tuple = client_progress[s]
              username = user_tuple[2]
              numCheck = user_tuple[3]
              if user_tuple[1] and user_tuple[2] and pickled_data == numCheck:
                salt_and_B_dict = {}
                A = user_tuple[1]
                B, v, b = get_params(user_tuple[2], user_tuple[1], salt)
                u = util.H(A,B)
                signed_salt = util.sign_document(private_key, str(salt).encode())
                signed_B =  util.sign_document(private_key, str(B).encode())
                salt_and_B_dict.update({'SALT': salt})
                salt_and_B_dict.update({'SIGNED_SALT': signed_salt})
                salt_and_B_dict.update({'B': B})
                salt_and_B_dict.update({'SIGNED_B': signed_B})
                message_queue[s].put(salt_and_B_dict)
                Kas = util.get_server_shared_key(A, v, u, b) 
                client_progress[s] = (3, util.MD5_HASH(Kas), username)
            if(status[0] == 3):
                user_tuple = client_progress[s]
                cipher, e_iv , e_sym_key = extract_cipher_data(pickled_data)
                decrypted_data = decrypt(cipher, e_iv, e_sym_key)
                Challenge_PK = decrypted_data['CHALLENGE_PK']
                IV = decrypted_data['IV']
                final_decrypted_data = util.decrypt_using_Kas(Challenge_PK, user_tuple[1], IV)
                d= ast.literal_eval(final_decrypted_data)
                if str(d['CHALLENGE']) == str(decrypted_data['CHALLENGE']):
                  print 'Challenge matches'
                  #global logged_users
                  client_ip = s.getpeername()[0]
                  client_port = s.getpeername()[1]
                  ip_port = str(client_ip) + ":" + str(client_port)
                  logged_users[username] = (user_tuple[1], s, d['PK_CLIENT'],ip_port, IV) # .................
                else:
                  print 'Challenge does not match'

                nonce = d['CHALLENGE']
                subtracted_nonce = long(nonce) - 1
                #iv = os.urandom(16)
                encrypted_nonce = util.encrypt_message_KAS(str(subtracted_nonce), user_tuple[1], IV)
                message_queue[s].put(encrypted_nonce)
                client_progress[s] = (4, util.MD5_HASH(Kas), username, IV)

            if(status[0] == 4):
              user_tuple = client_progress[s]
              IV = user_tuple[3]
              final_decrypted_data = util.decrypt_using_Kas(pickled_data, user_tuple[1], IV)
              d= ast.literal_eval(final_decrypted_data)
              if(type(d) != long):
                valid = False
                if(action_progress.has_key(s)):
                  action_status = action_progress[s]
                  status_2 = action_status[1]
                  valid = (status_2 == 3)
                else:
                  valid = True

                if (valid):
                  if(d['ACTION'] == 'LIST'):
                    A_ip_port = ''
                    all_users = []
                    for username, value in logged_users.items():
                      if not username == d['username']:
                        A_ip_port = value[3]
                        all_users.append((username, A_ip_port))
                    if len(all_users) == 0:
                      all_users = 'No user is online currently'
                    action_challenge = util.get_random_number()
                    user_list = {}
                    user_list.update({'MESSAGE': all_users})
                    user_list.update({'NONCE': action_challenge})
                    user_list.update({'ACTION': 'LIST'})
                    final_kas = user_tuple[1]
                    try:
                      to_send = util.encrypt_message_KAS(user_list, final_kas, IV)
                    except:
                      print "An error occured while encrypting the text message for ACTION. ", message, "! %s" %e
                    message_queue[s].put(to_send)
                    action_progress[s] = ('LIST', 2, action_challenge)
                  
                  if(d['ACTION'] == 'LOGOUT'):
                    user_to_remove = d['username']
                    challenge_received = d['NONCE']
                    decrement_nonce = long(challenge_received) - 1
                    new_nonce = util.get_random_number()
                    user_list = {}
                    user_list.update({'MESSAGE': decrement_nonce})
                    user_list.update({'NONCE': new_nonce})
                    user_list.update({'ACTION': 'LOGOUT'})
                    final_kas = user_tuple[1]
                    try:
                      to_send = util.encrypt_message_KAS(user_list, final_kas, IV)
                    except:
                      print "An error occured while encrypting the text message for ACTION. ", message, "! %s" %e
                    message_queue[s].put(to_send)
                    action_progress[s] = ('LOGOUT', 2, new_nonce)
                  
                  # UPDATE START

                  if(d['ACTION'] == 'CHAT'):
                    A_ipport = ''
                    B_ipport = ''
                    A_PK = ''
                    B_PK = ''
                    Kbs = ''
                    Kas = ''
                    for username, value in logged_users.items():
                      if username == d['A']:
                        A_ipport = value[3]
                        Kas = value[0]
                        A_PK = str(value[2])
                      if username == d['B']:
                        B_ipport = value[3]
                        Kbs = value[0]
                        B_PK = value[2]

                    A_IP = A_ipport.split(":")[0]
                    A_PORT = A_ipport.split(":")[1]
                    username_A = d['A']
                    N6 = util.get_random_number()
                    TICKET = {}
                    ticket_and_stuff = {}
                    TICKET.update({'A_PORT':A_PORT})
                    TICKET.update({'A_IP':A_IP})
                    TICKET.update({'A_PK':A_PK})
                    TICKET.update({'A':username_A})
                    TICKET.update({'NONCE':N6})
                    final_kas = user_tuple[1]
                    username_B = str(d['B'])
                    # use B's IV
                    login_tuple = logged_users[username_B]    
                    B_IV = login_tuple[4]

                    Kbs_encrypted_ticket = util.encrypt_message_KAS(TICKET, Kbs, B_IV)
                    
                    N4 = d['NONCE']
                    B_IP = B_ipport.split(":")[0]
                    B_PORT = B_ipport.split(":")[1]
                    N4_minus_1 = long(N4) - 1

                    ticket_and_stuff.update({'TICKET':Kbs_encrypted_ticket})
                    ticket_and_stuff.update({'B_PORT':B_PORT})
                    ticket_and_stuff.update({'B_IP':B_IP})
                    ticket_and_stuff.update({'B_PK':B_PK})
                    ticket_and_stuff.update({'NONCE':N4_minus_1})
                    ticket_and_stuff.update({'CHALLENGE':N6})
                    ticket_and_stuff.update({'ACTION':'CHAT'})
                    ticket_and_stuff.update({'B_IV': B_IV})
                    ticket_and_stuff.update({'B': username_B})              
                    Kas_final_encrypt = util.encrypt_message_KAS(ticket_and_stuff, Kas, IV)
                    message_queue[s].put(Kas_final_encrypt)
                  #UPDATE END

              else:
                action_status = action_progress[s]
                if(action_status[1] == 2 and action_status[0] == 'LIST'):
                  action_progress[s] = (action_status[0], 3)
                if(action_status[1] == 2 and action_status[0] == 'LOGOUT'):
                  earlier_nonce = action_status[2]
                  if(long(final_decrypted_data) == long(earlier_nonce) - 1):
                    print ' deleting user info '
                    del logged_users[user_to_remove]
                    print 'Deleting user: '******' Did not receive logout confirmation '
                else:
                  print 'Message ignored'

            #message_queue[s].put(pickled_data)
            if s not in write_sockets:
              write_sockets.append(s)
          else:
            if (client_progress.has_key(s)):
              client_status = client_progress[s]
              if(client_status[0] > 1):
                print("Connection closed ...... !")
                del logged_users[client_status[2]]
                print 'Deleting user: '******'Closing server .....'
    server.close()
    for s in read_sockets:
      s.close()
    for s in write_sockets:
      s.close()