Ejemplo n.º 1
0
def ping_check(username, password, target_connection_address, my_active_usernames=None):
    """
    Checks if another client is active

    Return:
        data_object - object
    """
    url = 'http://{}/api/ping_check'.format(target_connection_address)

    my_time = time.time()
    host = cherrypy.config.get('server.socket_host')
    port = cherrypy.config.get('server.socket_port')
    connection_address = '{}:{}'.format(host, port)
    connection_location = '2'

    headers = api_helper.create_header(username, password)

    if my_active_usernames != None:
        payload = {
            'my_time': my_time,
            'my_active_usernames': my_active_usernames,
            'connection_address': connection_address,
            'connection_location': connection_location,
        }
    else:
        payload = {
            'my_time': my_time,
            'connection_address': connection_address,
            'connection_location': connection_location,
        }
    json_bytes = json.dumps(payload).encode('utf-8')

    data_object = api_helper.get_data(url, headers=headers, data=json_bytes)
    return data_object
Ejemplo n.º 2
0
def group_invite(username, password, target_username):
    """
    Transmits a secret group message between users
    """
    url = 'http://172.23.159.9:1025/api/rx_groupinvite'  # uni

    loginserver_record = 'wyao332,69592f14f52422ecf713b21f1615da2fec7d67eb7f0a8c4d3a72121d8e49cb66,1559114951.7035556,d0a5992d76f5f5464ddc0a530d8ea5f8a99b0fde4e0a3d4b91d100b7515188929ef22801420f25cc0b0f51095fa8cd9fbe6d3c93e1a93b7b2857cafdd6159a0e'
    groupkey_hash = '69592f14f52422ecf713b21f1615da2fec7d67eb7f0a8c4d3a72121d8e49cb66'
    pubkey = '69592f14f52422ecf713b21f1615da2fec7d67eb7f0a8c4d3a72121d8e49cb66'
    encrypted_groupkey = pubkey
    ts = '1559114951.7035556'

    keys = security_helper.get_keys(
        loginserver_record + groupkey_hash + pubkey + username + encrypted_groupkey + str(ts))  # FOR TESTING PURPOSES

    headers = api_helper.create_header(username, password)

    payload = {
        'loginserver_record': loginserver_record,
        'groupkey_hash': groupkey_hash,
        'target_pubkey': pubkey,
        'target_username': username,
        'encrypted_groupkey': pubkey,
        'sender_created_at': str(ts),
        'signature': keys['signature'],
    }
    json_bytes = json.dumps(payload).encode('utf-8')

    data_object = api_helper.get_data(url, headers=headers, data=json_bytes)
    data_object = json.loads(data_object)

    return data_object
Ejemplo n.º 3
0
def add_pubkey(username, password):
    """
    Associates a public key with the user's account

    Return:
        data_object - object
    """
    url = "http://cs302.kiwi.land/api/add_pubkey"

    # generate new private key
    prikey = security_helper.generate_private_key()

    # upload private key to privatedata
    private_data = get_privatedata(username, password)
    (private_data['prikeys'])[0] = prikey
    add_privatedata(username, password, private_data)

    pubkey = security_helper.get_public_key(prikey)
    signature = security_helper.get_signature(prikey,
                                              pubkey,
                                              username=username)

    headers = api_helper.create_header(username, password)

    payload = {
        'pubkey': pubkey,
        'username': username,
        'signature': signature,
    }
    json_bytes = json.dumps(payload).encode('utf-8')

    data_object = api_helper.get_data(url, headers=headers, data=json_bytes)
    return data_object
Ejemplo n.º 4
0
def report_user_status(username, password, status='online'):
    """
    Informs the login server about connection information for the user

    Return:
        data_object - Python object
    """
    url = 'http://cs302.kiwi.land/api/report'

    host = cherrypy.config.get('server.socket_host')
    port = cherrypy.config.get('server.socket_port')
    connection_address = '{}:{}'.format(host, port)
    connection_location = '2'

    prikey = get_privatekey(username, password)
    pubkey = security_helper.get_public_key(prikey)

    headers = api_helper.create_header(username, password)

    payload = {
        'connection_address': connection_address,
        'connection_location': connection_location,
        'incoming_pubkey': pubkey,
        'status': status,
    }

    json_bytes = json.dumps(payload).encode('utf-8')

    data_object = api_helper.get_data(url, headers=headers, data=json_bytes)
    return data_object
