示例#1
0
    def test_invalid_group_message_header(self):
        # Setup
        message = b'testgroup'
        ts = datetime.datetime.now()
        apct_list = self.create_message_apct(ORIGIN_CONTACT_HEADER,
                                             message,
                                             header=GROUP_MESSAGE_HEADER)
        contact_list = ContactList(nicks=['Alice', 'Bob', 'local'])
        key_list = KeyList(nicks=['Alice', 'Bob', 'local'])
        keyset = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac = 1
        keyset.rx_key = 32 * b'\x01'
        keyset.rx_hek = 32 * b'\x01'
        group_list = GroupList(groups=['testgroup'])
        settings = Settings()
        packet_list = PacketList(contact_list=contact_list, settings=settings)
        window_list = WindowList(contact_list=contact_list,
                                 group_list=group_list,
                                 packet_list=packet_list,
                                 settings=settings)
        master_key = MasterKey()

        # Test
        for p in apct_list:
            self.assertFR("Received an invalid group message.",
                          process_message, ts, p, window_list, packet_list,
                          contact_list, key_list, group_list, settings,
                          master_key)
示例#2
0
    def test_valid_psk(self):
        # Setup
        packet          = b'*****@*****.**'
        contact_list    = ContactList(nicks=['Alice', 'local'])
        key_list        = KeyList(nicks=['Alice', 'local'])
        keyset          = key_list.get_keyset('*****@*****.**')
        keyset.rx_key   = bytes(32)
        keyset.rx_hek   = bytes(32)
        window_list     = WindowList(nicks=['Alice', 'local'])
        ts              = datetime.datetime.now()
        settings        = Settings(disable_gui_dialog=True)
        o_input         = builtins.input
        o_getpass       = getpass.getpass
        builtins.input  = lambda x: 'ut_psk'
        getpass.getpass = lambda x: 'testpassword'
        password        = '******'
        salt            = os.urandom(32)
        rx_key          = os.urandom(32)
        rx_hek          = os.urandom(32)
        kek, _          = argon2_kdf(password, salt, rounds=16, memory=128000, parallelism=1)
        ct_tag          = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open('ut_psk', 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assertTrue(os.path.isfile('ut_psk'))
        self.assertIsNone(psk_import(packet, ts, window_list, contact_list, key_list, settings))
        self.assertFalse(os.path.isfile('ut_psk'))
        self.assertEqual(keyset.rx_key, rx_key)
        self.assertEqual(keyset.rx_hek, rx_hek)

        # Teardown
        builtins.input  = o_input
        getpass.getpass = o_getpass
示例#3
0
    def test_invalid_window_raises_fr(self):
        # Setup
        message = b'testgroup'
        ts = datetime.datetime.now()
        timestamp = double_to_bytes(time.time() * 1000)
        header = GROUP_MESSAGE_HEADER + timestamp + b'test_group' + US_BYTE
        apct_list = self.create_message_apct(ORIGIN_CONTACT_HEADER,
                                             message,
                                             header=header)
        contact_list = ContactList(nicks=['Alice', 'Bob', 'local'])
        key_list = KeyList(nicks=['Alice', 'Bob', 'local'])
        keyset = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac = 1
        keyset.rx_key = 32 * b'\x01'
        keyset.rx_hek = 32 * b'\x01'
        group_list = GroupList(groups=['testgroup'])
        settings = Settings()
        packet_list = PacketList(contact_list=contact_list, settings=settings)
        window_list = WindowList(contact_list=contact_list,
                                 group_list=group_list,
                                 packet_list=packet_list,
                                 settings=settings)
        master_key = MasterKey()

        # Test
        for p in apct_list:
            self.assertFR("Received message to unknown group.",
                          process_message, ts, p, window_list, packet_list,
                          contact_list, key_list, group_list, settings,
                          master_key)

        # Teardown
        cleanup()
示例#4
0
    def test_function(self):
        # Setup
        packet       = 32 * b'\x01' + 32 * b'\x02' + b'*****@*****.**' + US_BYTE + b'Alice'
        ts           = datetime.datetime.now()
        window_list  = WindowList(nicks=['local'])
        settings     = Settings()
        pubkey_buf   = dict()
        contact_list = ContactList()
        key_list     = KeyList()

        # Test
        self.assertIsNone(psk_command(packet, ts, window_list, contact_list, key_list, settings, pubkey_buf))

        keyset = key_list.get_keyset('*****@*****.**')
        self.assertIsInstance(keyset, KeySet)
        self.assertEqual(keyset.rx_account, '*****@*****.**')
        self.assertEqual(keyset.tx_key, 32 * b'\x01')
        self.assertEqual(keyset.tx_hek, 32 * b'\x02')
        self.assertEqual(keyset.rx_key, bytes(32))
        self.assertEqual(keyset.rx_hek, bytes(32))

        contact = contact_list.get_contact('*****@*****.**')
        self.assertIsInstance(contact, Contact)

        self.assertEqual(contact.rx_account, '*****@*****.**')
        self.assertEqual(contact.nick, 'Alice')
        self.assertEqual(contact.rx_fingerprint, bytes(32))
        self.assertEqual(contact.tx_fingerprint, bytes(32))
示例#5
0
    def test_group_msg(self):
        # Setup
        ts = datetime.datetime.now()
        apct_list = self.create_message_apct(ORIGIN_CONTACT_HEADER,
                                             b'testmessage',
                                             group_name=b'testgroup')
        contact_list = ContactList(nicks=['Alice', 'Bob', 'local'])
        key_list = KeyList(nicks=['Alice', 'Bob', 'local'])
        keyset = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac = 1
        keyset.rx_key = 32 * b'\x01'
        keyset.rx_hek = 32 * b'\x01'
        group_list = GroupList(groups=['testgroup'])
        group = group_list.get_group('testgroup')
        group.log_messages = True
        settings = Settings()
        packet_list = PacketList(contact_list=contact_list, settings=settings)
        window_list = WindowList(contact_list=contact_list,
                                 group_list=group_list,
                                 packet_list=packet_list,
                                 settings=settings)
        master_key = MasterKey()

        # Test
        for p in apct_list:
            self.assertIsNone(
                process_message(ts, p, window_list, packet_list, contact_list,
                                key_list, group_list, settings, master_key))

        # Teardown
        cleanup()
示例#6
0
class TestAddPSKTxKeys(unittest.TestCase):

    def setUp(self):
        self.ts           = datetime.datetime.now()
        self.window_list  = WindowList(nicks=[LOCAL_ID])
        self.contact_list = ContactList()
        self.key_list     = KeyList()
        self.settings     = Settings()
        self.pubkey_buf   = {'*****@*****.**' : KEY_LENGTH*b'a'}
        self.packet       = KEY_LENGTH * b'\x01' + KEY_LENGTH * b'\x02' + b'*****@*****.**' + US_BYTE + b'Alice'

    def test_add_psk_tx_keys(self):
        self.assertIsNone(add_psk_tx_keys(self.packet, self.ts, self.window_list, self.contact_list,
                                          self.key_list, self.settings, self.pubkey_buf))

        keyset = self.key_list.get_keyset('*****@*****.**')
        self.assertIsInstance(keyset, KeySet)
        self.assertEqual(keyset.rx_account, '*****@*****.**')
        self.assertEqual(keyset.tx_key, KEY_LENGTH * b'\x01')
        self.assertEqual(keyset.tx_hek, KEY_LENGTH * b'\x02')
        self.assertEqual(keyset.rx_key, bytes(KEY_LENGTH))
        self.assertEqual(keyset.rx_hek, bytes(KEY_LENGTH))

        contact = self.contact_list.get_contact('*****@*****.**')
        self.assertIsInstance(contact, Contact)

        self.assertEqual(contact.rx_account, '*****@*****.**')
        self.assertEqual(contact.nick, 'Alice')
        self.assertEqual(contact.rx_fingerprint, bytes(FINGERPRINT_LEN))
        self.assertEqual(contact.tx_fingerprint, bytes(FINGERPRINT_LEN))

        self.assertFalse('*****@*****.**' in self.pubkey_buf)
示例#7
0
    def test_file(self):
        # Setup
        ts = datetime.datetime.now()
        apct_list = self.create_file_apct()
        contact_list = ContactList(nicks=['Alice', 'Bob', 'local'])
        key_list = KeyList(nicks=['Alice', 'Bob', 'local'])
        keyset = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac = 1
        keyset.rx_key = 32 * b'\x01'
        keyset.rx_hek = 32 * b'\x01'
        group_list = GroupList(groups=['testgroup'])
        settings = Settings()
        packet_list = PacketList(contact_list=contact_list, settings=settings)
        window_list = WindowList(contact_list=contact_list,
                                 group_list=group_list,
                                 packet_list=packet_list,
                                 settings=settings)
        master_key = MasterKey()

        # Test
        for p in apct_list:
            self.assertIsNone(
                process_message(ts, p, window_list, packet_list, contact_list,
                                key_list, group_list, settings, master_key))

        # Teardown
        shutil.rmtree('received_files/')
示例#8
0
    def test_group_remove_member_msg(self):
        # Setup
        message = b'testgroup' + US_BYTE + b'*****@*****.**' + US_BYTE + b'*****@*****.**'
        ts = datetime.datetime.now()
        apct_list = self.create_message_apct(ORIGIN_CONTACT_HEADER,
                                             message,
                                             header=GROUP_MSG_MEMBER_RM_HEADER)
        contact_list = ContactList(nicks=['Alice', 'Bob', 'local'])
        key_list = KeyList(nicks=['Alice', 'Bob', 'local'])
        keyset = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac = 1
        keyset.rx_key = 32 * b'\x01'
        keyset.rx_hek = 32 * b'\x01'
        group_list = GroupList(groups=['testgroup'])
        settings = Settings()
        packet_list = PacketList(contact_list=contact_list, settings=settings)
        window_list = WindowList(contact_list=contact_list,
                                 group_list=group_list,
                                 packet_list=packet_list,
                                 settings=settings)
        master_key = MasterKey()

        # Test
        for p in apct_list:
            self.assertIsNone(
                process_message(ts, p, window_list, packet_list, contact_list,
                                key_list, group_list, settings, master_key))

        # Teardown
        cleanup()
示例#9
0
class TestProcessCommand(TFCTestCase):

    def setUp(self):
        self.unittest_dir = cd_unittest()
        self.ts           = datetime.now()
        self.settings     = Settings()
        self.master_key   = MasterKey()
        self.group_list   = GroupList()
        self.exit_queue   = Queue()
        self.gateway      = Gateway()
        self.window_list  = WindowList(nicks=[LOCAL_ID])
        self.contact_list = ContactList(nicks=[LOCAL_ID])
        self.packet_list  = PacketList(self.settings, self.contact_list)
        self.key_list     = KeyList(nicks=[LOCAL_ID])
        self.key_set      = self.key_list.get_keyset(LOCAL_PUBKEY)

        self.args = (self.window_list, self.packet_list, self.contact_list, self.key_list, self.group_list,
                     self.settings, self.master_key, self.gateway, self.exit_queue)

    def tearDown(self):
        cleanup(self.unittest_dir)

    def test_incomplete_command_raises_fr(self):
        packet = assembly_packet_creator(COMMAND, b'test_command', s_header_override=C_L_HEADER, encrypt_packet=True)[0]
        self.assert_fr("Incomplete command.", process_command, self.ts, packet, *self.args)

    def test_invalid_command_header(self):
        packet = assembly_packet_creator(COMMAND, b'invalid_header', encrypt_packet=True)[0]
        self.assert_fr("Error: Received an invalid command.", process_command, self.ts, packet, *self.args)

    def test_process_command(self):
        packet = assembly_packet_creator(COMMAND, LOG_REMOVE, encrypt_packet=True)[0]
        self.assert_fr(f"No log database available.", process_command, self.ts, packet, *self.args)
示例#10
0
    def test_missing_rx_psk_raises_fr(self):
        # Setup
        packet        = MESSAGE_PACKET_HEADER + 344 * b'a' + ORIGIN_CONTACT_HEADER + b'*****@*****.**'
        window_list   = WindowList(nicks=['Alice', 'local'])
        contact_list  = ContactList(nicks=['Alice', 'local'])
        key_list      = KeyList(nicks=['Alice', 'local'])
        keyset        = key_list.get_keyset('*****@*****.**')
        keyset.rx_hek = bytes(32)  # Set to identify missing PSK

        # Test
        self.assertFR("Warning! Received packet from Alice but no PSK exists.", decrypt_assembly_packet, packet, window_list, contact_list, key_list)
示例#11
0
class TestKeyExPSKTx(TFCTestCase):

    def setUp(self):
        """Pre-test actions."""
        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

    @mock.patch('time.sleep', return_value=None)
    def test_invalid_nick_raises_fr(self, _):
        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)
                       + UNDECODABLE_UNICODE)
        self.args   = self.packet, self.ts, self.window_list, self.contact_list, self.key_list, self.settings

        self.assert_fr("Error: Received invalid contact data", key_ex_psk_tx, *self.args)

    @mock.patch('time.sleep', return_value=None)
    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))
