Exemple #1
0
def AES_decrypt(message, key, **kwargs):
    """
    Decrypt a message using AES cipher

    Args:
        message <bytes> - message to be decrypted
        key <bytes> - session key of size 8 or 16

    Kwargs:
        iv <bytes> - initialization vector
        iv_block <int> - size of the random initialization vector for CBC mode
        encoding <str> - string coding

    Return:
        msg_dec <bytes> - decrypted message
    """
    if not message:
        return message
    if key is None:
        fab_log('Decryption requires a cipher key!', verbose_mode=4)
        return
    cipher = AES_from_key(key, **kwargs)
    dec_cipher = cipher.decryptor()
    msg_dec = dec_cipher.update(message) + dec_cipher.finalize()
    msg_dec = block_unpad(msg_dec)
    return msg_dec
Exemple #2
0
    def AES_encrypt(self, message, key=None, **kwargs):
        """
        Fast AES encryption of a message

        Args:
            message <bytes> - message to be encrypted

        Kwargs:
            key <bytes> - session key of size 8 or 16
            iv <bytes> - initialization vector
            iv_block <int> - size of the random initialization vector for CBC mode
            encoding <str> - string coding

        Return:
            msg_enc <bytes> - encrypted message
        """
        if not message:
            return message
        key = self.key128 if key is None else key
        if self.key128 is None:
            fab_log('Encryption failed! Proceeding without encryption...',
                    verbose_mode=4)
            return message
        msg_enc = AES_encrypt(message, key, **kwargs)
        return msg_enc
Exemple #3
0
def ask_for_username(client, encoding=fc.DEFAULT_ENC):
    """
    Ask client for a valid username

    Args:
        client <socket object> - client socket

    Kwargs:
        encoding <str> - string coding

    Return:
        username <str> - received username
    """
    client.send(query_msg('Q:USERNAME'))
    while True:
        username = client.recv(1024).decode(encoding)
        knowns = known_users()
        if not fc.ALLOW_UNKNOWN and username in knowns:
            break
        elif fc.ALLOW_UNKNOWN and username not in clients:
            break
        else:
            try:
                client.send(query_msg('Q:CHUSERNAME'))
            except BrokenPipeError:
                fab_log('EXIT', username)
                return None
    return username
Exemple #4
0
def AES_from_key(key, iv=None, iv_block=16, encoding=fc.DEFAULT_ENC):
    """
    Create an AES cipher from a key

    Args:
        key <bytes> - session key of size 8 or 16

    Kwargs:
        iv <bytes> - initialization vector
        iv_block <int> - size of the random initialization vector for CBC mode
        encoding <str> - string coding

    Return:
        cipher <cryptography..Cipher object> - AES cipher
    """
    if isinstance(key, str):
        key = key.encode(encoding)
    if len(key) == 8:
        key2 = key + key[::-1]
    elif len(key) == 16:
        key2 = key
    elif len(key) > 16:
        key2 = key[:16]
    else:
        fab_log('AES requires a cipher key of length of N16!', verbose_mode=5)
        return
    iv = iv if iv is not None else key2
    AES_cipher = ciphers.Cipher(algorithm=ciphers.algorithms.AES(key2),
                                mode=ciphers.modes.CBC(iv))
    return AES_cipher
Exemple #5
0
 def test_fab_log(self):
     """ # fabular.comm.fab_log """
     sys_keys = ['CONN', 'USRN', 'CUSR', 'DCRY', 'FDCR', 'WRYT',
                 'CHAT', 'ENTR', 'EXIT', 'INIS', 'ENDS']
     for sys_key in sys_keys:
         self.printf((sys_key, '', {'verbose_mode': 3}))
         self.assertLogs(fcomm.fab_log(sys_key, '', verbose_mode=3))