Ejemplo n.º 5
0
def list_apis():
    """
    Lists the APIs supported by the login server
    """
    url = 'http://cs302.kiwi.land/api/list_apis'

    data_object = api_helper.get_data(url)

    return data_object
Ejemplo n.º 6
0
def server_pubkey():
    """
    Returns the public key of the login server

    Return:
        data_object - object
    """
    url = 'http://cs302.kiwi.land/api/loginserver_pubkey'

    data_object = api_helper.get_data(url)
    return data_object
Ejemplo n.º 7
0
def check_pubkey(username, password, pubkey):
    """
    Loads the loginserver_record for a given public key

    Return:
        data_object - object
    """
    url = "http://cs302.kiwi.land/api/check_pubkey?pubkey={}".format(pubkey)

    headers = api_helper.create_header(username, password)

    data_object = api_helper.get_data(url, headers=headers)
    return data_object
Ejemplo n.º 8
0
def load_new_apikey(username, password):
    """
    Returns a new API key for authentication for the rest of the session
    Note: implemented for future use

    Return:
        data_object - object
    """
    url = 'http://cs302.kiwi.land/api/load_new_apikey'

    headers = api_helper.create_header(username, password)
    data_object = api_helper.get_data(url, headers=headers)
    return data_object
Ejemplo n.º 9
0
def get_loginserver_record(username, password):
    """
    Loads the user's current loginserver_record for use in creating point-to-point messages.

    Return:
        data_object - object
    """
    url = 'http://cs302.kiwi.land/api/get_loginserver_record'

    headers = api_helper.create_header(username, password)

    data_object = api_helper.get_data(url, headers=headers)
    return data_object
Ejemplo n.º 10
0
def list_users(username, password):
    """
    Lists the connection details for all active users within the last five minutes

    Return:
        data_object - Python object
    """
    url = 'http://cs302.kiwi.land/api/list_users'

    headers = api_helper.create_header(username, password)

    data_object = api_helper.get_data(url, headers=headers)

    if data_object['response'] == 'ok':
        return data_object
    else:
        return {'response': 'error', 'message': data_object['message']}
Ejemplo n.º 11
0
def add_privatedata(username, password, data):
    """
    Saves symmetrically encrypted private data for a user

    Return:
        data_object - object
    """
    url = 'http://cs302.kiwi.land/api/add_privatedata'

    key = 'strongkey'  # FOR TESTING PURPOSE: change to take user input

    # data = {
    #     'prikeys': ['cd7f971fc826eeb354c5ade4293b5e83a93c74c1aa624a2c28e6a14b97ae3d0d'],
    #     'blocked_pubkeys': [],
    #     'blocked_usernames': [],
    #     'blocked_words': [],
    #     'blocked_message_signatures': [],
    #     'favourite_message_signatures': [],
    #     'friends_usernames': [],
    # }
    json_data = json.dumps(data)

    encrypted_data = security_helper.encrypt_data(key, json_data)

    loginserver_record = get_loginserver_record(username, password)
    ts = time.time()

    prikey = get_privatekey(username, password)
    pubkey = security_helper.get_public_key(prikey)
    message_data = encrypted_data + loginserver_record + str(ts)
    signature = security_helper.get_signature(prikey,
                                              pubkey,
                                              message_data=message_data)

    headers = api_helper.create_header(username, password)

    payload = {
        'privatedata': encrypted_data,
        'loginserver_record': loginserver_record,
        'client_saved_at': str(ts),
        'signature': signature,
    }
    json_bytes = json.dumps(payload).encode('utf-8')

    data_object = api_helper.get_data(url, headers=headers, data=json_bytes)
    return data_object