示例#12
0
    def test_expired_harac_raises_fr(self):
        # Setup
        encrypted_message = encrypt_and_sign(PRIVATE_MESSAGE_HEADER + byte_padding(b'test'), 32 * b'\x01')
        harac_in_bytes    = int_to_bytes(1)
        encrypted_harac   = encrypt_and_sign(harac_in_bytes, 32 * b'\x01')
        packet            = MESSAGE_PACKET_HEADER + encrypted_harac + encrypted_message + ORIGIN_CONTACT_HEADER + b'*****@*****.**'

        window_list       = WindowList(nicks=['Alice', 'local'])
        contact_list      = ContactList(nicks=['Alice', 'local'])
        key_list          = KeyList(nicks=['Alice', 'local'])
        keyset            = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac   = 3

        # Test
        self.assertFR("Warning! Received packet from Alice had an expired hash ratchet counter.", decrypt_assembly_packet, packet, window_list, contact_list, key_list)
示例#13
0
class TestProcessCommand(TFCTestCase):
    def setUp(self):
        self.ts = datetime.now()
        self.settings = Settings()
        self.master_key = MasterKey()
        self.group_list = GroupList()
        self.exit_queue = Queue()
        self.pubkey_buf = dict()
        self.window_list = WindowList(nicks=[LOCAL_ID])
        self.contact_list = ContactList(nicks=[LOCAL_ID])
        self.packet_list = PacketList(self.settings, self.contact_list)
        self.key_list = KeyList(nicks=[LOCAL_ID])
        self.key_set = self.key_list.get_keyset(LOCAL_ID)
        self.key_set.rx_key = bytes(KEY_LENGTH)
        self.key_set.rx_hek = bytes(KEY_LENGTH)
        self.key_set.tx_harac = 1
        self.key_set.rx_harac = 1

    def create_packet(self, data, header=C_S_HEADER):
        payload = zlib.compress(data, level=COMPRESSION_LEVEL)
        packet = header + byte_padding(payload)
        harac_in_bytes = int_to_bytes(self.key_set.tx_harac)
        encrypted_harac = encrypt_and_sign(harac_in_bytes, self.key_set.tx_hek)
        encrypted_message = encrypt_and_sign(packet, self.key_set.tx_key)

        return COMMAND_PACKET_HEADER + encrypted_harac + encrypted_message

    def test_incomplete_command_raises_fr(self):
        self.assertFR("Incomplete command.", process_command, self.ts,
                      self.create_packet(b'ZZ', header=C_L_HEADER),
                      self.window_list, self.packet_list, self.contact_list,
                      self.key_list, self.group_list, self.settings,
                      self.master_key, self.pubkey_buf, self.exit_queue)

    def test_invalid_command_header(self):
        self.assertFR("Error: Received an invalid command.", process_command,
                      self.ts, self.create_packet(b'ZZ'), self.window_list,
                      self.packet_list, self.contact_list, self.key_list,
                      self.group_list, self.settings, self.master_key,
                      self.pubkey_buf, self.exit_queue)

    def test_process_command(self):
        self.assertFR(f"Error: Could not find log database.",
                      process_command, self.ts,
                      self.create_packet(LOG_REMOVE_HEADER), self.window_list,
                      self.packet_list, self.contact_list, self.key_list,
                      self.group_list, self.settings, self.master_key,
                      self.pubkey_buf, self.exit_queue)
