def test_successful_command_decryption(self): packet = assembly_packet_creator(COMMAND, payload=b"command_data", encrypt_packet=True)[0] self.assertEqual( decrypt_assembly_packet(packet, *self.args), assembly_packet_creator(COMMAND, payload=b"command_data")[0])
def test_successful_packet_decryption(self): packet = assembly_packet_creator(MESSAGE, payload="Test message", encrypt_packet=True)[0] self.assertEqual( decrypt_assembly_packet(packet, *self.args), assembly_packet_creator(MESSAGE, payload="Test message")[0])
def test_successful_packet_decryption_with_offset(self): packet = assembly_packet_creator(MESSAGE, payload="Test message", encrypt_packet=True, message_number=3)[0] self.assertEqual( decrypt_assembly_packet(packet, *self.args), assembly_packet_creator(MESSAGE, payload="Test message", message_number=3)[0])
def process_message_packet( ts: 'datetime', # Timestamp of received message packet assembly_packet_ct: bytes, # Encrypted assembly packet window_list: 'WindowList', # WindowList object packet_list: 'PacketList', # PacketList object contact_list: 'ContactList', # ContactList object key_list: 'KeyList', # KeyList object group_list: 'GroupList', # GroupList object settings: 'Settings', # Settings object file_keys: Dict[bytes, bytes], # Dictionary of file decryption keys message_log: 'MessageLog', # MessageLog object ) -> None: """Process received message packet.""" command_window = window_list.get_command_window() onion_pub_key, origin, assembly_packet_ct = separate_headers( assembly_packet_ct, [ONION_SERVICE_PUBLIC_KEY_LENGTH, ORIGIN_HEADER_LENGTH]) if onion_pub_key == LOCAL_PUBKEY: raise SoftError("Warning! Received packet masqueraded as a command.", window=command_window) if origin not in [ORIGIN_USER_HEADER, ORIGIN_CONTACT_HEADER]: raise SoftError("Error: Received packet had an invalid origin-header.", window=command_window) assembly_packet = decrypt_assembly_packet(assembly_packet_ct, onion_pub_key, origin, window_list, contact_list, key_list) p_type = (FILE if assembly_packet[:ASSEMBLY_PACKET_HEADER_LENGTH].isupper() else MESSAGE) packet = packet_list.get_packet(onion_pub_key, origin, p_type) logging = contact_list.get_contact_by_pub_key(onion_pub_key).log_messages try: packet.add_packet(assembly_packet) except SoftError: log_masking_packets(onion_pub_key, origin, logging, settings, packet, message_log) raise log_masking_packets(onion_pub_key, origin, logging, settings, packet, message_log) if packet.is_complete: process_complete_message_packet(ts, onion_pub_key, p_type, origin, logging, packet, window_list, contact_list, group_list, settings, message_log, file_keys)
def process_message(ts: 'datetime', assembly_packet_ct: bytes, window_list: 'WindowList', packet_list: 'PacketList', contact_list: 'ContactList', key_list: 'KeyList', group_list: 'GroupList', settings: 'Settings', master_key: 'MasterKey', file_keys: Dict[bytes, bytes]) -> None: """Process received private / group message.""" local_window = window_list.get_local_window() onion_pub_key, origin, assembly_packet_ct = separate_headers( assembly_packet_ct, [ONION_SERVICE_PUBLIC_KEY_LENGTH, ORIGIN_HEADER_LENGTH]) if onion_pub_key == LOCAL_PUBKEY: raise FunctionReturn( "Warning! Received packet masqueraded as a command.", window=local_window) if origin not in [ORIGIN_USER_HEADER, ORIGIN_CONTACT_HEADER]: raise FunctionReturn( "Error: Received packet had an invalid origin-header.", window=local_window) assembly_packet = decrypt_assembly_packet(assembly_packet_ct, onion_pub_key, origin, window_list, contact_list, key_list) p_type = FILE if assembly_packet[:ASSEMBLY_PACKET_HEADER_LENGTH].isupper( ) else MESSAGE packet = packet_list.get_packet(onion_pub_key, origin, p_type) logging = contact_list.get_contact_by_pub_key(onion_pub_key).log_messages def log_masking_packets(completed: bool = False) -> None: """Add masking packets to log file. If logging and log file masking are enabled, this function will in case of erroneous transmissions, store the correct number of placeholder data packets to log file to hide the quantity of communication that log file observation would otherwise reveal. """ if logging and settings.log_file_masking and (packet.log_masking_ctr or completed): no_masking_packets = len(packet.assembly_pt_list ) if completed else packet.log_masking_ctr for _ in range(no_masking_packets): write_log_entry(PLACEHOLDER_DATA, onion_pub_key, settings, master_key, origin) packet.log_masking_ctr = 0 try: packet.add_packet(assembly_packet) except FunctionReturn: log_masking_packets() raise log_masking_packets() if not packet.is_complete: return None try: if p_type == FILE: packet.assemble_and_store_file(ts, onion_pub_key, window_list) raise FunctionReturn( "File storage complete.", output=False) # Raising allows calling log_masking_packets elif p_type == MESSAGE: whisper_byte, header, assembled = separate_headers( packet.assemble_message_packet(), [WHISPER_FIELD_LENGTH, MESSAGE_HEADER_LENGTH]) if len(whisper_byte) != WHISPER_FIELD_LENGTH: raise FunctionReturn( "Error: Message from contact had an invalid whisper header." ) whisper = bytes_to_bool(whisper_byte) if header == GROUP_MESSAGE_HEADER: logging = process_group_message(assembled, ts, onion_pub_key, origin, whisper, group_list, window_list) elif header == PRIVATE_MESSAGE_HEADER: window = window_list.get_window(onion_pub_key) window.add_new(ts, assembled.decode(), onion_pub_key, origin, output=True, whisper=whisper) elif header == FILE_KEY_HEADER: nick = process_file_key_message(assembled, onion_pub_key, origin, contact_list, file_keys) raise FunctionReturn( f"Received file decryption key from {nick}", window=local_window) else: raise FunctionReturn( "Error: Message from contact had an invalid header.") # Logging if whisper: raise FunctionReturn("Whisper message complete.", output=False) if logging: for p in packet.assembly_pt_list: write_log_entry(p, onion_pub_key, settings, master_key, origin) except (FunctionReturn, UnicodeError): log_masking_packets(completed=True) raise finally: packet.clear_assembly_packets()
def process_command(ts: 'datetime', assembly_ct: bytes, window_list: 'WindowList', packet_list: 'PacketList', contact_list: 'ContactList', key_list: 'KeyList', group_list: 'GroupList', settings: 'Settings', master_key: 'MasterKey', gateway: 'Gateway', exit_queue: 'Queue[bytes]') -> None: """Decrypt command assembly packet and process command.""" assembly_packet = decrypt_assembly_packet(assembly_ct, LOCAL_PUBKEY, ORIGIN_USER_HEADER, window_list, contact_list, key_list) cmd_packet = packet_list.get_packet(LOCAL_PUBKEY, ORIGIN_USER_HEADER, COMMAND) cmd_packet.add_packet(assembly_packet) if not cmd_packet.is_complete: raise FunctionReturn("Incomplete command.", output=False) header, cmd = separate_header(cmd_packet.assemble_command_packet(), ENCRYPTED_COMMAND_HEADER_LENGTH) no = None # Keyword Function to run ( Parameters ) # -------------------------------------------------------------------------------------------------------------- d = { LOCAL_KEY_RDY: (local_key_rdy, ts, window_list, contact_list), WIN_ACTIVITY: (win_activity, window_list), WIN_SELECT: (win_select, cmd, window_list), CLEAR_SCREEN: (clear_screen, ), RESET_SCREEN: (reset_screen, cmd, window_list), EXIT_PROGRAM: (exit_tfc, exit_queue), LOG_DISPLAY: (log_command, cmd, no, window_list, contact_list, group_list, settings, master_key), LOG_EXPORT: (log_command, cmd, ts, window_list, contact_list, group_list, settings, master_key), LOG_REMOVE: (remove_log, cmd, contact_list, group_list, settings, master_key), CH_MASTER_KEY: (ch_master_key, ts, window_list, contact_list, group_list, key_list, settings, master_key), CH_NICKNAME: ( ch_nick, cmd, ts, window_list, contact_list, ), CH_SETTING: (ch_setting, cmd, ts, window_list, contact_list, group_list, key_list, settings, gateway), CH_LOGGING: (ch_contact_s, cmd, ts, window_list, contact_list, group_list, header), CH_FILE_RECV: (ch_contact_s, cmd, ts, window_list, contact_list, group_list, header), CH_NOTIFY: (ch_contact_s, cmd, ts, window_list, contact_list, group_list, header), GROUP_CREATE: (group_create, cmd, ts, window_list, contact_list, group_list, settings), GROUP_ADD: (group_add, cmd, ts, window_list, contact_list, group_list, settings), GROUP_REMOVE: (group_remove, cmd, ts, window_list, contact_list, group_list), GROUP_DELETE: (group_delete, cmd, ts, window_list, group_list), GROUP_RENAME: (group_rename, cmd, ts, window_list, contact_list, group_list), KEY_EX_ECDHE: (key_ex_ecdhe, cmd, ts, window_list, contact_list, key_list, settings), KEY_EX_PSK_TX: (key_ex_psk_tx, cmd, ts, window_list, contact_list, key_list, settings), KEY_EX_PSK_RX: (key_ex_psk_rx, cmd, ts, window_list, contact_list, key_list, settings), CONTACT_REM: (contact_rem, cmd, ts, window_list, contact_list, group_list, key_list, settings, master_key), WIPE_USR_DATA: (wipe, exit_queue) } # type: Dict[bytes, Any] try: from_dict = d[header] except KeyError: raise FunctionReturn("Error: Received an invalid command.") func = from_dict[0] parameters = from_dict[1:] func(*parameters)