Ejemplo n.º 12
0
def ping(username, password):
    """
    Checks if the login server is online and authenticates login

    Return:
        data_object - object
    """
    url = 'http://cs302.kiwi.land/api/ping'

    prikey = get_privatekey(username, password)
    pubkey = security_helper.get_public_key(prikey)
    signature = security_helper.get_signature(prikey, pubkey)

    headers = api_helper.create_header(username, password)

    payload = {
        "pubkey": pubkey,
        "signature": signature,
    }
    json_bytes = json.dumps(payload).encode('utf-8')

    data_object = api_helper.get_data(url, headers=headers, data=json_bytes)
    return data_object
Ejemplo n.º 13
0
def get_privatedata(username, password):
    """
    Loads the saved symmetrically encrypted private data of the user

    Return:
        privatedata - decrypted data as Python object
        Or if error, Python object with error message
    """
    url = 'http://cs302.kiwi.land/api/get_privatedata'

    key = 'strongkey'  # FOR TESTING PURPOSE: change to take user input

    headers = api_helper.create_header(username, password)

    data_object = api_helper.get_data(url, headers=headers)

    if data_object['response'] == 'ok':
        encrypted_data = data_object['privatedata']
        decrypted_data = security_helper.decrypt_data(key, encrypted_data)
        privatedata = json.loads(decrypted_data)

        return privatedata
    else:
        return {'response': 'error', 'message': data_object['message']}
Ejemplo n.º 14
0
def private_message(username, password, target_username, message):
    """
    Transmits a secret message between users.
    """
    # sender details
    loginserver_record = login_server.get_loginserver_record(username, password)[
        'loginserver_record']
    ts = time.time()

    # receiver details
    target_pubkey = user_repository.get_pubkey(target_username)

    isOnline = False

    # finds connection address of receiver
    connection_address = None
    users = login_server.list_users(username, password)['users']
    for user in users:
        if user['username'] == target_username:
            cherrypy.log('{} is online'.format(target_username))
            isOnline = True
            connection_address = user['connection_address']

            if target_pubkey != user['incoming_pubkey']:
                target_pubkey = user['incoming_pubkey']
                user_repository.post_user_info(target_username, target_pubkey)
                cherrypy.log('updated user\'s pubkey')
            break

    if target_pubkey != None:
        # encrypt message
        encrypted_message = security_helper.encrypt_message(target_pubkey, message)

        prikey = login_server.get_privatekey(username, password)
        pubkey = security_helper.get_public_key(prikey)
        message_data = loginserver_record + \
            target_pubkey + username + message + str(ts)
        signature = security_helper.get_signature(
            prikey, pubkey, message_data=message_data)

        headers = api_helper.create_header(username, password)

        payload = {
            'loginserver_record': loginserver_record,
            'target_pubkey': target_pubkey,
            'target_username': target_username,
            'encrypted_message': encrypted_message,
            'sender_created_at': str(ts),
            'signature': signature,
        }
        json_bytes = json.dumps(payload).encode('utf-8')

        # send message
        pingFailed = False
        if isOnline:
            # ping receiver to check if available
            response = ping_check(username, password, connection_address)

            if response['response'] != 'ok':
                cherrypy.log('{}: Ping error: {}'.format(
                    connection_address, response['message']))
                pingFailed = True

            if not pingFailed:
                # send to receiver
                url = 'http://{}/api/rx_privatemessage'.format(connection_address)

                data_object = api_helper.get_data(
                    url, headers=headers, data=json_bytes)
                cherrypy.log('Private message sent (recipient)')            

        # send to everyone else
        if not isOnline or pingFailed:
            for user in users:
                response = ping_check(username, password, user['connection_address'])

                try:
                    if response['response'] != 'ok':
                        cherrypy.log('{}: Ping error: {}'.format(
                            user['connection_address'], response['message']))
                        data_object = {
                            'response': 'error',
                            'message': 'Ping error'
                        }
                    else:
                        url = 'http://{}/api/rx_privatemessage'.format(
                            user['connection_address'])

                        data_object = api_helper.get_data(
                            url, headers=headers, data=json_bytes)

                        data_object = api_helper.get_data(
                            url, headers=headers, data=json_bytes)
                        cherrypy.log('{}: {}'.format(
                            user['connection_address'], data_object['response']))
                except TypeError:
                    continue
                except KeyError:
                    continue

            cherrypy.log('Private message sent (everyone)')
    else:
        cherrypy.log('No target pubkey')

        data_object = {
            'response': 'error',
            'message': 'No pubkey for target user'
        } 

    return data_object