示例#14
0
class TestProcessCommand(TFCTestCase):
    def setUp(self) -> None:
        """Pre-test actions."""
        self.unit_test_dir = cd_unit_test()
        self.ts = datetime.now()
        self.settings = Settings()
        self.master_key = MasterKey()
        self.group_list = GroupList()
        self.exit_queue = Queue()
        self.gateway = Gateway()
        self.window_list = WindowList(nicks=[LOCAL_ID])
        self.contact_list = ContactList(nicks=[LOCAL_ID])
        self.packet_list = PacketList(self.settings, self.contact_list)
        self.key_list = KeyList(nicks=[LOCAL_ID])
        self.key_set = self.key_list.get_keyset(LOCAL_PUBKEY)

        self.args = (self.window_list, self.packet_list, self.contact_list,
                     self.key_list, self.group_list, self.settings,
                     self.master_key, self.gateway, self.exit_queue)

    def tearDown(self) -> None:
        """Post-test actions."""
        cleanup(self.unit_test_dir)
        tear_queue(self.exit_queue)

    def test_incomplete_command_raises_soft_error(self) -> None:
        packet = assembly_packet_creator(COMMAND,
                                         b'test_command',
                                         s_header_override=C_L_HEADER,
                                         encrypt_packet=True)[0]
        self.assert_se("Incomplete command.", process_command, self.ts, packet,
                       *self.args)

    def test_invalid_command_header(self) -> None:
        packet = assembly_packet_creator(COMMAND,
                                         b'invalid_header',
                                         encrypt_packet=True)[0]
        self.assert_se("Error: Received an invalid command.", process_command,
                       self.ts, packet, *self.args)

    def test_process_command(self) -> None:
        packet = assembly_packet_creator(COMMAND,
                                         CLEAR_SCREEN,
                                         encrypt_packet=True)[0]
        self.assert_se(f"Command completed.", process_command, self.ts, packet,
                       *self.args)
