def test_function(self): # Setup master_key = MasterKey() settings = Settings() ts = datetime.datetime.now() o_getpass = getpass.getpass window_list = WindowList() contact_list = ContactList() group_list = GroupList() key_list = KeyList() getpass.getpass = lambda x: 'a' write_log_entry(F_S_HEADER + bytes(255), '*****@*****.**', settings, master_key) # Test self.assertEqual(master_key.master_key, bytes(32)) self.assertIsNone( change_master_key(ts, window_list, contact_list, group_list, key_list, settings, master_key)) self.assertNotEqual(master_key.master_key, bytes(32)) # Teardown getpass.getpass = o_getpass cleanup()
def test_export_short_private_message(self, _): # Setup # Test title displayed by the Receiver program. self.settings.software_operation = RX # Add a message from contact Alice to user (Bob). for p in assembly_packet_creator(MESSAGE, 'Hi Bob'): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key, origin=ORIGIN_CONTACT_HEADER) # Add a message from user (Bob) to Alice. for p in assembly_packet_creator(MESSAGE, 'Hi Alice'): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key) # Test self.assertIsNone(access_logs(*self.args, export=True)) with open("Receiver - Plaintext log (Alice)") as f: self.assertEqual( f.read(), f"""\ Log file of message(s) to/from contact Alice ════════════════════════════════════════════════════════════════════════════════ {self.time} Alice: Hi Bob {self.time} Me: Hi Alice <End of log file> """)
def test_export(self): # Setup for p in assembly_packet_creator(MESSAGE, b'A short message'): write_log_entry(p, '*****@*****.**', self.settings, self.master_key, origin=ORIGIN_CONTACT_HEADER) # Test self.assertIsNone( log_command(self.cmd_data, self.ts, self.window_list, self.contact_list, self.group_list, self.settings, self.master_key)) with open('UtM - Plaintext log (None)') as f: data = f.read() self.assertEqual( data, f"""\ Logfile of 1 most recent message to/from None ════════════════════════════════════════════════════════════════════════════════ {self.time} Bob: A short message <End of logfile> """)
def test_master_key_change(self, *_) -> None: # Setup write_log_entry(F_S_HEADER + bytes(PADDING_LENGTH), nick_to_pub_key("Alice"), self.tfc_log_database) self.contact_list.file_name = f'{DIR_USER_DATA}{RX}_contacts' self.group_list.file_name = f'{DIR_USER_DATA}{RX}_groups' self.key_list.file_name = f'{DIR_USER_DATA}{RX}_keys' self.settings.file_name = f'{DIR_USER_DATA}{RX}_settings' self.contact_list.database = TFCDatabase(self.contact_list.file_name, self.contact_list.master_key) self.group_list.database = TFCDatabase(self.group_list.file_name, self.group_list.master_key) self.key_list.database = TFCDatabase(self.key_list.file_name, self.group_list.master_key) self.settings.database = TFCDatabase(self.settings.file_name, self.settings.master_key) orig_cl_rd = self.contact_list.database.replace_database orig_gl_rd = self.group_list.database.replace_database orig_kl_rd = self.key_list.database.replace_database orig_st_rd = self.settings.database.replace_database self.contact_list.database.replace_database = lambda: None self.group_list.database.replace_database = lambda: None self.key_list.database.replace_database = lambda: None self.settings.database.replace_database = lambda: None # Test self.assertEqual(self.master_key.master_key, bytes(SYMMETRIC_KEY_LENGTH)) self.assertIsNone(ch_master_key(*self.args)) self.assertNotEqual(self.master_key.master_key, bytes(SYMMETRIC_KEY_LENGTH)) # Teardown self.contact_list.database.replace_database = orig_cl_rd self.group_list.database.replace_database = orig_gl_rd self.key_list.database.replace_database = orig_kl_rd self.settings.database.replace_database = orig_st_rd
def test_oversize_packet_raises_critical_error(self): # Setup assembly_p = F_S_HEADER + bytes(PADDING_LENGTH) + b'a' # Test with self.assertRaises(SystemExit): write_log_entry(assembly_p, nick_to_pub_key('Alice'), self.settings, self.master_key)
def log_masking_packets( onion_pub_key: bytes, # Onion address of associated contact origin: bytes, # Origin of packet (user / contact) logging: bool, # When True, message will be logged settings: 'Settings', # Settings object packet: 'Packet', # Packet object message_log: 'MessageLog', # MessageLog object completed: bool = False, # When True, logs placeholder data for completed message ) -> 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, message_log, origin) packet.log_masking_ctr = 0
def test_master_key_change(self, *_): # Setup write_log_entry(F_S_HEADER + bytes(PADDING_LENGTH), nick_to_pub_key("Alice"), self.settings, self.master_key) # Test self.assertEqual(self.master_key.master_key, bytes(SYMMETRIC_KEY_LENGTH)) self.assertIsNone(ch_master_key(*self.args)) self.assertNotEqual(self.master_key.master_key, bytes(SYMMETRIC_KEY_LENGTH))
def test_long_private_message(self): # Setup # Add an assembly packet sequence for contact containing cancel packet that the function should skip packets = assembly_packet_creator(MESSAGE, self.msg) packets = packets[2:] + [M_C_HEADER + bytes(PADDING_LEN)] for p in packets: write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Add an orphaned 'append' assembly packet that the function should skip write_log_entry(M_A_HEADER + bytes(PADDING_LEN), '*****@*****.**', self.settings, self.masterkey) # Add a group message that the function should skip for p in assembly_packet_creator(MESSAGE, b'This is a short message', group_name='test_group'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Add normal messages for contact and user that should be displayed for p in assembly_packet_creator(MESSAGE, self.msg): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER) for p in assembly_packet_creator(MESSAGE, self.msg): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Test self.assertPrints((CLEAR_ENTIRE_SCREEN + CURSOR_LEFT_UP_CORNER + f"""\ Logfile of messages to/from Alice ════════════════════════════════════════════════════════════════════════════════ {self.time} Alice: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean condimentum consectetur purus quis dapibus. Fusce venenatis lacus ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed bibendum velit maximus in. Aliquam ac metus risus. Sed cursus ornare luctus. Integer aliquet lectus id massa blandit imperdiet. Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl. Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed commodo arcu. In hac habitasse platea dictumst. Integer luctus aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis ullamcorper leo. Nunc egestas lectus eget est porttitor, in iaculis felis scelerisque. In sem elit, fringilla id viverra commodo, sagittis varius purus. Pellentesque rutrum lobortis neque a facilisis. Mauris id tortor placerat, aliquam dolor ac, venenatis arcu. {self.time} Me: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean condimentum consectetur purus quis dapibus. Fusce venenatis lacus ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed bibendum velit maximus in. Aliquam ac metus risus. Sed cursus ornare luctus. Integer aliquet lectus id massa blandit imperdiet. Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl. Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed commodo arcu. In hac habitasse platea dictumst. Integer luctus aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis ullamcorper leo. Nunc egestas lectus eget est porttitor, in iaculis felis scelerisque. In sem elit, fringilla id viverra commodo, sagittis varius purus. Pellentesque rutrum lobortis neque a facilisis. Mauris id tortor placerat, aliquam dolor ac, venenatis arcu. <End of logfile> """), access_logs, self.window, self.contact_list, self.group_list, self.settings, self.masterkey)
def test_no_aborts_removal(self, *_): # Setup write_log_entry(M_S_HEADER + PADDING_LENGTH * b'a', nick_to_pub_key('Alice'), self.settings, self.master_key) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH) # Test self.assert_fr("Log file removal aborted.", remove_log, UserInput('/rmlogs Alice'), *self.args)
def test_unknown_selector_raises_fr(self, _): # Setup write_log_entry(M_S_HEADER + PADDING_LENGTH * b'a', nick_to_pub_key("Alice"), self.settings, self.master_key) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH) # Test self.assert_fr("Error: Unknown selector.", remove_log, UserInput(f'/rmlogs unknown'), *self.args)
def test_no_aborts_removal(self): # Setup write_log_entry(M_S_HEADER + PADDING_LEN * b'a', '*****@*****.**', self.settings, self.master_key) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), LOG_ENTRY_LENGTH) builtins.input = lambda _: 'No' self.assertFR("Logfile removal aborted.", remove_log, UserInput('/rmlogs Alice'), self.contact_list, self.settings, self.c_queue, self.master_key)
def test_transmitter_command(self, *_): # Setup write_log_entry(M_S_HEADER + PADDING_LENGTH * b'a', nick_to_pub_key('Alice'), self.settings, self.master_key) # Test self.assertIsNone(change_master_key(UserInput("passwd tx"), *self.args)) self.assertEqual(self.queues[COMMAND_PACKET_QUEUE].qsize(), 0) self.assertEqual(self.queues[KEY_MANAGEMENT_QUEUE].qsize(), 1)
def test_master_key_change(self): # Setup write_log_entry(F_S_HEADER + bytes(PADDING_LEN), '*****@*****.**', self.settings, self.master_key) # Test self.assertEqual(self.master_key.master_key, bytes(KEY_LENGTH)) self.assertIsNone( change_master_key(self.ts, self.window_list, self.contact_list, self.group_list, self.key_list, self.settings, self.master_key)) self.assertNotEqual(self.master_key.master_key, bytes(KEY_LENGTH))
def test_log_remove_with_nick(self, _): # Setup write_log_entry(M_S_HEADER + PADDING_LENGTH * b'a', nick_to_pub_key("Alice"), self.settings, self.master_key) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH) # Test self.assert_fr("Removed log entries for contact 'Alice'.", remove_log, UserInput('/rmlogs Alice'), *self.args) self.assertEqual(os.path.getsize(self.file_name), 0) self.assertEqual(self.queues[COMMAND_PACKET_QUEUE].qsize(), 1)
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
def test_short_group_message(self, _): # Setup self.window = RxWindow(type=WIN_TYPE_GROUP, uid=group_name_to_group_id('test_group'), name='test_group', group=self.group, type_print='group', group_list=self.group_list) # Add messages to Alice and Charlie. Add duplicate of outgoing message that should be skipped by access_logs. for p in assembly_packet_creator(MESSAGE, 'This is a short message', group_id=self.window.uid): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key) write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key, origin=ORIGIN_CONTACT_HEADER) write_log_entry(p, nick_to_pub_key('Charlie'), self.settings, self.master_key) write_log_entry(p, nick_to_pub_key('Charlie'), self.settings, self.master_key, origin=ORIGIN_CONTACT_HEADER) # Test self.assert_prints((CLEAR_ENTIRE_SCREEN + CURSOR_LEFT_UP_CORNER + f"""\ Log file of message(s) sent to group test_group ════════════════════════════════════════════════════════════════════════════════ {self.time} Me: This is a short message {self.time} Alice: This is a short message {self.time} Charlie: This is a short message <End of log file> """), access_logs, self.window, self.contact_list, self.group_list, self.settings, self.master_key)
def test_database_encryption_with_another_key(self, _: Any) -> None: # Setup window = RxWindow(type=WIN_TYPE_CONTACT, uid=nick_to_pub_key('Alice'), name='Alice', type_print='contact') contact_list = ContactList(self.old_master_key, self.settings) contact_list.contacts = [create_contact('Alice')] group_list = GroupList() # Create temp file that must be removed. temp_file_data = os.urandom(LOG_ENTRY_LENGTH) with open(self.tmp_file_name, 'wb+') as f: f.write(temp_file_data) # Add a message from contact Alice to user (Bob). for p in assembly_packet_creator(MESSAGE, 'This is a short message'): write_log_entry(p, nick_to_pub_key('Alice'), self.message_log, origin=ORIGIN_CONTACT_HEADER) # Add a message from user (Bob) to Alice. for p in assembly_packet_creator(MESSAGE, 'This is a short message'): write_log_entry(p, nick_to_pub_key('Alice'), self.message_log) # Check logfile content. message = (CLEAR_ENTIRE_SCREEN + CURSOR_LEFT_UP_CORNER + f"""\ Log file of message(s) sent to contact Alice ════════════════════════════════════════════════════════════════════════════════ {self.time} Alice: This is a short message {self.time} Me: This is a short message <End of log file> """) self.assertIsNone( change_log_db_key(self.old_master_key.master_key, self.new_master_key.master_key, self.settings)) with open(self.tmp_file_name, 'rb') as f: purp_temp_data = f.read() self.assertNotEqual(purp_temp_data, temp_file_data) # Test that decryption with new key is identical. replace_log_db(self.settings) self.assert_prints(message, access_logs, window, contact_list, group_list, self.settings, self.new_master_key) # Test that temp file is removed. self.assertFalse(os.path.isfile(self.tmp_file_name))
def test_removal_of_contact_logs(self) -> None: # Setup short_msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." # Create temp file that must be removed. with open(self.tmp_file_name, 'wb+') as f: f.write(os.urandom(LOG_ENTRY_LENGTH)) # Add a long message sent to both Alice and Bob. for p in assembly_packet_creator(MESSAGE, self.msg): write_log_entry(p, nick_to_pub_key('Alice'), self.tfc_log_database) write_log_entry(p, nick_to_pub_key('Charlie'), self.tfc_log_database) # Add a short message sent to both Alice and Bob. for p in assembly_packet_creator(MESSAGE, short_msg): write_log_entry(p, nick_to_pub_key('Alice'), self.tfc_log_database) write_log_entry(p, nick_to_pub_key('Charlie'), self.tfc_log_database) # Test self.assert_se(f"Removed log entries for contact '{nick_to_short_address('Alice')}'.", remove_logs, *self.args, selector=nick_to_pub_key('Alice')) self.assert_se(f"Removed log entries for contact '{nick_to_short_address('Charlie')}'.", remove_logs, *self.args, selector=nick_to_pub_key('Charlie')) self.assert_se(f"Found no log entries for contact '{nick_to_short_address('Alice')}'.", remove_logs, *self.args, selector=nick_to_pub_key('Alice')) self.contact_list.contacts = [create_contact('Alice')] self.assert_se(f"Found no log entries for contact 'Alice'.", remove_logs, *self.args, selector=nick_to_pub_key('Alice')) self.assert_se(f"Found no log entries for group '2e8b2Wns7dWjB'.", remove_logs, *self.args, selector=group_name_to_group_id('searched_group'))
def test_log_remove(self): # Setup write_log_entry(M_S_HEADER + PADDING_LEN * b'a', '*****@*****.**', self.settings, self.master_key) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), LOG_ENTRY_LENGTH) # Test self.assertIsNone( remove_log(UserInput('/rmlogs Alice'), self.contact_list, self.settings, self.c_queue, self.master_key)) time.sleep(0.1) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), 0) self.assertEqual(self.c_queue.qsize(), 1)
def test_log_remove_with_unknown_onion_address(self, *_): # Setup write_log_entry(M_S_HEADER + PADDING_LENGTH * b'a', nick_to_pub_key("Alice"), self.settings, self.master_key) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH) # Test self.assert_fr( "Found no log entries for contact 'w5sm3'.", remove_log, UserInput(f'/rmlogs {nick_to_onion_address("Unknown")}'), *self.args) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH) self.assertEqual(self.queues[COMMAND_PACKET_QUEUE].qsize(), 1)
def test_function(self): #Setup masterkey = MasterKey() settings = Settings() # Test self.assertIsNone(write_log_entry(F_S_HEADER + bytes(255), '*****@*****.**', settings, masterkey)) self.assertTrue(os.path.isfile(f'{DIR_USER_DATA}/ut_logs')) entry_size = 24 + 4 + 1 + 1024 + 1 + 255 + 16 self.assertTrue(os.path.getsize(f'{DIR_USER_DATA}/ut_logs') % entry_size == 0) self.assertIsNone(write_log_entry(F_S_HEADER + bytes(255), '*****@*****.**', settings, masterkey)) self.assertTrue(os.path.getsize(f'{DIR_USER_DATA}/ut_logs') % entry_size == 0) # Teardown cleanup()
def test_txm_command(self): # Setup settings = Settings(software_operation='ut') getpass.getpass = lambda _: 'a' write_log_entry(M_S_HEADER + PADDING_LEN * b'a', '*****@*****.**', settings, self.master_key) # Test self.assertIsNone( change_master_key(UserInput("passwd tx"), self.contact_list, self.group_list, settings, self.queues, self.master_key)) time.sleep(0.1) self.assertEqual(self.queues[COMMAND_PACKET_QUEUE].qsize(), 0) self.assertEqual(self.queues[KEY_MANAGEMENT_QUEUE].qsize(), 1)
def log_masking_packets(completed: bool = False) -> None: """Add masking packets to log file. If logging and logfile masking are enabled this function will in case of erroneous transmissions, store the correct number of placeholder data packets to log file to hide quantity of communication that log file observation would reveal. """ if logging and settings.logfile_masking and (packet.log_masking_ctr or completed): iterator = packet.assembly_pt_list if completed else range( packet.log_masking_ctr) # type: Any for _ in iterator: write_log_entry(PLACEHOLDER_DATA, account, settings, master_key, origin) packet.log_masking_ctr = 0
def test_log_remove_with_group_name(self, _): # Setup for p in assembly_packet_creator( MESSAGE, 'This is a short group message', group_id=group_name_to_group_id('test_group')): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH) # Test self.assert_fr("Removed log entries for group 'test_group'.", remove_log, UserInput(f'/rmlogs test_group'), *self.args) self.assertEqual(os.path.getsize(self.file_name), 0) self.assertEqual(self.queues[COMMAND_PACKET_QUEUE].qsize(), 1)
def test_successful_export_command(self, *_): # Setup self.window.type = 'contact' self.window.uid = nick_to_pub_key('Alice') whisper_header = b'\x00' packet = split_to_assembly_packets( whisper_header + PRIVATE_MESSAGE_HEADER + b'test', MESSAGE)[0] write_log_entry(packet, nick_to_pub_key('Alice'), self.settings, self.master_key) # Test for command in ['export', 'export 1']: self.assert_fr(f"Exported log file of contact 'Alice'.", log_command, UserInput(command), self.window, ContactList(nicks=['Alice']), self.group_list, self.settings, self.queues, self.master_key)
def test_log_entry_is_concatenated(self): for i in range(5): assembly_p = F_S_HEADER + bytes(PADDING_LENGTH) self.assertIsNone( write_log_entry(assembly_p, nick_to_pub_key('Alice'), self.settings, self.master_key)) self.assertTrue(os.path.getsize(self.log_file), (i + 1) * LOG_ENTRY_LENGTH)
def test_export(self, _): # Setup for p in assembly_packet_creator(MESSAGE, 'A short message'): write_log_entry(p, nick_to_pub_key("Bob"), self.settings, self.master_key, origin=ORIGIN_CONTACT_HEADER) # Test self.assertIsNone(log_command(self.cmd_data, *self.args)) with open('Transmitter - Plaintext log (Bob)') as f: data = f.read() self.assertEqual(data, f"""\ Log file of 1 most recent message(s) sent to contact Bob ════════════════════════════════════════════════════════════════════════════════ {self.time} Bob: A short message <End of log file> """)
def test_successful_export_command(self, *_): # Setup from src.common.db_masterkey import MasterKey self.master_key = MasterKey(operation=TX, local_test=True) self.window.type = WIN_TYPE_CONTACT self.window.uid = nick_to_pub_key('Alice') whisper_header = bool_to_bytes(False) packet = split_to_assembly_packets( whisper_header + PRIVATE_MESSAGE_HEADER + b'test', MESSAGE)[0] write_log_entry(packet, nick_to_pub_key('Alice'), self.settings, self.master_key) # Test for command in ['export', 'export 1']: self.assert_fr(f"Exported log file of contact 'Alice'.", log_command, UserInput(command), self.window, ContactList(nicks=['Alice']), self.group_list, self.settings, self.queues, self.master_key)
def test_function(self): # Setup ts = datetime.datetime.now() no_msg = int_to_bytes(1) cmd_data = b'*****@*****.**' + US_BYTE + no_msg window_list = WindowList() contact_list = ContactList() settings = Settings() master_key = MasterKey() write_log_entry(F_S_HEADER + bytes(255), '*****@*****.**', settings, master_key) # Test self.assertIsNone( export_logs(cmd_data, ts, window_list, contact_list, settings, master_key)) os.remove('Unittest - Plaintext log (None)') cleanup()
def test_export_short_private_message(self): # Setup for p in assembly_packet_creator(MESSAGE, b'Hi Bob'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER) for p in assembly_packet_creator(MESSAGE, b'Hi Alice'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Test self.assertIsNone(access_logs(self.window, self.contact_list, self.group_list, self.settings, self.masterkey, export=True)) with open("UtM - Plaintext log (Alice)") as f: exported_log = f.read() self.assertEqual(exported_log, f"""\ Logfile of messages to/from Alice ════════════════════════════════════════════════════════════════════════════════ {self.time} Alice: Hi Bob {self.time} Me: Hi Alice <End of logfile> """)