def test_advanced_ciphertext_message():
    add_message = AddMessage(index=1337,
                             init_key=os.urandom(32),
                             welcome_info_hash=os.urandom(32))
    group_op = GroupOperation(msg_type=GroupOperationType.ADD,
                              operation=add_message)
    handshake = MLSPlaintextHandshake(confirmation=12,
                                      group_operation=group_op)

    message = MLSPlaintext(group_id=b'helloworld',
                           epoch=1337,
                           content_type=ContentType.HANDSHAKE,
                           sender=42,
                           signature=b'steffensoddemann',
                           content=handshake)

    encrypted_message = MLSCiphertext(group_id=message.group_id,
                                      epoch=message.epoch,
                                      content_type=message.content_type,
                                      sender_data_nounce=b'0',
                                      encrypted_sender_data=b'0',
                                      ciphertext=message.pack())

    box_thingy = MLSCiphertext.from_bytes(encrypted_message.pack())
    assert box_thingy == encrypted_message
    assert MLSPlaintext.from_bytes(box_thingy.ciphertext) == message
def test_ciphertext_message():
    # pylint: disable=unexpected-keyword-arg
    message = MLSCiphertext(group_id=b'helloworld',
                            epoch=1337,
                            content_type=ContentType.HANDSHAKE,
                            sender_data_nounce=b'steffensoddemann',
                            encrypted_sender_data=b'mepmep',
                            ciphertext=b'topsecrit')

    assert MLSCiphertext.from_bytes(message.pack()) == message
Beispiel #3
0
    def get_messages(self, user: str, device: str):
        """
        Requests messages from dirserver using own identity
        :return:
        """
        try:
            params = {"user": user, "device": device}
            response = requests.get("http://" + self.dir_server + "/message",
                                    params=params)

            # print(response.content)

            if response.status_code != 200:
                raise RuntimeError(
                    f'GetMessage status code {response.status_code}')

            messages: Dict = json.loads(response.content)
            print(f"Got {len(messages)} messages!")

            for message in messages:
                print(message)
                message_wrapper = message['message']
                is_welcome: bool = message_wrapper['is_welcome']
                message_content: bytes = bytes.fromhex(
                    message_wrapper['message'])

                if is_welcome:
                    session: Session = Session.from_welcome(
                        WelcomeInfoMessage.from_bytes(message_content),
                        self.keystore, self.user)
                    chat_name = session.get_state().get_group_context(
                    ).group_id.decode('ASCII')
                    self.chats[chat_name] = Chat.from_welcome([], chat_name,
                                                              session)
                    print("Got added to group " + chat_name)
                    continue

                name = Session.get_groupid_from_cipher(
                    data=message_content).decode('UTF-8')
                self.chats[name].session.process_message(
                    message=MLSCiphertext.from_bytes(message_content),
                    handler=self)
            return len(messages)
        except requests.exceptions.ConnectionError:
            raise ConnectionError
def test_weird_plaintext():
    pytest.skip()
    expected_cipher = b'\x00\x00\x00\x00\x00\x00\x00\x16\x01\x00\x00\x00\x11' \
                      b'\x00\x00\x00\x01\x00\x00\x00\x041234\x00\x00\x00\x010'

    my_bytes = bytes.fromhex(
        "000000036d65700000000001000000013000000001300000001e000000"
        "000000001601000000110000000100000004313233340000000130")

    cipher = MLSCiphertext.from_bytes(my_bytes)

    print(vars(cipher))

    assert expected_cipher == cipher.ciphertext

    plain = MLSPlaintext.from_bytes(cipher.ciphertext)

    assert plain.content_type == ContentType.HANDSHAKE
Beispiel #5
0
    def encrypt_handshake_message(self,
                                  group_op: GroupOperation) -> MLSCiphertext:
        """
        RFC Section 9 Handshake Message
        https://tools.ietf.org/html/draft-ietf-mls-protocol-07#section-9

        An MLS handshake message encapsulates a specific GroupOperation
        message that accomplishes a change to the group state.  It is carried
        in an MLSPlaintext message that provides a signature by the sender of
        the message.  Applications may choose to send handshake messages in
        encrypted form, as MLSCiphertext messages.

        :param group_op: which Handshake operation is encrypted
        :return: the encrypted object MLSCiphertext
        """
        # todo: confirmation
        # pylint: disable=unexpected-keyword-arg
        handshake = MLSPlaintextHandshake(confirmation=0,
                                          group_operation=group_op)

        # pylint: disable=unexpected-keyword-arg
        plaintext = MLSPlaintext(
            group_id=self._state.get_group_context().group_id,
            epoch=self._state.get_group_context().epoch,
            content_type=ContentType.HANDSHAKE,
            sender=self._user_index,
            signature=b'0',
            content=handshake)

        # todo: encrypt stuff
        # pylint: disable=unexpected-keyword-arg
        encrypted = MLSCiphertext(content_type=ContentType.HANDSHAKE,
                                  group_id=plaintext.group_id,
                                  epoch=plaintext.epoch,
                                  sender_data_nounce=b'0',
                                  encrypted_sender_data=b'0',
                                  ciphertext=plaintext.pack())

        return encrypted
Beispiel #6
0
    def encrypt_application_message(self, message: bytes) -> MLSCiphertext:
        """
        RFC Section 11.1 Tree of Application Secrets
        RFC Section 11.2 Sender Ratchets
        RFC Section 11.3 Deletion Schedule

        Here, the the encryption of application messages using the ApplicationSecretTree and
        DoubleRatchets would take place.

        :param message: the message to encrypt
        :return: the encrypted MLSCiphertext object
        """
        if self._user_index is None:
            raise RuntimeError(
                "User index is None. This typically happens, whenever we do not have the private"
                "key for a public key which is used to create a group, even though we should"
                "have it.")

        # pylint: disable=unexpected-keyword-arg
        sender_data = MLSSenderData(sender=self._user_index, generation=0)

        # pylint: disable=unexpected-keyword-arg
        plaintext = MLSPlaintext(
            group_id=self._state.get_group_context().group_id,
            epoch=self._state.get_group_context().epoch,
            content_type=ContentType.APPLICATION,
            sender=self._user_index,
            signature=b'0',
            content=MLSPlaintextApplicationData(application_data=message))

        # pylint: disable=unexpected-keyword-arg
        out = MLSCiphertext(content_type=ContentType.APPLICATION,
                            group_id=plaintext.group_id,
                            epoch=plaintext.epoch,
                            sender_data_nounce=b'0',
                            encrypted_sender_data=sender_data.pack(),
                            ciphertext=plaintext.pack())

        return out
Beispiel #7
0
 def get_groupid_from_cipher(data: bytes) -> bytes:
     return MLSCiphertext.from_bytes(data).group_id