示例#15
0
    def test_successful_packet_decryption_with_offset(self):
        # Setup
        message           = PRIVATE_MESSAGE_HEADER + byte_padding(b'test')
        encrypted_message = encrypt_and_sign(message, hash_chain(32 * b'\x01'))
        harac_in_bytes    = int_to_bytes(2)
        encrypted_harac   = encrypt_and_sign(harac_in_bytes, 32 * b'\x01')
        packet            = MESSAGE_PACKET_HEADER + encrypted_harac + encrypted_message + ORIGIN_CONTACT_HEADER + b'*****@*****.**'

        window_list       = WindowList(nicks=['Alice', 'local'])
        contact_list      = ContactList(nicks=['Alice', 'local'])
        key_list          = KeyList(nicks=['Alice', 'local'])
        keyset            = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac   = 1

        # Test
        assembly_pt, account, origin = decrypt_assembly_packet(packet, window_list, contact_list, key_list)

        self.assertEqual(assembly_pt, message)
        self.assertEqual(account, '*****@*****.**')
        self.assertEqual(origin, ORIGIN_CONTACT_HEADER)
示例#16
0
    def test_successful_command_decryption(self):
        # Setup
        command           = byte_padding(b'test')
        encrypted_message = encrypt_and_sign(command, 32 * b'\x01')
        harac_in_bytes    = int_to_bytes(1)
        encrypted_harac   = encrypt_and_sign(harac_in_bytes, 32 * b'\x01')
        packet            = COMMAND_PACKET_HEADER + encrypted_harac + encrypted_message

        window_list       = WindowList(nicks=['Alice', 'local'])
        contact_list      = ContactList(nicks=['Alice', 'local'])
        key_list          = KeyList(nicks=['Alice', 'local'])
        keyset            = key_list.get_keyset('local')
        keyset.tx_harac   = 1

        # Test
        assembly_pt, account, origin = decrypt_assembly_packet(packet, window_list, contact_list, key_list)

        self.assertEqual(assembly_pt, command)
        self.assertEqual(account, 'local')
        self.assertEqual(origin, ORIGIN_USER_HEADER)
示例#17
0
    def test_harac_dos_can_be_interrupted(self):
        # Setup
        encrypted_message = encrypt_and_sign(PRIVATE_MESSAGE_HEADER + byte_padding(b'test'), 32 * b'\x01')
        harac_in_bytes    = int_to_bytes(10000)
        encrypted_harac   = encrypt_and_sign(harac_in_bytes, 32 * b'\x01')
        packet            = MESSAGE_PACKET_HEADER + encrypted_harac + encrypted_message + ORIGIN_CONTACT_HEADER + b'*****@*****.**'
        o_input           = builtins.input
        builtins.input    = lambda x: 'No'

        window_list       = WindowList(nicks=['Alice', 'local'])
        contact_list      = ContactList(nicks=['Alice', 'local'])
        key_list          = KeyList(nicks=['Alice', 'local'])
        keyset            = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac   = 3

        # Test
        self.assertFR("Dropped packet from Alice.", decrypt_assembly_packet, packet, window_list, contact_list, key_list)

        # Teardown
        builtins.input = o_input
示例#18
0
    def test_normal_msg(self):
        # Setup
        message = (
            "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 bibendu"
            "m velit maximus in. Aliquam ac metus risus. Sed cursus ornare luctus. Integer aliquet lectus id ma"
            "ssa blandit imperdiet. Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl. Sed ut el"
            "it iaculis, faucibus lacus eget, sodales magna. Nunc sed commodo arcu. In hac habitasse platea dic"
            "tumst. Integer luctus aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est eget odio r"
            "utrum, vel malesuada lorem rhoncus. Cras finibus in neque eu euismod. Nulla facilisi. Nunc nec ali"
            "quam quam, quis ullamcorper leo. Nunc egestas lectus eget est porttitor, in iaculis felis sceleris"
            "que. In sem elit, fringilla id viverra commodo, sagittis varius purus. Pellentesque rutrum loborti"
            "s neque a facilisis. Mauris id tortor placerat, aliquam dolor ac, venenatis arcu."
            .encode())
        ts = datetime.datetime.now()
        apct_list = self.create_message_apct(ORIGIN_CONTACT_HEADER, message)
        contact_list = ContactList(nicks=['Alice', 'Bob', 'local'])
        key_list = KeyList(nicks=['Alice', 'Bob', 'local'])
        keyset = key_list.get_keyset('*****@*****.**')
        keyset.rx_harac = 1
        keyset.rx_key = 32 * b'\x01'
        keyset.rx_hek = 32 * b'\x01'
        group_list = GroupList(groups=['testgroup'])
        settings = Settings()
        packet_list = PacketList(contact_list=contact_list, settings=settings)
        window_list = WindowList(contact_list=contact_list,
                                 group_list=group_list,
                                 packet_list=packet_list,
                                 settings=settings)
        master_key = MasterKey()

        # Test
        for p in apct_list:
            self.assertIsNone(
                process_message(ts, p, window_list, packet_list, contact_list,
                                key_list, group_list, settings, master_key))

        # Teardown
        cleanup()