Exemple #6
0
def handle(server, client_key):
    """
    Client connection handler

    Args:
        server <socket object> - server socket
        client_key <str> - client connected as USERNAME=client_key

    Kwargs/Return:
        None
    """
    global clients
    while True:
        if client_key not in clients:
            break
        try:
            data = clients[client_key].recv(1024)
            if data:
                if clients.is_encrypted[client_key]:
                    message = clients.secret[client_key].AES_decrypt(data)
                else:
                    message = data.decode(fc.DEFAULT_ENC)
                message = fab_msg('CHAT',
                                  message,
                                  prefix='{}{}>{} '.format(
                                      ansi_map[clients.color[client_key]],
                                      client_key, ansi_map['reset']),
                                  suffix='')
                broadcast(message)

        except Exception as ex:
            client = clients.pop(client_key)
            if client:
                client.close()
                exit_msg = fab_msg('EXIT', client_key)
                broadcast(exit_msg)
            fab_log('fabular.server.handle: {}'.format(ex), verbose_mode=1)
            return
Exemple #7
0
    def Fernet_decrypt(self, message, key=None, **kwargs):
        """
        Fernet decryption scheme

        Args:
            message <bytes> - message to be decrypted

        Kwargs:
            key <bytes> - Fernet session key
            encoding <str> - string coding

        Return:
            msg_dec <bytes> - decrypted message
        """
        if not message:
            return message
        key = self.session if key is None else key
        if self.session is None:
            fab_log('Encryption failed! Proceeding without encryption...',
                    verbose_mode=4)
            return message
        msg_dec = Fernet_decrypt(message, key, **kwargs)
        return msg_dec
Exemple #8
0
def broadcast(data):
    """
    Broadcast a message to all clients

    Args:
        data <bytes/str> - the message to be broadcast

    Kwargs/Return:
        None
    """
    if isinstance(data, str):
        data = data.encode(fc.DEFAULT_ENC)
    for username in clients:
        if clients[username]:
            if clients.is_encrypted[username]:
                message = clients.secret[username].AES_encrypt(data)
            else:
                message = data
            try:
                clients[username].send(message)
            except Exception as ex:
                clients.pop(username)
    fab_log(data, verbose_mode=fc.VERBOSE)
Exemple #9
0
    def AES_decrypt(self, message, key=None, **kwargs):
        """
        Fast AES decryption of a message

        Args:
            message <bytes> - message to be decrypted

        Kwargs:
            key <bytes> - session key of size 8 or 16
            iv <bytes> - initialization vector
            iv_block <int> - size of the random initialization vector for CBC mode
            encoding <str> - string coding

        Return:
            msg_dec <str> - decrypted message
        """
        if not message:
            return message
        key = self.key128 if key is None else key
        if self.key128 is None:
            fab_log('Decryption requires a cipher key!', verbose_mode=4)
            return message
        msg_dec = AES_decrypt(message, key, **kwargs)
        return msg_dec
Exemple #10
0
def main(host=LOCALHOST, port=PORT):
    """
    Start a listening server and handle incoming connections

    Args:
        None

    Kwargs:
        host <str> - host IP address
        port <int/str> - IP port

    Return:
        None
    """
    global clients

    try:
        # Name definitions
        file_id = input('Session name: ')
        if not file_id:
            file_id = 'server'
        pw = pw_prompt(confirm=True)
        # RSA keys
        server_secrets = Secrets.random(file_id='server')
        server_secrets.pw = pw
        if not server_secrets.check_hash():
            sys.exit()

        # Set up server socket
        clients = Clients()
        server = init_server(host, port, max_conn=16)
        fab_log('INIS', verbose_mode=3)

        # open ngrok tunnel
        tunnel = ngrok.connect(fc.PORT, "tcp")
        public_addr = tunnel.public_url
        pub_host, pub_port = public_addr.split(':')[1:]
        pub_host = pub_host[2:]
        fab_log(f"Opened tunnel @ --host {pub_host} --port {pub_port}...",
                verbose_mode=3)

        # start accept thread
        accept_thread = threading.Thread(target=handshake,
                                         args=(
                                             server,
                                             server_secrets,
                                         ))
        accept_thread.daemon = True
        accept_thread.start()
        accept_thread.join()
    except KeyboardInterrupt:
        fab_log('ENDS', verbose_mode=3)
