Exemple #1
0
    def store_settings(self) -> None:
        """Store settings to an encrypted database.

        The plaintext in the encrypted database is a constant
        length bytestring regardless of stored setting values.
        """
        attribute_list = [self.__getattribute__(k) for k in self.key_list]

        bytes_lst = []
        for a in attribute_list:
            if isinstance(a, bool):
                bytes_lst.append(bool_to_bytes(a))
            elif isinstance(a, int):
                bytes_lst.append(int_to_bytes(a))
            elif isinstance(a, float):
                bytes_lst.append(double_to_bytes(a))
            else:
                raise CriticalError("Invalid attribute type in settings.")

        pt_bytes = b''.join(bytes_lst)
        ct_bytes = encrypt_and_sign(pt_bytes, self.master_key.master_key)

        ensure_dir(DIR_USER_DATA)
        with open(self.file_name, 'wb+') as f:
            f.write(ct_bytes)
Exemple #2
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()
Exemple #3
0
    def mock_entry_preprocessor(message: str, header: bytes = b'', group: bool = False) -> List[bytes]:
        if not header:
            if group:
                timestamp = double_to_bytes(time.time() * 1000)
                header    = GROUP_MESSAGE_HEADER + timestamp + 'testgroup'.encode() + US_BYTE
            else:
                header = PRIVATE_MESSAGE_HEADER

        plaintext = message.encode()
        payload   = header + plaintext
        payload   = zlib.compress(payload, level=9)

        if len(payload) < 255:
            padded      = byte_padding(payload)
            packet_list = [M_S_HEADER + padded]
        else:
            msg_key  = bytes(32)
            payload  = encrypt_and_sign(payload, msg_key)
            payload += msg_key
            padded   = byte_padding(payload)
            p_list   = split_byte_string(padded, item_len=255)

            packet_list = ([M_L_HEADER + p_list[0]] +
                           [M_A_HEADER + p for p in p_list[1:-1]] +
                           [M_E_HEADER + p_list[-1]])

        return packet_list
Exemple #4
0
def queue_message(user_input: Union['UserInput', 'Message'],
                  window: Union['MockWindow', 'Window'],
                  settings: 'Settings',
                  m_queue: 'Queue',
                  header: bytes = b'') -> None:
    """Convert message into set of assembly packets and queue them.

    :param user_input: UserInput object
    :param window:     Window object
    :param settings:   Settings object
    :param m_queue:    Multiprocessing message queue
    :param header:     Overrides message header with group management header
    :return:           None
    """
    if not header:
        if window.type == 'group':
            timestamp = double_to_bytes(time.time() * 1000)
            header = GROUP_MESSAGE_HEADER + timestamp + window.name.encode(
            ) + US_BYTE
        else:
            header = PRIVATE_MESSAGE_HEADER

    plaintext = user_input.plaintext.encode()
    payload = header + plaintext
    payload = zlib.compress(payload, level=9)

    if len(payload) < 255:
        padded = byte_padding(payload)
        packet_list = [M_S_HEADER + padded]
    else:
        msg_key = keygen()
        payload = encrypt_and_sign(payload, msg_key)
        payload += msg_key
        padded = byte_padding(payload)
        p_list = split_byte_string(padded, item_len=255)

        packet_list = ([M_L_HEADER + p_list[0]] +
                       [M_A_HEADER + p
                        for p in p_list[1:-1]] + [M_E_HEADER + p_list[-1]])

    if settings.session_trickle:
        log_m_dictionary = dict((c.rx_account, c.log_messages) for c in window)
        for p in packet_list:
            m_queue.put((p, log_m_dictionary))

    else:
        for c in window:
            log_setting = window.group.log_messages if window.type == 'group' else c.log_messages
            for p in packet_list:
                m_queue.put((p, settings, c.rx_account, c.tx_account,
                             log_setting, window.uid))
Exemple #5
0
    def change_setting(self, key: str, value: str, contact_list: 'ContactList',
                       group_list: 'GroupList') -> None:
        """Parse, update and store new setting value."""
        attribute = self.__getattribute__(key)

        if isinstance(attribute, bool):
            value_ = value
            value = value.lower().capitalize()
            if value not in ['True', 'False']:
                raise FunctionReturn(f"Invalid value {value_}.")

        elif isinstance(attribute, int):
            if not value.isdigit() or eval(value) < 0 or eval(
                    value) > 7378697629483820640:
                raise FunctionReturn(f"Invalid value {value}.")

        elif isinstance(attribute, float):
            if not isinstance(eval(value), float) or eval(value) < 0.0:
                raise FunctionReturn(f"Invalid value {value}.")
            try:
                double_to_bytes(eval(value))
            except struct.error:
                raise FunctionReturn(f"Invalid value {value}.")

        elif isinstance(attribute, str):
            if len(value) > 255:
                raise FunctionReturn(
                    f"Setting must be shorter than 256 chars.")

        else:
            raise CriticalError("Invalid attribute type in settings.")

        self.validate_key_value_pair(key, value, contact_list, group_list)

        value = value if isinstance(attribute, str) else eval(value)
        setattr(self, key, value)
        self.store_settings()
