def test_invalid_window_raises_fr(self, _): # Setup assembly_ct_list = assembly_packet_creator(MESSAGE, 'test_message', origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), group_id=self.group_id) self.group_list.get_group('test_group').group_id = GROUP_ID_LENGTH * b'a' # Test self.assert_fr("Error: Received message to an unknown group.", process_message, self.ts, assembly_ct_list[0], *self.args) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH)
def test_invalid_encoding_in_group_management_message_raises_fr_but_is_logged(self): # Setup message = b'testgroup' + US_BYTE + b'*****@*****.**' + US_BYTE + binascii.unhexlify('a466c02c221cb135') encrypted_packet = assembly_packet_creator(MESSAGE, message, ORIGIN_CONTACT_HEADER, header=GROUP_MSG_INVITEJOIN_HEADER, encrypt=True)[0] self.settings.logfile_masking = True self.contact_list.get_contact('*****@*****.**').log_messages = True # Test self.assertFR("Error: Received group management message had invalid encoding.", process_message, self.ts, encrypted_packet, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), LOG_ENTRY_LENGTH)
def test_long_command(self) -> None: # Setup packet = Packet(LOCAL_ID, ORIGIN_CONTACT_HEADER, COMMAND, self.contact, self.settings) command = 500 * b'test_command' packets = assembly_packet_creator(COMMAND, command) for p in packets: packet.add_packet(p) # Test self.assertEqual(packet.assemble_command_packet(), command) self.assertEqual(packet.log_masking_ctr, 0)
def test_invalid_assembly_packet_header_raises_soft_error(self) -> None: # Setup packet = Packet(self.onion_pub_key, ORIGIN_CONTACT_HEADER, MESSAGE, self.contact, self.settings) a_packet = assembly_packet_creator(MESSAGE, payload=self.short_msg, s_header_override=b'i')[0] # Test self.assert_se( "Error: Received packet had an invalid assembly packet header.", packet.add_packet, a_packet) self.assertEqual(packet.log_masking_ctr, 1)
def test_unauthorized_long_file_raises_soft_error(self) -> None: # Setup self.contact.file_reception = False packet = Packet(self.onion_pub_key, ORIGIN_CONTACT_HEADER, FILE, self.contact, self.settings) packet_list = assembly_packet_creator(FILE) # Test self.assert_se( "Alert! File transmission from Alice but reception is disabled.", packet.add_packet, packet_list[0]) self.assertEqual(packet.log_masking_ctr, 1)
def test_empty_whisper_msg_from_user(self, _): # Setup assembly_ct_list = assembly_packet_creator(MESSAGE, '', origin_header=ORIGIN_USER_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), whisper_header=bool_to_bytes(True)) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message(self.ts, p, *self.args)) for p in assembly_ct_list[-1:]: self.assert_fr("Whisper message complete.", process_message, self.ts, p, *self.args) self.assertEqual(os.path.getsize(self.file_name), len(assembly_ct_list)*LOG_ENTRY_LENGTH)
def test_file(self): # Setup assembly_ct_list = assembly_packet_creator(FILE, origin=ORIGIN_CONTACT_HEADER, encrypt=True) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message(self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key)) for p in assembly_ct_list[-1:]: self.assertFR("File storage complete.", process_message, self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), len(assembly_ct_list)*LOG_ENTRY_LENGTH)
def test_empty_whisper_msg_from_user(self): # Setup assembly_ct_list = assembly_packet_creator(MESSAGE, b' ', ORIGIN_USER_HEADER, encrypt=True, header=WHISPER_MESSAGE_HEADER) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message(self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key)) for p in assembly_ct_list[-1:]: self.assertFR("Key message message complete.", process_message, self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), len(assembly_ct_list)*LOG_ENTRY_LENGTH)
def test_removal_of_contact_logs(self): # Setup short_msg = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit." for p in assembly_packet_creator(MESSAGE, self.msg): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) for p in assembly_packet_creator(MESSAGE, short_msg): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Test self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), 8*LOG_ENTRY_LENGTH) self.assertIsNone(remove_logs('*****@*****.**', self.settings, self.masterkey)) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), 4*LOG_ENTRY_LENGTH) self.assertIsNone(remove_logs('*****@*****.**', self.settings, self.masterkey)) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), 0) self.assertFR(f"Found no log entries for contact '*****@*****.**'", remove_logs, '*****@*****.**', self.settings, self.masterkey)
def test_short_message(self): # Setup packet = Packet(self.onion_pub_key, ORIGIN_USER_HEADER, MESSAGE, self.contact, self.settings) packet_list = assembly_packet_creator(MESSAGE, self.short_msg) for p in packet_list: packet.add_packet(p, packet_ct=b'test_ct') # Test self.assertEqual( packet.assemble_message_packet(), self.whisper_header + PRIVATE_MESSAGE_HEADER + self.short_msg.encode()) self.assertEqual(packet.log_ct_list, [b'test_ct'])
def test_noise_packet_interrupts_file(self): # Setup packet = Packet(self.onion_pub_key, ORIGIN_CONTACT_HEADER, FILE, self.contact, self.settings) packet_list = assembly_packet_creator(FILE)[:20] packet_list.append(byte_padding(P_N_HEADER)) # Add noise packet for p in packet_list: packet.add_packet(p) # Test self.assertEqual(len(packet.assembly_pt_list), 0) # Noise packet empties packet list self.assertFalse(packet.long_active) self.assertFalse(packet.is_complete) self.assertEqual(packet.log_masking_ctr, len(packet_list))
def test_file(self, _): # Setup assembly_ct_list = assembly_packet_creator(FILE, origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice')) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message(self.ts, p, *self.args)) for p in assembly_ct_list[-1:]: self.assert_fr("File storage complete.", process_message, self.ts, p, *self.args) self.assertEqual(os.path.getsize(self.file_name), len(assembly_ct_list)*LOG_ENTRY_LENGTH)
def test_decryption_error_raises_fr(self): # Setup packet = Packet(self.onion_pub_key, ORIGIN_USER_HEADER, MESSAGE, self.contact, self.settings) packet_list = assembly_packet_creator(MESSAGE, self.msg, tamper_ciphertext=True) for p in packet_list: packet.add_packet(p) # Test self.assert_fr("Error: Decryption of message failed.", packet.assemble_message_packet)
def test_compression_error_raises_soft_error(self) -> None: # Setup packet = Packet(self.onion_pub_key, ORIGIN_USER_HEADER, MESSAGE, self.contact, self.settings) packet_list = assembly_packet_creator(MESSAGE, self.short_msg, tamper_compression=True) for p in packet_list: packet.add_packet(p) # Test self.assert_se("Error: Decompression of message failed.", packet.assemble_message_packet)
def test_invalid_message_header_raises_se(self, _: Any) -> None: # Setup assembly_ct_list = assembly_packet_creator( MESSAGE, 'test_message', origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), message_header=b'Z') # Test self.assert_se("Error: Message from contact had an invalid header.", process_message_packet, self.ts, assembly_ct_list[0], *self.args)
def test_display_short_private_message(self, _): # Setup # Add a message from user (Bob) to different contact (Charlie). access_logs should not display this message. for p in assembly_packet_creator(MESSAGE, 'Hi Charlie'): write_log_entry(p, nick_to_pub_key('Charlie'), self.settings, self.master_key) # 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.assert_prints((CLEAR_ENTIRE_SCREEN + CURSOR_LEFT_UP_CORNER + f"""\ Log file of message(s) sent to contact Alice ════════════════════════════════════════════════════════════════════════════════ {self.time} Alice: Hi Bob {self.time} Me: Hi Alice <End of log file> """), access_logs, *self.args)
def test_private_msg_from_contact(self, _): # Setup assembly_ct_list = assembly_packet_creator( MESSAGE, self.msg, origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice')) # Test for p in assembly_ct_list: self.assertIsNone(process_message(self.ts, p, *self.args)) self.assertEqual(os.path.getsize(self.file_name), len(assembly_ct_list) * LOG_ENTRY_LENGTH)
def test_long_command_compression_error_raises_fr(self): # Setup packet = Packet(LOCAL_ID, ORIGIN_CONTACT_HEADER, COMMAND, self.contact, self.settings) packet_list = assembly_packet_creator(COMMAND, os.urandom(500), tamper_compression=True) for p in packet_list: packet.add_packet(p) # Test self.assert_fr("Error: Decompression of command failed.", packet.assemble_command_packet) self.assertEqual(packet.log_masking_ctr, 0)
def test_long_command_hash_mismatch_raises_fr(self): # Setup packet = Packet(LOCAL_ID, ORIGIN_CONTACT_HEADER, COMMAND, self.contact, self.settings) packet_list = assembly_packet_creator(COMMAND, os.urandom(500), tamper_cmd_hash=True) for p in packet_list: packet.add_packet(p) # Test self.assert_fr("Error: Received an invalid command.", packet.assemble_command_packet) self.assertEqual(packet.log_masking_ctr, 0)
def test_removal_of_group_logs(self): # Setup short_msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." # Add long message from user (Bob) to Alice and Charlie. These should be removed. for p in assembly_packet_creator(MESSAGE, self.msg, group_id=group_name_to_group_id('test_group')): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key) write_log_entry(p, nick_to_pub_key('Charlie'), self.settings, self.master_key) # Add short message from user (Bob) to Alice and Charlie. These should be removed. for p in assembly_packet_creator(MESSAGE, short_msg, group_id=group_name_to_group_id('test_group')): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key) write_log_entry(p, nick_to_pub_key('Charlie'), self.settings, self.master_key) # Add short message from user (Bob) to David. This should be kept. for p in assembly_packet_creator(MESSAGE, short_msg): write_log_entry(p, nick_to_pub_key('David'), self.settings, self.master_key) # Add long message from user (Bob) to David. These should be kept. for p in assembly_packet_creator(MESSAGE, self.msg): write_log_entry(p, nick_to_pub_key('David'), self.settings, self.master_key) # Add short message from user (Bob) to David in a group. This should be kept as group is different. for p in assembly_packet_creator(MESSAGE, short_msg, group_id=group_name_to_group_id('different_group')): write_log_entry(p, nick_to_pub_key('David'), self.settings, self.master_key) # Add an orphaned 'append' assembly packet. This should be removed as it's corrupted. write_log_entry(M_A_HEADER + bytes(PADDING_LENGTH), nick_to_pub_key('Alice'), self.settings, self.master_key) # Add long message to group member David, canceled half-way. This should be removed as unviewable. packets = assembly_packet_creator(MESSAGE, self.msg, group_id=group_name_to_group_id('test_group')) packets = packets[2:] + [M_C_HEADER + bytes(PADDING_LENGTH)] for p in packets: write_log_entry(p, nick_to_pub_key('David'), self.settings, self.master_key) # Add long message to group member David, remove_logs should keep these as group is different. for p in assembly_packet_creator(MESSAGE, self.msg, group_id=group_name_to_group_id('different_group')): write_log_entry(p, nick_to_pub_key('David'), self.settings, self.master_key) # Test self.assertEqual(os.path.getsize(self.file_name), 19 * LOG_ENTRY_LENGTH) # Test log entries were found. self.assert_fr("Removed log entries for group 'test_group'.", remove_logs, *self.args, selector=group_name_to_group_id('test_group')) self.assertEqual(os.path.getsize(self.file_name), 8 * LOG_ENTRY_LENGTH) # Test log entries were not found when removing group again. self.assert_fr("Found no log entries for group 'test_group'.", remove_logs, *self.args, selector=group_name_to_group_id('test_group')) self.assertEqual(os.path.getsize(self.file_name), 8 * LOG_ENTRY_LENGTH)
def test_group_invitation_msg_from_user(self): # Setup assembly_ct_list = assembly_packet_creator(MESSAGE, self.message, ORIGIN_USER_HEADER, header=GROUP_MSG_INVITEJOIN_HEADER, encrypt=True) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message(self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key)) for p in assembly_ct_list[-1:]: self.assertFR("Ignored group management message from user.", process_message, self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), len(assembly_ct_list)*LOG_ENTRY_LENGTH)
def test_normal_group_msg_from_user(self, _): # Setup assembly_ct_list = assembly_packet_creator( MESSAGE, self.msg, origin_header=ORIGIN_USER_HEADER, group_id=self.group_id, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice')) for p in assembly_ct_list: self.assertIsNone(process_message(self.ts, p, *self.args)) self.assertEqual(os.path.getsize(self.file_name), len(assembly_ct_list) * LOG_ENTRY_LENGTH)
def test_group_exit_msg_from_contact(self): # Setup assembly_ct_list = assembly_packet_creator(MESSAGE, b'testgroup', ORIGIN_CONTACT_HEADER, header=GROUP_MSG_EXIT_GROUP_HEADER, encrypt=True) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message(self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key)) for p in assembly_ct_list[-1:]: self.assertFR("Group management message complete.", process_message, self.ts, p, self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list, self.settings, self.master_key) self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), len(assembly_ct_list)*LOG_ENTRY_LENGTH)
def test_file_when_reception_is_disabled(self, _: Any) -> None: # Setup assembly_ct_list = assembly_packet_creator( FILE, origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice')) self.contact_list.get_contact_by_pub_key( nick_to_pub_key('Alice')).file_reception = False # Test self.assert_se( "Alert! File transmission from Alice but reception is disabled.", process_message_packet, self.ts, assembly_ct_list[0], *self.args)
def test_disabled_file_reception_raises_fr_with_end_packet(self): # Setup packet = Packet(self.onion_pub_key, ORIGIN_CONTACT_HEADER, FILE, self.contact, self.settings) packet.long_active = True packet_list = assembly_packet_creator(FILE) for p in packet_list[:-1]: self.assertIsNone(packet.add_packet(p)) packet.contact.file_reception = False # Test for p in packet_list[-1:]: self.assert_fr("Alert! File reception disabled mid-transfer.", packet.add_packet, p) self.assertEqual(packet.log_masking_ctr, len(packet_list))
def test_file(self, _: Any) -> None: # Setup assembly_ct_list = assembly_packet_creator( FILE, origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice')) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message_packet(self.ts, p, *self.args)) for p in assembly_ct_list[-1:]: self.assert_se("File storage complete.", process_message_packet, self.ts, p, *self.args)
def test_contact_not_in_group_raises_se(self, _: Any) -> None: # Setup assembly_ct_list = assembly_packet_creator( MESSAGE, 'test_message', origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, group_id=self.group_id, onion_pub_key=nick_to_pub_key('Charlie')) # Test self.assert_se("Error: Account is not a member of the group.", process_message_packet, self.ts, assembly_ct_list[0], *self.args)
def test_invalid_message_raises_se(self, _: Any) -> None: # Setup assembly_ct_list = assembly_packet_creator( MESSAGE, ' ', origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), group_id=self.group_id, tamper_plaintext=True) # Test self.assert_se("Error: Received an invalid group message.", process_message_packet, self.ts, assembly_ct_list[0], *self.args)
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_empty_whisper_msg_from_user(self, _: Any) -> None: # Setup assembly_ct_list = assembly_packet_creator( MESSAGE, '', origin_header=ORIGIN_USER_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), whisper_header=bool_to_bytes(True)) # Test for p in assembly_ct_list[:-1]: self.assertIsNone(process_message_packet(self.ts, p, *self.args)) for p in assembly_ct_list[-1:]: self.assert_se("Whisper message complete.", process_message_packet, self.ts, p, *self.args)