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_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 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