示例#19
0
    def test_invalid_keys_raise_fr(self):
        # Setup
        packet          = b'*****@*****.**'
        contact_list    = ContactList(nicks=['Alice', 'local'])
        key_list        = KeyList(nicks=['Alice', 'local'])
        keyset          = key_list.get_keyset('*****@*****.**')
        keyset.rx_key   = bytes(32)
        keyset.rx_hek   = bytes(32)
        window_list     = WindowList(nicks=['Alice', 'local'])
        ts              = datetime.datetime.now()
        settings        = Settings(disable_gui_dialog=True)
        o_input         = builtins.input
        o_getpass       = getpass.getpass
        builtins.input  = lambda x: 'ut_psk'
        input_list      = ['bad', 'testpassword']
        gen             = iter(input_list)

        def mock_input(_):
            return str(next(gen))

        getpass.getpass = mock_input
        password        = '******'
        salt            = os.urandom(32)
        rx_key          = bytes(32)
        rx_hek          = os.urandom(32)
        kek, _          = argon2_kdf(password, salt, rounds=16, memory=128000, parallelism=1)
        ct_tag          = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open('ut_psk', 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assertFR("Keys from contact are not valid.", psk_import, packet, ts, window_list, contact_list, key_list, settings)

        # Teardown
        os.remove('ut_psk')
        builtins.input  = o_input
        getpass.getpass = o_getpass
示例#20
0
class TestImportPSKRxKeys(TFCTestCase):

    class MockPopen(object):
        def __init__(self, cmd, shell):
            self.cmd   = cmd
            self.shell = shell

        def wait(self):
            pass

    def setUp(self):
        self.o_input   = builtins.input
        self.o_getpass = getpass.getpass
        self.o_sp      = subprocess.Popen

        self.packet       = b'*****@*****.**'
        self.ts           = datetime.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)

        builtins.input = lambda _: 'ut_psk'

    def tearDown(self):
        builtins.input   = self.o_input
        getpass.getpass  = self.o_getpass
        subprocess.Popen = self.o_sp

        with ignored(OSError):
            os.remove('ut_psk')

    def test_unknown_account_raises_fr(self):
        self.assertFR("Error: Unknown account '*****@*****.**'",
                      import_psk_rx_keys, b'*****@*****.**', self.ts, self.window_list, self.contact_list, self.key_list, self.settings)

    def test_invalid_psk_data_raises_fr(self):
        # Setup
        with open('ut_psk', 'wb+') as f:
            f.write(os.urandom(135))

        # Test
        self.assertFR("Error: Invalid PSK data in file.",
                      import_psk_rx_keys, self.packet, self.ts, self.window_list, self.contact_list, self.key_list, self.settings)

    def test_invalid_keys_raise_fr(self):
        # Setup
        keyset          = self.key_list.get_keyset('*****@*****.**')
        keyset.rx_key   = bytes(KEY_LENGTH)
        keyset.rx_hek   = bytes(KEY_LENGTH)
        password        = '******'
        input_list      = ['bad', password]
        gen             = iter(input_list)
        getpass.getpass = lambda _: str(next(gen))

        salt    = os.urandom(ARGON2_SALT_LEN)
        rx_key  = bytes(KEY_LENGTH)
        rx_hek  = os.urandom(KEY_LENGTH)
        kek, _  = argon2_kdf(password, salt, parallelism=1)
        ct_tag  = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open('ut_psk', 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assertFR("Error: Received invalid keys from contact.",
                      import_psk_rx_keys, self.packet, self.ts, self.window_list, self.contact_list, self.key_list, self.settings)

    def test_valid_psk(self):
        # Setup
        keyset        = self.key_list.get_keyset('*****@*****.**')
        keyset.rx_key = bytes(KEY_LENGTH)
        keyset.rx_hek = bytes(KEY_LENGTH)

        getpass.getpass = lambda _: 'testpassword'
        password        = '******'
        salt            = os.urandom(ARGON2_SALT_LEN)
        rx_key          = os.urandom(KEY_LENGTH)
        rx_hek          = os.urandom(KEY_LENGTH)
        kek, _          = argon2_kdf(password, salt, parallelism=1)
        ct_tag          = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open('ut_psk', 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assertTrue(os.path.isfile('ut_psk'))
        self.assertIsNone(import_psk_rx_keys(self.packet, self.ts, self.window_list, self.contact_list, self.key_list, self.settings))
        self.assertFalse(os.path.isfile('ut_psk'))
        self.assertEqual(keyset.rx_key, rx_key)
        self.assertEqual(keyset.rx_hek, rx_hek)

    def test_valid_psk_overwrite_failure(self):
        # Setup
        keyset        = self.key_list.get_keyset('*****@*****.**')
        keyset.rx_key = bytes(KEY_LENGTH)
        keyset.rx_hek = bytes(KEY_LENGTH)

        input_list       = ['ut_psk', '']
        gen              = iter(input_list)
        builtins.input   = lambda _: next(gen)
        subprocess.Popen = TestImportPSKRxKeys.MockPopen

        getpass.getpass = lambda _: 'testpassword'
        password        = '******'
        salt            = os.urandom(ARGON2_SALT_LEN)
        rx_key          = os.urandom(KEY_LENGTH)
        rx_hek          = os.urandom(KEY_LENGTH)
        kek, _          = argon2_kdf(password, salt, parallelism=1)
        ct_tag          = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open('ut_psk', 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assertTrue(os.path.isfile('ut_psk'))
        self.assertIsNone(import_psk_rx_keys(self.packet, self.ts, self.window_list, self.contact_list, self.key_list, self.settings))
        self.assertTrue(os.path.isfile('ut_psk'))
        self.assertEqual(keyset.rx_key, rx_key)
        self.assertEqual(keyset.rx_hek, rx_hek)
示例#21
0
class TestKeyExPSKRx(TFCTestCase):

    file_name = f"{nick_to_short_address('User')}.psk - give to {nick_to_short_address('Alice')}"

    def setUp(self):
        self.unittest_dir = cd_unittest()
        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 tearDown(self):
        cleanup(self.unittest_dir)

    def test_unknown_account_raises_fr(self):
        self.assert_fr(
            f"Error: Unknown account '{nick_to_short_address('Bob')}'.",
            key_ex_psk_rx, b'\x00' + nick_to_pub_key("Bob"), self.ts,
            self.window_list, self.contact_list, self.key_list, self.settings)

    @mock.patch('builtins.input', return_value=file_name)
    def test_invalid_psk_data_raises_fr(self, _):
        # Setup
        with open(self.file_name, 'wb+') as f:
            f.write(os.urandom(135))

        # Test
        self.assert_fr("Error: The PSK data in the file was invalid.",
                       key_ex_psk_rx, *self.args)

    @mock.patch('time.sleep', return_value=None)
    @mock.patch('builtins.input', return_value=file_name)
    def test_permission_error_raises_fr(self, *_):
        # Setup
        with open(self.file_name, 'wb+') as f:
            f.write(os.urandom(PSK_FILE_SIZE))

        # Test
        e_raised = False
        try:
            with mock.patch('builtins.open', side_effect=PermissionError):
                key_ex_psk_rx(*self.args)
        except FunctionReturn as inst:
            e_raised = True
            self.assertEqual("Error: No read permission for the PSK file.",
                             inst.message)
        self.assertTrue(e_raised)

    @mock.patch('src.receiver.key_exchanges.ARGON2_ROUNDS', 1)
    @mock.patch('src.receiver.key_exchanges.ARGON2_MIN_MEMORY', 100)
    @mock.patch('getpass.getpass', side_effect=['invalid', 'password'])
    @mock.patch('time.sleep', return_value=None)
    @mock.patch('os.urandom', side_effect=[bytes(XCHACHA20_NONCE_LENGTH)])
    @mock.patch('builtins.input', return_value=file_name)
    def test_invalid_keys_raise_fr(self, *_):
        # Setup
        keyset = self.key_list.get_keyset(nick_to_pub_key("Alice"))
        keyset.rx_mk = bytes(SYMMETRIC_KEY_LENGTH)
        keyset.rx_hk = bytes(SYMMETRIC_KEY_LENGTH)

        salt = bytes(ARGON2_SALT_LENGTH)
        rx_key = bytes(SYMMETRIC_KEY_LENGTH)
        rx_hek = bytes(SYMMETRIC_KEY_LENGTH)
        kek = argon2_kdf('password', salt, rounds=1, memory=100)
        ct_tag = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open(self.file_name, 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assert_fr("Error: Received invalid keys from contact.",
                       key_ex_psk_rx, *self.args)

    @mock.patch('src.receiver.key_exchanges.ARGON2_ROUNDS', 1)
    @mock.patch('src.receiver.key_exchanges.ARGON2_MIN_MEMORY', 100)
    @mock.patch('time.sleep', return_value=None)
    @mock.patch('builtins.input', return_value=file_name)
    @mock.patch('getpass.getpass', return_value='test_password')
    def test_valid_psk(self, *_):
        # Setup
        keyset = self.key_list.get_keyset(nick_to_pub_key("Alice"))
        keyset.rx_mk = bytes(SYMMETRIC_KEY_LENGTH)
        keyset.rx_hk = bytes(SYMMETRIC_KEY_LENGTH)
        salt = os.urandom(ARGON2_SALT_LENGTH)
        rx_key = os.urandom(SYMMETRIC_KEY_LENGTH)
        rx_hek = os.urandom(SYMMETRIC_KEY_LENGTH)
        kek = argon2_kdf('test_password', salt, rounds=1, memory=100)
        ct_tag = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open(self.file_name, 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assertTrue(os.path.isfile(self.file_name))
        self.assertIsNone(key_ex_psk_rx(*self.args))
        self.assertFalse(os.path.isfile(self.file_name))
        self.assertEqual(keyset.rx_mk, rx_key)
        self.assertEqual(keyset.rx_hk, rx_hek)

    @mock.patch('src.receiver.key_exchanges.ARGON2_ROUNDS', 1)
    @mock.patch('src.receiver.key_exchanges.ARGON2_MIN_MEMORY', 100)
    @mock.patch('subprocess.Popen')
    @mock.patch('time.sleep', return_value=None)
    @mock.patch('builtins.input', side_effect=[file_name, ''])
    @mock.patch('getpass.getpass', return_value='test_password')
    def test_valid_psk_overwrite_failure(self, *_):
        # Setup
        keyset = self.key_list.get_keyset(nick_to_pub_key("Alice"))
        keyset.rx_mk = bytes(SYMMETRIC_KEY_LENGTH)
        keyset.rx_hk = bytes(SYMMETRIC_KEY_LENGTH)

        salt = os.urandom(ARGON2_SALT_LENGTH)
        rx_key = os.urandom(SYMMETRIC_KEY_LENGTH)
        rx_hek = os.urandom(SYMMETRIC_KEY_LENGTH)
        kek = argon2_kdf('test_password', salt, rounds=1, memory=100)
        ct_tag = encrypt_and_sign(rx_key + rx_hek, key=kek)

        with open(self.file_name, 'wb+') as f:
            f.write(salt + ct_tag)

        # Test
        self.assertTrue(os.path.isfile(self.file_name))
        self.assertIsNone(key_ex_psk_rx(*self.args))
        self.assertTrue(os.path.isfile(self.file_name))
        self.assertEqual(keyset.rx_mk, rx_key)
        self.assertEqual(keyset.rx_hk, rx_hek)

    @mock.patch('src.receiver.key_exchanges.ARGON2_ROUNDS', 1)
    @mock.patch('src.receiver.key_exchanges.ARGON2_MIN_MEMORY', 100)
    @mock.patch('subprocess.Popen')
    @mock.patch('time.sleep', return_value=None)
    @mock.patch('builtins.input', side_effect=[file_name, ''])
    @mock.patch('getpass.getpass', side_effect=[KeyboardInterrupt])
    def test_valid_psk_keyboard_interrupt_raises_fr(self, *_):
        with open(self.file_name, 'wb+') as f:
            f.write(bytes(PSK_FILE_SIZE))

        self.assert_fr("PSK import aborted.", key_ex_psk_rx, *self.args)
示例#22
0
class TestDecryptAssemblyPacket(TFCTestCase):

    def setUp(self):
        self.onion_pub_key = nick_to_pub_key("Alice")
        self.origin        = ORIGIN_CONTACT_HEADER
        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.keyset        = self.key_list.get_keyset(nick_to_pub_key("Alice"))
        self.args          = self.onion_pub_key, self.origin, self.window_list, self.contact_list, self.key_list

    def test_decryption_with_zero_rx_key_raises_fr(self):
        # Setup
        keyset       = self.key_list.get_keyset(nick_to_pub_key("Alice"))
        keyset.rx_mk = 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 test_invalid_harac_ct_raises_fr(self):
        packet = assembly_packet_creator(MESSAGE, payload="Test message", encrypt_packet=True, tamper_harac=True)[0]
        self.assert_fr("Warning! Received packet from Alice had an invalid hash ratchet MAC.",
                       decrypt_assembly_packet, packet, *self.args)

    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 test_expired_harac_raises_fr(self):
        # Setup
        self.keyset.rx_harac = 1

        # Test
        packet = assembly_packet_creator(MESSAGE, payload="Test message", encrypt_packet=True, harac=0)[0]
        self.assert_fr("Warning! Received packet from Alice had an expired hash ratchet counter.",
                       decrypt_assembly_packet, packet, *self.args)

    @mock.patch('builtins.input', return_value='No')
    def test_harac_dos_can_be_interrupted(self, _):
        packet = assembly_packet_creator(MESSAGE, payload="Test message", encrypt_packet=True, harac=100_001)[0]
        self.assert_fr("Dropped packet from Alice.",
                       decrypt_assembly_packet, packet, *self.args)

    def test_invalid_packet_ct_raises_fr(self):
        packet = assembly_packet_creator(MESSAGE, payload="Test message", encrypt_packet=True, tamper_message=True)[0]
        self.assert_fr("Warning! Received packet from Alice had an invalid MAC.",
                       decrypt_assembly_packet, packet, *self.args)

    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 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])
示例#23
0
class TestProcessMessage(TFCTestCase):

    def setUp(self):
        self.msg = ("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 bibendu"
                    "m velit maximus in. Aliquam ac metus risus. Sed cursus ornare luctus. Integer aliquet lectus id ma"
                    "ssa blandit imperdiet. Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl. Sed ut el"
                    "it iaculis, faucibus lacus eget, sodales magna. Nunc sed commodo arcu. In hac habitasse platea dic"
                    "tumst. Integer luctus aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est eget odio r"
                    "utrum, vel malesuada lorem rhoncus. Cras finibus in neque eu euismod. Nulla facilisi. Nunc nec ali"
                    "quam quam, quis ullamcorper leo. Nunc egestas lectus eget est porttitor, in iaculis felis sceleris"
                    "que. In sem elit, fringilla id viverra commodo, sagittis varius purus. Pellentesque rutrum loborti"
                    "s neque a facilisis. Mauris id tortor placerat, aliquam dolor ac, venenatis arcu.").encode()

        self.ts              = datetime.now()
        self.master_key      = MasterKey()
        self.settings        = Settings(logfile_masking=True)

        self.contact_list    = ContactList(nicks=['Alice', 'Bob', 'Charlie', LOCAL_ID])
        self.key_list        = KeyList(    nicks=['Alice', 'Bob', 'Charlie', LOCAL_ID])
        self.group_list      = GroupList( groups=['testgroup'])
        self.packet_list     = PacketList(contact_list=self.contact_list, settings=self.settings)
        self.window_list     = WindowList(contact_list=self.contact_list, settings=self.settings, group_list=self.group_list, packet_list=self.packet_list)
        self.group_list.get_group('testgroup').log_messages = True
        for account in self.contact_list.get_list_of_accounts():
            keyset          = self.key_list.get_keyset(account)
            keyset.tx_harac = 1
            keyset.rx_harac = 1
            keyset.tx_hek   = KEY_LENGTH * b'\x01'
            keyset.rx_hek   = KEY_LENGTH * b'\x01'
            keyset.tx_key   = KEY_LENGTH * b'\x01'
            keyset.rx_key   = KEY_LENGTH * b'\x01'

        self.message = b'testgroup' + US_BYTE + b'*****@*****.**' + US_BYTE + b'*****@*****.**'

    def tearDown(self):
        cleanup()
        with ignored(FileNotFoundError):
            shutil.rmtree(DIR_RX_FILES)

    # Private messages
    def test_private_msg_from_contact(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.msg, ORIGIN_CONTACT_HEADER, encrypt=True)

        # Test
        for p in assembly_ct_list:
            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))
        self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), len(assembly_ct_list)*LOG_ENTRY_LENGTH)

    def test_private_msg_from_user(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.msg, ORIGIN_USER_HEADER, encrypt=True)

        # Test
        for p in assembly_ct_list:
            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))
        self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), len(assembly_ct_list) * LOG_ENTRY_LENGTH)

    # Whispered messages
    def test_whisper_msg_from_contact(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.msg, ORIGIN_CONTACT_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_whisper_msg_from_user(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.msg, 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_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)

    # Group messages
    def test_invalid_encoding_raises_fr(self):
        encrypted_packet = assembly_packet_creator(MESSAGE, b'test', ORIGIN_CONTACT_HEADER, group_name='testgroup', encrypt=True, break_g_name=True)[0]

        # Test
        self.assertFR("Error: Received an invalid group message.",
                      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_invalid_message_header_raises_fr(self):
        # Setup
        encrypted_packet = assembly_packet_creator(MESSAGE, b'testgroup', ORIGIN_CONTACT_HEADER, header=b'Z', encrypt=True)[0]

        # Test
        self.assertFR("Error: Message from contact had an invalid header.",
                          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_invalid_window_raises_fr(self):
        # Setup
        encrypted_packet = assembly_packet_creator(MESSAGE, b'test', ORIGIN_CONTACT_HEADER, group_name='test_group', encrypt=True)[0]

        # Test
        self.assertFR("Error: Received message to unknown group.",
                      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_contact_not_in_group_raises_fr(self):
        # Setup
        encrypted_packet = assembly_packet_creator(MESSAGE, b'test', ORIGIN_CONTACT_HEADER, group_name='testgroup', encrypt=True, origin_acco=b'*****@*****.**')[0]

        # Test
        self.assertFR("Error: Account is not member of group.",
                      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_normal_group_msg_from_contact(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.msg, ORIGIN_CONTACT_HEADER, group_name='testgroup', encrypt=True)

        for p in assembly_ct_list:
            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))
        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_USER_HEADER, group_name='testgroup', encrypt=True)

        for p in assembly_ct_list:
            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))
        self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_logs'), len(assembly_ct_list)*LOG_ENTRY_LENGTH)

    # Group management messages
    def test_group_invitation_msg_from_contact(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.message, ORIGIN_CONTACT_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("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_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_group_add_member_msg_from_contact(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.message, ORIGIN_CONTACT_HEADER,
                                                   header=GROUP_MSG_MEMBER_ADD_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_group_remove_member_msg_from_contact(self):
        # Setup
        assembly_ct_list = assembly_packet_creator(MESSAGE, self.message, ORIGIN_CONTACT_HEADER,
                                                   header=GROUP_MSG_MEMBER_REM_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_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_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)

    # Files
    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_file_file_reception_is_disabled(self):
        # Setup
        payload          = int_to_bytes(1) + int_to_bytes(2) + b'testfile.txt' + US_BYTE + os.urandom(50)
        encrypted_packet = assembly_packet_creator(FILE, payload=payload, origin=ORIGIN_CONTACT_HEADER, encrypt=True)[0]

        self.contact_list.get_contact('*****@*****.**').file_reception = False

        # Test
        self.assertFR("Alert! File transmission from Alice but reception is disabled.",
                      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)
示例#24
0
class TestDecryptAssemblyPacket(TFCTestCase):

    def setUp(self):
        self.o_input      = builtins.input
        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.keyset       = self.key_list.get_keyset('*****@*****.**')
        self.packet       = None

    def tearDown(self):
        builtins.input = self.o_input

    def create_encrypted_packet(self, tx_harac, rx_harac, hek=KEY_LENGTH*b'\x01', key=KEY_LENGTH*b'\x01'):
        encrypted_message    = encrypt_and_sign(PRIVATE_MESSAGE_HEADER + byte_padding(b'test'), key)
        encrypted_harac      = encrypt_and_sign(int_to_bytes(tx_harac), hek)
        self.packet          = MESSAGE_PACKET_HEADER + encrypted_harac + encrypted_message + ORIGIN_CONTACT_HEADER + b'*****@*****.**'
        self.keyset.rx_harac = rx_harac

    def test_invalid_origin_header_raises_fr(self):
        # Setup
        packet = MESSAGE_PACKET_HEADER + MESSAGE_LENGTH*b'm' + b'e'

        # Test
        self.assertFR("Error: Received packet had an invalid origin-header.",
                      decrypt_assembly_packet, packet, self.window_list, self.contact_list, self.key_list)

    def test_masqueraded_command_raises_fr(self):
        for o in [ORIGIN_USER_HEADER, ORIGIN_CONTACT_HEADER]:
            # Setup
            packet = MESSAGE_PACKET_HEADER + MESSAGE_LENGTH*b'm' + o + LOCAL_ID.encode()

            # Test
            self.assertFR("Warning! Received packet masqueraded as command.",
                          decrypt_assembly_packet, packet, self.window_list, self.contact_list, self.key_list)

    def test_invalid_harac_ct_raises_fr(self):
        # Setup
        packet = MESSAGE_PACKET_HEADER + MESSAGE_LENGTH*b'm' + ORIGIN_CONTACT_HEADER + b'*****@*****.**'

        # Test
        self.assertFR("Warning! Received packet from Alice had an invalid hash ratchet MAC.",
                      decrypt_assembly_packet, packet, self.window_list, self.contact_list, self.key_list)

    def test_decryption_with_zero_rx_key_raises_fr(self):
        # Setup
        self.create_encrypted_packet(tx_harac=2, rx_harac=1, key=(hash_chain(KEY_LENGTH*b'\x01')))
        keyset        = self.key_list.get_keyset('*****@*****.**')
        keyset.rx_key = bytes(KEY_LENGTH)

        # Test
        self.assertFR("Warning! Loaded zero-key for packet decryption.",
                      decrypt_assembly_packet, self.packet, self.window_list, self.contact_list, self.key_list)

    def test_decryption_with_zero_rx_hek_raises_fr(self):
        # Setup
        self.create_encrypted_packet(tx_harac=2, rx_harac=1, key=(hash_chain(KEY_LENGTH*b'\x01')))
        keyset        = self.key_list.get_keyset('*****@*****.**')
        keyset.rx_hek = bytes(KEY_LENGTH)

        # Test
        self.assertFR("Warning! Loaded zero-key for packet decryption.",
                      decrypt_assembly_packet, self.packet, self.window_list, self.contact_list, self.key_list)

    def test_invalid_harac_raises_fr(self):
        # Setup
        self.create_encrypted_packet(tx_harac=3, rx_harac=3, hek=KEY_LENGTH*b'\x02')

        # Test
        self.assertFR("Warning! Received packet from Alice had an invalid hash ratchet MAC.",
                      decrypt_assembly_packet, self.packet, self.window_list, self.contact_list, self.key_list)

    def test_expired_harac_raises_fr(self):
        # Setup
        self.create_encrypted_packet(tx_harac=1, rx_harac=3)

        # Test
        self.assertFR("Warning! Received packet from Alice had an expired hash ratchet counter.",
                      decrypt_assembly_packet, self.packet, self.window_list, self.contact_list, self.key_list)

    def test_harac_dos_can_be_interrupted(self):
        # Setup
        self.create_encrypted_packet(tx_harac=10000, rx_harac=3)
        builtins.input = lambda _: 'No'

        # Test
        self.assertFR("Dropped packet from Alice.",
                      decrypt_assembly_packet, self.packet, self.window_list, self.contact_list, self.key_list)

    def test_invalid_packet_ct_raises_fr(self):
        # Setup
        self.create_encrypted_packet(tx_harac=5, rx_harac=3)

        # Test
        self.assertFR("Warning! Received packet from Alice had an invalid MAC.",
                      decrypt_assembly_packet, self.packet, self.window_list, self.contact_list, self.key_list)

    def test_successful_packet_decryption(self):
        # Setup
        self.create_encrypted_packet(tx_harac=1, rx_harac=1)

        # Test
        assembly_pt, account, origin = decrypt_assembly_packet(self.packet, self.window_list, self.contact_list, self.key_list)
        self.assertEqual(rm_padding_bytes(assembly_pt), PRIVATE_MESSAGE_HEADER + b'test')
        self.assertEqual(account, '*****@*****.**')
        self.assertEqual(origin, ORIGIN_CONTACT_HEADER)

    def test_successful_packet_decryption_with_offset(self):
        # Setup
        self.create_encrypted_packet(tx_harac=2, rx_harac=1, key=(hash_chain(KEY_LENGTH*b'\x01')))

        # Test
        assembly_pt, account, origin = decrypt_assembly_packet(self.packet, self.window_list, self.contact_list, self.key_list)
        self.assertEqual(rm_padding_bytes(assembly_pt), PRIVATE_MESSAGE_HEADER + b'test')
        self.assertEqual(account, '*****@*****.**')
        self.assertEqual(origin, ORIGIN_CONTACT_HEADER)

    def test_successful_command_decryption(self):
        # Setup
        command           = byte_padding(b'test')
        encrypted_message = encrypt_and_sign(command, KEY_LENGTH*b'\x01')
        encrypted_harac   = encrypt_and_sign(int_to_bytes(1), KEY_LENGTH*b'\x01')
        packet            = COMMAND_PACKET_HEADER + encrypted_harac + encrypted_message
        keyset            = self.key_list.get_keyset(LOCAL_ID)
        keyset.tx_harac   = 1

        # Test
        assembly_pt, account, origin = decrypt_assembly_packet(packet, self.window_list, self.contact_list, self.key_list)
        self.assertEqual(assembly_pt, command)
        self.assertEqual(account, LOCAL_ID)
        self.assertEqual(origin, ORIGIN_USER_HEADER)