Exemple #6
0
    def store_settings(self) -> None:
        """Store settings to encrypted database."""
        attribute_list = [self.__getattribute__(k) for k in self.key_list]

        # Convert attributes into constant length byte string
        pt_bytes = b''
        for a in attribute_list:
            if isinstance(a, bool): pt_bytes += bool_to_bytes(a)
            elif isinstance(a, int): pt_bytes += int_to_bytes(a)
            elif isinstance(a, float): pt_bytes += double_to_bytes(a)
            elif isinstance(a, str): pt_bytes += str_to_bytes(a)
            else: raise CriticalError("Invalid attribute type in settings.")

        ct_bytes = encrypt_and_sign(pt_bytes, self.master_key.master_key)

        ensure_dir(f'{DIR_USER_DATA}/')
        with open(self.file_name, 'wb+') as f:
            f.write(ct_bytes)
Exemple #7
0
    def store_settings(self, replace: bool = True) -> None:
        """Store settings to an encrypted database.

        The plaintext in the encrypted database is a constant
        length bytestring regardless of stored setting values.
        """
        attribute_list = [self.__getattribute__(k) for k in self.key_list]

        bytes_lst = []
        for a in attribute_list:
            if isinstance(a, bool):
                bytes_lst.append(bool_to_bytes(a))
            elif isinstance(a, int):
                bytes_lst.append(int_to_bytes(a))
            elif isinstance(a, float):
                bytes_lst.append(double_to_bytes(a))
            else:
                raise CriticalError("Invalid attribute type in settings.")

        pt_bytes = b''.join(bytes_lst)
        self.database.store_database(pt_bytes, replace)
Exemple #8
0
    def create_message_apct(origin, message, header=None, group_name=None):
        if not header:
            if group_name is not None:
                timestamp = double_to_bytes(time.time() * 1000)
                header = GROUP_MESSAGE_HEADER + timestamp + group_name + US_BYTE
            else:
                header = PRIVATE_MESSAGE_HEADER

        plaintext = header + message
        payload = zlib.compress(plaintext, level=9)
        if len(payload) < 255:
            padded = byte_padding(payload)
            packet_list = [M_S_HEADER + padded]
        else:
            msg_key = os.urandom(32)
            payload = encrypt_and_sign(payload, msg_key)
            payload += msg_key
            padded = byte_padding(payload)
            p_list = split_byte_string(padded, item_len=255)

            packet_list = ([M_L_HEADER + p_list[0]] +
                           [M_A_HEADER + p
                            for p in p_list[1:-1]] + [M_E_HEADER + p_list[-1]])

        harac = 1
        m_key = 32 * b'\x01'
        apctl = []
        for p in packet_list:
            harac_in_bytes = int_to_bytes(harac)
            encrypted_harac = encrypt_and_sign(harac_in_bytes, 32 * b'\x01')
            encrypted_message = encrypt_and_sign(p, m_key)
            encrypted_packet = MESSAGE_PACKET_HEADER + encrypted_harac + encrypted_message + origin + b'*****@*****.**'
            apctl.append(encrypted_packet)
            harac += 1
            m_key = hash_chain(m_key)
        return apctl
Exemple #9
0
 def test_double_to_bytes(self):
     self.assertEqual(double_to_bytes(1.0),
                      bytes.fromhex('000000000000f03f'))
     self.assertEqual(double_to_bytes(1.1),
                      bytes.fromhex('9a9999999999f13f'))
     self.assertEqual(len(double_to_bytes(1.1)), ENCODED_FLOAT_LENGTH)
Exemple #10
0
 def test_double_to_bytes(self):
     self.assertEqual(double_to_bytes(1.0),
                      binascii.unhexlify('000000000000f03f'))
     self.assertEqual(double_to_bytes(1.1),
                      binascii.unhexlify('9a9999999999f13f'))
     self.assertEqual(len(double_to_bytes(1.1)), FLOAT_SETTING_LEN)
Exemple #11
0
 def test_double_to_bytes(self):
     self.assertEqual(double_to_bytes(1.0), binascii.unhexlify('000000000000f03f'))
     self.assertEqual(double_to_bytes(1.1), binascii.unhexlify('9a9999999999f13f'))