def test_disabled_file_reception_raises_fr(self): # Setup file_ct = encrypt_and_sign(self.compressed, self.file_key) packet = nick_to_pub_key('Alice') + ORIGIN_CONTACT_HEADER + file_ct self.contact_list.get_contact_by_address_or_nick( 'Alice').file_reception = False # Test self.assert_fr( "Alert! Discarded file from Alice as file reception for them is disabled.", new_file, self.ts, packet, *self.args)
def test_contact_window_change_during_traffic_masking_raises_fr(self): # Setup self.settings.traffic_masking = True self.window.uid = nick_to_pub_key("Alice") # Test self.assert_fr("Error: Can't change window during traffic masking.", self.window.select_tx_window, *self.args, selection=nick_to_onion_address("Bob"), cmd=True)
def setUp(self): self.contact_list = ContactList(nicks=['Alice', 'Bob']) self.settings = Settings() self.onion_pub_key = nick_to_pub_key('Alice') packet = Packet( self.onion_pub_key, ORIGIN_CONTACT_HEADER, MESSAGE, self.contact_list.get_contact_by_address_or_nick('Alice'), self.settings) self.packet_list = PacketList(self.settings, self.contact_list) self.packet_list.packets = [packet]
def test_decryption_with_zero_rx_hek_raises_fr(self): # Setup keyset = self.key_list.get_keyset(nick_to_pub_key("Alice")) keyset.rx_hk = bytes(SYMMETRIC_KEY_LENGTH) packet = assembly_packet_creator(MESSAGE, payload="Test message", encrypt_packet=True)[0] # Test self.assert_fr("Warning! Loaded zero-key for packet decryption.", decrypt_assembly_packet, packet, *self.args)
def setUp(self) -> None: """Pre-test actions.""" self.unit_test_dir = cd_unit_test() self.ts = datetime.now() self.account = nick_to_pub_key('Alice') self.file_key = SYMMETRIC_KEY_LENGTH * b'a' self.file_ct = encrypt_and_sign(50 * b'a', key=self.file_key) self.contact_list = ContactList(nicks=['Alice']) self.window_list = WindowList() self.settings = Settings() self.args = self.file_key, self.contact_list, self.window_list, self.settings
def setUp(self): self.window = TxWindow(uid=nick_to_pub_key("Alice"), name='Alice', window_contacts=[create_contact('test_group')], log_messages=True, type=WIN_TYPE_CONTACT) self.contact_list = ContactList(nicks=['Alice']) self.contact = self.contact_list.get_contact_by_address_or_nick( 'Alice') self.window.contact = self.contact self.args = self.window, self.contact_list
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_too_large_final_member_list_raises_soft_error(self) -> None: # Setup group_list = GroupList(groups=['test_group']) contact_list = ContactList(nicks=[str(n) for n in range(51)]) group = group_list.get_group('test_group') group.members = contact_list.contacts[:50] cmd_data = group_name_to_group_id('test_group') + nick_to_pub_key('50') # Test self.assert_se("Error: TFC settings only allow 50 members per group.", group_add, cmd_data, self.ts, self.window_list, contact_list, group_list, self.settings)
def test_full_group_list_raises_soft_error(self) -> None: # Setup self.group_list = GroupList( groups=[f"testgroup_{n}" for n in range(50)]) # Test self.assert_se("Error: TFC settings only allow 50 groups.", group_create, 'testgroup_50', [nick_to_pub_key("Alice")], self.contact_list, self.group_list, self.settings, self.queues, self.master_key)
def setUp(self, _): """Pre-test actions.""" self.unit_test_dir = cd_unit_test() self.window = TxWindow(name='Alice', uid=nick_to_pub_key('Alice')) self.contact_list = ContactList() self.group_list = GroupList() self.settings = Settings() self.queues = gen_queue_dict() self.master_key = MasterKey() self.args = (self.window, self.contact_list, self.group_list, self.settings, self.queues, self.master_key)
def test_unknown_group_id_raises_se(self) -> None: # Setup group_list = GroupList(groups=['test_group']) contact_list = ContactList(nicks=[str(n) for n in range(21)]) cmd_data = group_name_to_group_id('test_group2') + nick_to_pub_key( '20') # Test self.assert_se("Error: No group with ID '2e7mHQznTMsP6' found.", group_remove, cmd_data, self.ts, self.window_list, contact_list, group_list)
def test_full_group_list_raises_se(self) -> None: # Setup cmd_data = self.group_id + b'test_group' + US_BYTE + nick_to_pub_key( '51') group_list = GroupList(groups=[f"test_group_{n}" for n in range(50)]) contact_list = ContactList(nicks=['Alice']) # Test self.assert_se("Error: TFC settings only allow 50 groups.", group_create, cmd_data, self.ts, self.window_list, contact_list, group_list, self.settings)
def test_local_key_installed_existing_contact(self, _): # Setup self.window_list = WindowList(nicks=[LOCAL_ID, 'Alice']) self.contact_list = ContactList(nicks=[LOCAL_ID, 'Alice']) self.window_list.active_win = self.window_list.get_window( nick_to_pub_key('Alice')) self.window_list.active_win.type = WIN_TYPE_CONTACT # Test self.assertIsNone( local_key_rdy(self.ts, self.window_list, self.contact_list))
def test_add_psk_tx_keys(self, _): self.assertIsNone(key_ex_psk_tx(*self.args)) keyset = self.key_list.get_keyset(nick_to_pub_key("Alice")) self.assertIsInstance(keyset, KeySet) self.assertEqual(keyset.onion_pub_key, nick_to_pub_key("Alice")) self.assertEqual(keyset.tx_mk, SYMMETRIC_KEY_LENGTH * b'\x01') self.assertEqual(keyset.rx_mk, bytes(SYMMETRIC_KEY_LENGTH)) self.assertEqual(keyset.tx_hk, SYMMETRIC_KEY_LENGTH * b'\x02') self.assertEqual(keyset.rx_hk, bytes(SYMMETRIC_KEY_LENGTH)) contact = self.contact_list.get_contact_by_pub_key( nick_to_pub_key("Alice")) self.assertIsInstance(contact, Contact) self.assertEqual(contact.onion_pub_key, nick_to_pub_key("Alice")) self.assertEqual(contact.nick, 'Alice') self.assertEqual(contact.tx_fingerprint, bytes(FINGERPRINT_LENGTH)) self.assertEqual(contact.rx_fingerprint, bytes(FINGERPRINT_LENGTH))
class TestInputLoop(unittest.TestCase): conf_code = blake2b(nick_to_pub_key('Alice'), digest_size=CONFIRM_CODE_LENGTH).hex() input_list = [ '61', # Enter Relay confirmation code '61', # Enter Receiver confirmation code nick_to_onion_address("Alice"), # Enter rx-account for new contact 'Alice', # Enter nick for contact '', # Enter to default for ECDHE VALID_ECDHE_PUB_KEY, # Enter public key for contact 'Yes', # Accept key fingerprints for Alice conf_code, # Confirmation code 'Alice', # Select Alice as the recipient 'Test', # Send test message '/file', # Open file selection prompt '', # Give empty string to abort '/exit' ] # Enter exit command def setUp(self) -> None: """Pre-test actions.""" self.settings = Settings(disable_gui_dialog=True) self.gateway = Gateway() self.contact_list = ContactList() self.group_list = GroupList() self.master_key = MasterKey() self.onion_service = OnionService() self.queues = gen_queue_dict() def tearDown(self) -> None: """Post-test actions.""" tear_queues(self.queues) @mock.patch('builtins.input', side_effect=input_list) @mock.patch('os.fdopen', MagicMock()) @mock.patch('os.getrandom', lambda n, flags: n * b'a') @mock.patch('os.urandom', lambda n: n * b'a') @mock.patch('shutil.get_terminal_size', return_value=[200, 200]) @mock.patch('src.transmitter.commands.exit_tfc', side_effect=SystemExit) @mock.patch('sys.stdin', MagicMock()) @mock.patch('time.sleep', return_value=None) @mock.patch('os.system', return_value=None) def test_input_loop_functions(self, *_: Any) -> None: with self.assertRaises(SystemExit): self.assertIsNone( input_loop(self.queues, self.settings, self.gateway, self.contact_list, self.group_list, self.master_key, self.onion_service, stdin_fd=1))
def setUp(self) -> None: """Pre-test actions.""" self.unit_test_dir = cd_unit_test() self.packet = b'\x00' + nick_to_pub_key("Alice") self.ts = datetime.now() self.window_list = WindowList(nicks=['Alice', LOCAL_ID]) self.contact_list = ContactList(nicks=['Alice', LOCAL_ID]) self.key_list = KeyList(nicks=['Alice', LOCAL_ID]) self.settings = Settings(disable_gui_dialog=True) self.file_name = self.file_name self.args = self.packet, self.ts, self.window_list, self.contact_list, self.key_list, self.settings
def test_keyboard_interrupt_raises_soft_error(self, *_: Any) -> None: # Setup contact = create_contact('Alice', kex_status=KEX_STATUS_NO_RX_PSK) contact_list = ContactList(contacts=[contact]) window = TxWindow(type=WIN_TYPE_CONTACT, uid=nick_to_pub_key("Alice"), contact=contact) # Test self.assert_se("PSK install verification aborted.", rxp_load_psk, window, contact_list, *self.args)
def test_ecdhe_key_raises_soft_error(self) -> None: # Setup contact = create_contact('Alice') contact_list = ContactList(contacts=[contact]) window = TxWindow(type=WIN_TYPE_CONTACT, uid=nick_to_pub_key("Alice"), contact=contact) # Test self.assert_se(f"Error: The current key was exchanged with {ECDHE}.", rxp_load_psk, window, contact_list, *self.args)
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 setUp(self): self.ts = datetime.fromtimestamp(1502750000) self.window_list = WindowList(nicks=[LOCAL_ID]) self.contact_list = ContactList() self.key_list = KeyList() self.settings = Settings() self.packet = (nick_to_pub_key("Alice") + SYMMETRIC_KEY_LENGTH * b'\x01' + bytes(SYMMETRIC_KEY_LENGTH) + SYMMETRIC_KEY_LENGTH * b'\x02' + bytes(SYMMETRIC_KEY_LENGTH) + str_to_bytes('Alice')) self.args = self.packet, self.ts, self.window_list, self.contact_list, self.key_list, self.settings
def test_invalid_file_key_data_raises_se(self, _: Any) -> None: assembly_ct_list = assembly_packet_creator( MESSAGE, ' ', origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), message_header=FILE_KEY_HEADER) for p in assembly_ct_list[-1:]: self.assert_se("Error: Received an invalid file key message.", process_message_packet, self.ts, p, *self.args)
def test_user_origin_raises_se(self, _: Any) -> None: assembly_ct_list = assembly_packet_creator( MESSAGE, ' ', origin_header=ORIGIN_USER_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), message_header=FILE_KEY_HEADER) for p in assembly_ct_list[-1:]: self.assert_se("File key message from the user.", process_message_packet, self.ts, p, *self.args)
def test_private_msg_from_contact(self, _: Any) -> None: # 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_packet(self.ts, p, *self.args))
def test_file_when_reception_is_disabled(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')) self.contact_list.get_contact_by_pub_key(nick_to_pub_key('Alice')).file_reception = False # Test self.assert_fr("Alert! File transmission from Alice but reception is disabled.", process_message, self.ts, assembly_ct_list[0], *self.args) self.assertEqual(os.path.getsize(self.file_name), LOG_ENTRY_LENGTH)
def test_print_to_inactive_window_preview_on_long_message(self, _): # Setup window = self.create_window(nick_to_pub_key("Alice")) window.is_active = False window.handle_dict = {nick_to_pub_key("Alice"): 'Alice'} window.settings = Settings(new_message_notify_preview=True) long_message = ( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque consequat libero et lao" "reet egestas. Aliquam a arcu malesuada, elementum metus eget, elementum mi. Vestibulum i" "d arcu sem. Ut sodales odio sed viverra mollis. Praesent gravida ante tellus, pellentesq" "ue venenatis massa placerat quis. Nullam in magna porta, hendrerit sem vel, dictum ipsum" ". Ut sagittis, ipsum ut bibendum ornare, ex lorem congue metus, vel posuere metus nulla " "at augue.") msg_tuple = (self.ts, long_message, nick_to_pub_key("Bob"), ORIGIN_USER_HEADER, False, False) # Test self.assert_prints( f"{BOLD_ON}{self.time} Me (private message): {NORMAL_TEXT}Lorem ipsum dolor sit " f"amet, consectetu…\n{CURSOR_UP_ONE_LINE}{CLEAR_ENTIRE_LINE}", window.print, msg_tuple)
def test_valid_file_key_message(self, _: Any) -> None: assembly_ct_list = assembly_packet_creator( MESSAGE, base64.b85encode(BLAKE2_DIGEST_LENGTH * b'a' + SYMMETRIC_KEY_LENGTH * b'b').decode(), origin_header=ORIGIN_CONTACT_HEADER, encrypt_packet=True, onion_pub_key=nick_to_pub_key('Alice'), message_header=FILE_KEY_HEADER) for p in assembly_ct_list[-1:]: self.assert_se("Received file decryption key from Alice", process_message_packet, self.ts, p, *self.args)
def test_redraw_empty_window(self): # Setup window = self.create_window(nick_to_pub_key("Alice")) window.is_active = True window.message_log = [] # Test self.assert_prints( f"""\ {CLEAR_ENTIRE_SCREEN}{CURSOR_LEFT_UP_CORNER} {BOLD_ON} This window for Alice is currently empty. {NORMAL_TEXT}\n """, window.redraw)
def test_normal_group_msg_from_user(self, _: Any) -> None: # 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_packet(self.ts, p, *self.args))
def test_too_many_purp_accounts_raises_soft_error(self) -> None: # Setup create_list = [nick_to_pub_key(str(n)) for n in range(51)] cmd_data = self.group_id + b'test_group' + US_BYTE + b''.join(create_list) group_list = GroupList(groups=['test_group']) contact_list = ContactList(nicks=[str(n) for n in range(51)]) group = group_list.get_group('test_group') group.members = contact_list.contacts # Test self.assert_se("Error: TFC settings only allow 50 members per group.", group_create, cmd_data, self.ts, self.window_list, contact_list, group_list, self.settings)
def create_keyset(nick: str, tx_key: bytes = SYMMETRIC_KEY_LENGTH * b'\x01', tx_hek: bytes = SYMMETRIC_KEY_LENGTH * b'\x01', rx_key: bytes = SYMMETRIC_KEY_LENGTH * b'\x01', rx_hek: bytes = SYMMETRIC_KEY_LENGTH * b'\x01', tx_harac: int = INITIAL_HARAC, rx_harac: int = INITIAL_HARAC, store_f: Callable[..., None] = None) -> KeySet: """Create a mock keyset object.""" pub_key = LOCAL_PUBKEY if nick == LOCAL_ID else nick_to_pub_key(nick) return KeySet(pub_key, tx_key, tx_hek, rx_key, rx_hek, tx_harac, rx_harac, store_keys=lambda: None if store_f is None else store_f)