Exemple #11
0
def receive(client):
    """
    Message recipience loop; handles special keys and reacts accordingly

    Args:
        client <socket.socket object> - client socket

    Kwargs/Return:
        None
    """
    global username, client_secrets, accepted, decode, stop_threads
    while True:
        if stop_threads:
            break
        try:
            message = client.recv(fc.BLOCK_SIZE)
            if message:
                if is_query(message, 'Q:USERNAME'):
                    client.send(username.encode(fc.DEFAULT_ENC))
                elif is_query(message, 'Q:CHUSERNAME'):
                    fab_log('CUSR', verbose_mode=3)
                    username = input('Enter another username: '******'Q:PUBKEY'):
                    client.send(client_secrets.pubkey)
                elif is_query(message, 'Q:SESSION_KEY'):
                    if fc.ENCRYPTION:
                        client.send(f'{username}: Setting up encryption...'.encode(fc.DEFAULT_ENC))
                        fab_log('DCRY', verbose_mode=3)
                        enc_msg = client.recv(2*fc.BLOCK_SIZE)
                        server_keys = client_secrets.hybrid_decrypt(enc_msg)
                        server_secrets = Secrets.from_keys(server_keys)
                        if server_secrets is not None:
                            client_secrets.sesskey = server_secrets.sesskey
                            decode = True
                            client.send(b'1')
                        else:
                            fab_log('FDCR', verbose_mode=3)
                            client.send(b'0')
                    else:
                        client.send(f'{username}: Proceed without encryption'.encode(
                            fc.DEFAULT_ENC))
                        client.recv(2*fc.BLOCK_SIZE)
                        server_secrets = Secrets()
                        client.send(b'0')
                elif is_query(message, 'Q:ACCEPT'):
                    client.send(f'{username}: Starting Thread(write)...'.encode(fc.DEFAULT_ENC))
                    fab_log('WRYT', verbose_mode=3)
                    fab_log('', verbose_mode=3)
                    accepted = True
                elif is_query(message, 'Q:KILL'):
                    fab_log('LERR', verbose_mode=3)
                    accepted = False
                    stop_threads = True
                else:
                    if decode:
                        message = client_secrets.AES_decrypt(message)
                    fab_log(message)
        except Exception as ex:
            fab_log('fabular.client.receive: {}'.format(ex), verbose_mode=5)
            stop_threads = True
            client.close()
            break
Exemple #12
0
def handshake(server, secrets=None):
    """
    Server main loop: Accept and set up new incoming connections

    Args:
        server <socket object> - server socket

    Kwargs:
        secrets <Secrets object> - secret keys to be exchanged with client

    Return:
        None
    """
    global clients
    v = dict(verbose_mode=fc.VERBOSE)
    while True:
        try:
            client, address = server.accept()
            fab_log('CONN', address, **v)

            # set up username
            username = ask_for_username(client)
            if username:
                fab_log('USRN', username, **v)

            # encryption handshake
            client_secrets, status, is_encrypted = \
                encryption_setup(client, secrets=secrets)
            if status:
                fab_log(status, verbose_mode=3)

            # add username to user table and current clients
            status = register_user(username, client, address, is_encrypted,
                                   client_secrets)
            if status == 0:
                fab_log('LERR', username)
                known = known_users()
                try:
                    client.send(query_msg('Q:KILL'))
                    client.close()
                except BrokenPipeError:
                    pass
                continue

            # announce entry of user
            client.send(query_msg('Q:ACCEPT'))
            try:
                fab_log(client.recv(256), verbose_mode=3)
                broadcast(fab_msg('ENTR', username))
            except UnicodeDecodeError:
                pass

            handle_thread = threading.Thread(target=handle,
                                             args=(
                                                 server,
                                                 username,
                                             ))
            handle_thread.daemon = True
            handle_thread.start()

        except KeyboardInterrupt:
            fab_log('ENDS', verbose_mode=3)
            return