Ejemplo n.º 15
0
def check_messages(username, password):
    """
    Retrieve already-sent messages from other clients in the network

    Return:
    data_object - Python object
    """
    headers = api_helper.create_header(username, password)

    # get time user was last online
    login_times = user_repository.get_login_times(username)
    last_online = login_times[-2][0]

    # broadcast to everyone that's online
    users = login_server.list_users(username, password)['users']
    # users = [{'connection_address': '127.0.0.1:1025'}]

    for user in users:
        connection_address = user['connection_address']

        # ping client to check if they are online
        response = ping_check(username, password, connection_address)

        try:
            if response['response'] != 'ok':
                cherrypy.log('{}: Ping error: {}'.format(
                    connection_address, response['message']))
                continue
        except KeyError:
            continue
        except TypeError:
            continue

        url = 'http://{}/api/checkmessages?since={}'.format(
            connection_address, last_online)

        data_object = api_helper.get_data(
            url, headers=headers)

        try:
            if data_object['response'] == 'ok':
                broadcasts = data_object['broadcasts']
                private_messages = data_object['private_messages']

                # post new messages to database
                for b in broadcasts:
                    broadcast_repository.post_broadcast(
                        b['loginserver_record'], b['message'], b['sender_created_at'], b['signature'])

                for p in private_messages:
                    private_message_repository.post_message(
                        p['loginserver_record'], p['target_pubkey'], p['target_username'], p['encrypted_message'], p['sender_created_at'], p['signature'])

                cherrypy.log('{}: {}'.format(
                    connection_address, data_object['response']))
            else:
                cherrypy.log('{}: {}'.format(
                    connection_address, data_object['message']))
        except KeyError:
            continue
        except TypeError:
            continue
        except json.decoder.JSONDecodeError:
            continue

    return data_object
Ejemplo n.º 16
0
def broadcast(username, password, message):
    """
    Transmits a signed broadcast between users

    Returns:
        'ok' - string
    """
    loginserver_record = login_server.get_loginserver_record(username, password)[
        'loginserver_record']
    ts = time.time()

    prikey = login_server.get_privatekey(username, password)
    pubkey = security_helper.get_public_key(prikey)
    message_data = loginserver_record + message + str(ts)
    signature = security_helper.get_signature(
        prikey, pubkey, message_data=message_data)

    headers = api_helper.create_header(username, password)

    payload = {
        'loginserver_record': loginserver_record,
        'message': message,
        'sender_created_at': str(ts),
        'signature': signature,
    }
    json_bytes = json.dumps(payload).encode('utf-8')

    # broadcast to everyone that's online
    users = login_server.list_users(username, password)['users']

    for user in users:
        connection_address = user['connection_address']

        # ping client to check if they are online
        response = ping_check(username, password, connection_address)
        try:
            if response['response'] != 'ok':
                cherrypy.log('{}: Ping error: {}'.format(
                    connection_address, response['message']))
                continue
        except KeyError:
            continue
        except TypeError:
            continue

        url = 'http://{}/api/rx_broadcast'.format(connection_address)

        data_object = api_helper.get_data(
            url, headers=headers, data=json_bytes)

        try:
            if data_object['response'] == 'ok':
                cherrypy.log('{}: {}'.format(
                    connection_address, data_object['response']))
            else:
                cherrypy.log('{}: {}'.format(
                    connection_address, data_object['message']))
        except TypeError:
            continue
        except KeyError:
            continue

    cherrypy.log('Broadcast sent')
    return 'ok'