async def complete_rekey(self, peer,
                             action: DecryptedMessageActionCommitKey):
        peer = self.get_secret_chat(peer)
        if peer.rekeying[0] != 2 or self.temp_rekeyed_secret_chats.get(
                action.exchange_id, None):
            return
        if self.temp_rekeyed_secret_chats.get(
                action.exchange_id) != action.key_fingerprint:
            message = DecryptedMessageService(
                action=DecryptedMessageActionAbortKey(
                    exchange_id=action.exchange_id, ))
            message = await self.encrypt_secret_message(peer, message)
            await self.client(
                SendEncryptedServiceRequest(
                    InputEncryptedChat(peer.id, peer.access_hash), message))
            raise SecurityError("Invalid Key fingerprint")

        self._log.debug(f'Completing rekeying secret chat {peer}')
        peer.rekeying = [0]
        peer.auth_key = self.temp_rekeyed_secret_chats[action.exchange_id]
        peer.ttr = 100
        peer.updated = time()
        del self.temp_rekeyed_secret_chats[action.exchange_id]
        message = DecryptedMessageService(action=DecryptedMessageActionNoop())
        message = await self.encrypt_secret_message(peer, message)
        await self.client(
            SendEncryptedServiceRequest(
                InputEncryptedChat(peer.id, peer.access_hash), message))
        self._log.debug(f'Secret chat {peer} rekeyed succrsfully')
 async def commit_rekey(self, peer, action: DecryptedMessageActionAcceptKey):
     peer = self.get_secret_chat(peer)
     if peer.rekeying[0] != 1 or not self._temp_rekeyed_secret_chats.get(action.exchange_id, None):
         peer.rekeying = [0]
         return
     self._log.debug(f'Committing rekeying secret chat {peer}')
     dh_config = await self.get_dh_config()
     g_b = int.from_bytes(action.g_b, 'big', signed=False)
     self.check_g_a(g_b, dh_config.p)
     res = pow(g_b, self._temp_rekeyed_secret_chats[action.exchange_id], dh_config.p)
     auth_key = res.to_bytes(256, 'big', signed=False)
     key_fingerprint = struct.unpack('<q', sha1(auth_key).digest()[-8:])[0]
     if key_fingerprint != action.key_fingerprint:
         message = DecryptedMessageService(action=DecryptedMessageActionAbortKey(
             exchange_id=action.exchange_id,
         ))
         message = await self.encrypt_secret_message(peer, message)
         await self.client(SendEncryptedServiceRequest(InputEncryptedChat(peer.id, peer.access_hash), message))
         raise SecurityError("Invalid Key fingerprint")
     message = DecryptedMessageService(action=DecryptedMessageActionCommitKey(
         exchange_id=action.exchange_id,
         key_fingerprint=key_fingerprint
     ))
     message = await self.encrypt_secret_message(peer, message)
     await self.client(SendEncryptedServiceRequest(InputEncryptedChat(peer.id, peer.access_hash), message))
     del self._temp_rekeyed_secret_chats[action.exchange_id]
     peer.rekeying = [0]
     peer.auth_key = auth_key
     peer.ttl = 100
     peer.updated = time()
    async def accept_secret_chat(self, chat: TypeEncryptedChat):
        if chat.id == 0:
            raise ValueError("Already accepted")
        dh_config = await self.get_dh_config()
        random_bytes = os.urandom(256)
        b = int.from_bytes(random_bytes, byteorder="big", signed=False)
        g_a = int.from_bytes(chat.g_a, 'big', signed=False)
        self.check_g_a(g_a, dh_config.p)
        res = pow(g_a, b, dh_config.p)
        auth_key = res.to_bytes(256, 'big', signed=False)

        key_fingerprint = struct.unpack('<q', sha1(auth_key).digest()[-8:])[0]
        input_peer = InputEncryptedChat(chat_id=chat.id,
                                        access_hash=chat.access_hash)
        secret_chat = SecretChat(chat.id,
                                 chat.access_hash,
                                 auth_key,
                                 admin=False,
                                 user_id=chat.admin_id,
                                 input_chat=input_peer)
        self.session.save_chat(secret_chat, False)
        g_b = pow(dh_config.g, b, dh_config.p)
        self.check_g_a(g_b, dh_config.p)
        result = await self.client(
            AcceptEncryptionRequest(input_peer,
                                    g_b=g_b.to_bytes(256, 'big', signed=False),
                                    key_fingerprint=key_fingerprint))
        await self.notify_layer(chat)
        return result
 async def accept_rekey(self, peer,
                        action: DecryptedMessageActionRequestKey):
     peer = self.get_secret_chat(peer)
     if peer.rekeying[0] != 0:
         my_exchange_id = peer.rekeying[1]
         other_exchange_id = action.exchange_id
         if my_exchange_id > other_exchange_id:
             return
         if my_exchange_id == other_exchange_id:
             peer.rekeying = [0]
             return
     self._log.debug(f'Accepting rekeying secret chat {peer}')
     dh_config = await self.get_dh_config()
     random_bytes = os.urandom(256)
     b = int.from_bytes(random_bytes, byteorder="big", signed=False)
     g_a = int.from_bytes(action.g_a, 'big', signed=False)
     self.check_g_a(g_a, dh_config.p)
     res = pow(g_a, b, dh_config.p)
     auth_key = res.to_bytes(256, 'big', signed=False)
     key_fingerprint = struct.unpack('<q', sha1(auth_key).digest()[-8:])[0]
     self.temp_rekeyed_secret_chats[action.exchange_id] = auth_key
     peer.rekeying = [2, action.exchange_id]
     g_b = pow(dh_config.g, b, dh_config.p)
     self.check_g_a(g_b, dh_config.p)
     message = DecryptedMessageService(
         action=DecryptedMessageActionAcceptKey(
             g_b=g_b.to_bytes(256, 'big', signed=False),
             exchange_id=action.exchange_id,
             key_fingerprint=key_fingerprint))
     message = await self.encrypt_secret_message(peer, message)
     await self.client(
         SendEncryptedServiceRequest(
             InputEncryptedChat(peer.id, peer.access_hash), message))
 async def notify_layer(self, peer: [int, SecretChat, InputEncryptedChat, EncryptedChat]):
     peer = self.get_secret_chat(peer)
     if peer.layer == 8:
         return
     message = DecryptedMessageService8(action=DecryptedMessageActionNotifyLayer(
         layer=min(DEFAULT_LAYER, peer.layer)), random_bytes=os.urandom(15 + 4 * random.randint(0, 2)))
     data = await self.encrypt_secret_message(peer.id, message)
     return await self.client(
         SendEncryptedServiceRequest(peer=InputEncryptedChat(peer.id, peer.access_hash),
                                     data=data))
 async def finish_secret_chat_creation(self, chat):
     dh_config = await self.get_dh_config()
     g_a_or_b = int.from_bytes(chat.g_a_or_b, "big", signed=False)
     self.check_g_a(g_a_or_b, dh_config.p)
     a = self.session.get_temp_secret_chat_by_id(chat.id).auth_key
     a = int.from_bytes(a, "big", signed=False)
     auth_key = pow(g_a_or_b, a, dh_config.p).to_bytes(
         256, "big", signed=False)
     self.session.remove_secret_chat_by_id(chat.id, True)
     key_fingerprint = struct.unpack('<q', sha1(auth_key).digest()[-8:])[0]
     if key_fingerprint != chat.key_fingerprint:
         raise ValueError("Wrong fingerprint")
     input_peer = InputEncryptedChat(chat_id=chat.id, access_hash=chat.access_hash)
     SecretChat(chat.id, chat.access_hash, auth_key, True, chat.participant_id,
                input_peer, session=self.session).save()
     await self.notify_layer(chat)
    async def rekey(self, peer):
        peer = self.get_secret_chat(peer)
        self._log.debug(f'Rekeying secret chat {peer}')
        dh_config = await self.get_dh_config()
        a = int.from_bytes(os.urandom(256), 'big', signed=False)
        g_a = pow(dh_config.g, a, dh_config.p)
        self.check_g_a(g_a, dh_config.p)
        e = random.randint(10000000, 99999999)
        self._temp_rekeyed_secret_chats[e] = a
        peer.rekeying = [1, e]
        message = DecryptedMessageService(action=DecryptedMessageActionRequestKey(
            g_a=g_a.to_bytes(256, 'big', signed=False),
            exchange_id=e,
        ))
        message = await self.encrypt_secret_message(peer, message)
        await self.client(SendEncryptedServiceRequest(InputEncryptedChat(peer.id, peer.access_hash), message))

        return e
Example #8
0
 def get_temp_secret_chat_by_id(self, id):
     row = self._execute(
         f"select * from {TABLE_NAME} where temp=1 and id = ?", id)
     if row:
         input_chat = InputEncryptedChat(chat_id=row[0], access_hash=row[1])
         return SecretChat(id=row[0],
                           access_hash=row[1],
                           auth_key=row[2],
                           admin=True if row[3] else False,
                           user_id=row[4],
                           in_seq_no_x=row[5],
                           out_seq_no_x=row[6],
                           in_seq_no=row[7],
                           out_seq_no=row[8],
                           layer=row[9],
                           ttl=row[10],
                           ttr=row[11],
                           updated=row[12],
                           created=row[13],
                           mtproto=row[14],
                           input_chat=input_chat)