code: def decrypt_message_data(self, body):
          
          if len(body) < 8:
              raise InvalidBufferError(body)
  
          # TODO Check salt, session_id and sequence_number
          key_id = struct.unpack('<Q', body[:8])[0]
          if key_id != self.auth_key.key_id:
              raise SecurityError('Server replied with an invalid auth key')
  
          msg_key = body[8:24]
          aes_key, aes_iv = self._calc_key(self.auth_key.key, msg_key, False)
          body = AES.decrypt_ige(body[24:], aes_key, aes_iv)
  
          # https://core.telegram.org/mtproto/security_guidelines
          # Sections "checking sha256 hash" and "message length"
          our_key = sha256(self.auth_key.key[96:96 + 32] + body)
          if msg_key != our_key.digest()[8:24]:
              raise SecurityError(
                  "Received msg_key doesn't match with expected one")
  
          reader = BinaryReader(body)
          reader.read_long()  # remote_salt
          if reader.read_long() != self.id:
              raise SecurityError('Server replied with a wrong session ID')
  
          remote_msg_id = reader.read_long()
          remote_sequence = reader.read_int()
          reader.read_int()  # msg_len for the inner object, padding ignored
  
          # We could read msg_len bytes and use those in a new reader to read
          # the next TLObject without including the padding, but since the
          # reader isn't used for anything else after this, it's unnecessary.
          obj = reader.tgread_object()
  
          return TLMessage(remote_msg_id, remote_sequence, obj)
docs: Inverse of `encrypt_message_data` for incoming server messages.