예제 #1
0
    def read(data: BytesIO, *args: Any) -> "HidePromoData":
        # No flags

        peer = TLObject.read(data)

        return HidePromoData(peer=peer)
예제 #2
0
    def read(data: BytesIO, *args: Any) -> "GetAllChats":
        # No flags

        except_ids = TLObject.read(data, Int)

        return GetAllChats(except_ids=except_ids)
예제 #3
0
    async def create(self):
        """
        https://core.telegram.org/mtproto/auth_key
        https://core.telegram.org/mtproto/samples-auth_key
        """
        retries_left = self.MAX_RETRIES

        # The server may close the connection at any time, causing the auth key creation to fail.
        # If that happens, just try again up to MAX_RETRIES times.
        while True:
            self.connection = Connection(self.dc_id, self.test_mode, self.ipv6,
                                         self.proxy)

            try:
                log.info(f"Start creating a new auth key on DC{self.dc_id}")

                await self.connection.connect()

                # Step 1; Step 2
                nonce = int.from_bytes(urandom(16), "little", signed=True)
                log.debug(f"Send req_pq: {nonce}")
                res_pq = await self.invoke(
                    raw.functions.ReqPqMulti(nonce=nonce))
                log.debug(f"Got ResPq: {res_pq.server_nonce}")
                log.debug(
                    f"Server public key fingerprints: {res_pq.server_public_key_fingerprints}"
                )

                for i in res_pq.server_public_key_fingerprints:
                    if i in rsa.server_public_keys:
                        log.debug(f"Using fingerprint: {i}")
                        public_key_fingerprint = i
                        break
                    else:
                        log.debug(f"Fingerprint unknown: {i}")
                else:
                    raise Exception("Public key not found")

                # Step 3
                pq = int.from_bytes(res_pq.pq, "big")
                log.debug(f"Start PQ factorization: {pq}")
                start = time.time()
                g = prime.decompose(pq)
                p, q = sorted((g, pq // g))  # p < q
                log.debug(
                    f"Done PQ factorization ({round(time.time() - start, 3)}s): {p} {q}"
                )

                # Step 4
                server_nonce = res_pq.server_nonce
                new_nonce = int.from_bytes(urandom(32), "little", signed=True)

                data = raw.types.PQInnerData(
                    pq=res_pq.pq,
                    p=p.to_bytes(4, "big"),
                    q=q.to_bytes(4, "big"),
                    nonce=nonce,
                    server_nonce=server_nonce,
                    new_nonce=new_nonce,
                ).write()

                sha = sha1(data).digest()
                padding = urandom(-(len(data) + len(sha)) % 255)
                data_with_hash = sha + data + padding
                encrypted_data = rsa.encrypt(data_with_hash,
                                             public_key_fingerprint)

                log.debug("Done encrypt data with RSA")

                # Step 5. TODO: Handle "server_DH_params_fail". Code assumes response is ok
                log.debug("Send req_DH_params")
                server_dh_params = await self.invoke(
                    raw.functions.ReqDHParams(
                        nonce=nonce,
                        server_nonce=server_nonce,
                        p=p.to_bytes(4, "big"),
                        q=q.to_bytes(4, "big"),
                        public_key_fingerprint=public_key_fingerprint,
                        encrypted_data=encrypted_data))

                encrypted_answer = server_dh_params.encrypted_answer

                server_nonce = server_nonce.to_bytes(16, "little", signed=True)
                new_nonce = new_nonce.to_bytes(32, "little", signed=True)

                tmp_aes_key = (sha1(new_nonce + server_nonce).digest() +
                               sha1(server_nonce + new_nonce).digest()[:12])

                tmp_aes_iv = (sha1(server_nonce + new_nonce).digest()[12:] +
                              sha1(new_nonce + new_nonce).digest() +
                              new_nonce[:4])

                server_nonce = int.from_bytes(server_nonce,
                                              "little",
                                              signed=True)

                answer_with_hash = aes.ige256_decrypt(encrypted_answer,
                                                      tmp_aes_key, tmp_aes_iv)
                answer = answer_with_hash[20:]

                server_dh_inner_data = TLObject.read(BytesIO(answer))

                log.debug("Done decrypting answer")

                dh_prime = int.from_bytes(server_dh_inner_data.dh_prime, "big")
                delta_time = server_dh_inner_data.server_time - time.time()

                log.debug(f"Delta time: {round(delta_time, 3)}")

                # Step 6
                g = server_dh_inner_data.g
                b = int.from_bytes(urandom(256), "big")
                g_b = pow(g, b, dh_prime).to_bytes(256, "big")

                retry_id = 0

                data = raw.types.ClientDHInnerData(nonce=nonce,
                                                   server_nonce=server_nonce,
                                                   retry_id=retry_id,
                                                   g_b=g_b).write()

                sha = sha1(data).digest()
                padding = urandom(-(len(data) + len(sha)) % 16)
                data_with_hash = sha + data + padding
                encrypted_data = aes.ige256_encrypt(data_with_hash,
                                                    tmp_aes_key, tmp_aes_iv)

                log.debug("Send set_client_DH_params")
                set_client_dh_params_answer = await self.invoke(
                    raw.functions.SetClientDHParams(
                        nonce=nonce,
                        server_nonce=server_nonce,
                        encrypted_data=encrypted_data))

                # TODO: Handle "auth_key_aux_hash" if the previous step fails

                # Step 7; Step 8
                g_a = int.from_bytes(server_dh_inner_data.g_a, "big")
                auth_key = pow(g_a, b, dh_prime).to_bytes(256, "big")
                server_nonce = server_nonce.to_bytes(16, "little", signed=True)

                # TODO: Handle errors

                #######################
                # Security checks
                #######################

                SecurityCheckMismatch.check(dh_prime == prime.CURRENT_DH_PRIME)
                log.debug("DH parameters check: OK")

                # https://core.telegram.org/mtproto/security_guidelines#g-a-and-g-b-validation
                g_b = int.from_bytes(g_b, "big")
                SecurityCheckMismatch.check(1 < g < dh_prime - 1)
                SecurityCheckMismatch.check(1 < g_a < dh_prime - 1)
                SecurityCheckMismatch.check(1 < g_b < dh_prime - 1)
                SecurityCheckMismatch.check(
                    2**(2048 - 64) < g_a < dh_prime - 2**(2048 - 64))
                SecurityCheckMismatch.check(
                    2**(2048 - 64) < g_b < dh_prime - 2**(2048 - 64))
                log.debug("g_a and g_b validation: OK")

                # https://core.telegram.org/mtproto/security_guidelines#checking-sha1-hash-values
                answer = server_dh_inner_data.write(
                )  # Call .write() to remove padding
                SecurityCheckMismatch.check(
                    answer_with_hash[:20] == sha1(answer).digest())
                log.debug("SHA1 hash values check: OK")

                # https://core.telegram.org/mtproto/security_guidelines#checking-nonce-server-nonce-and-new-nonce-fields
                # 1st message
                SecurityCheckMismatch.check(nonce == res_pq.nonce)
                # 2nd message
                server_nonce = int.from_bytes(server_nonce,
                                              "little",
                                              signed=True)
                SecurityCheckMismatch.check(nonce == server_dh_params.nonce)
                SecurityCheckMismatch.check(
                    server_nonce == server_dh_params.server_nonce)
                # 3rd message
                SecurityCheckMismatch.check(
                    nonce == set_client_dh_params_answer.nonce)
                SecurityCheckMismatch.check(
                    server_nonce == set_client_dh_params_answer.server_nonce)
                server_nonce = server_nonce.to_bytes(16, "little", signed=True)
                log.debug("Nonce fields check: OK")

                # Step 9
                server_salt = aes.xor(new_nonce[:8], server_nonce[:8])

                log.debug(
                    f"Server salt: {int.from_bytes(server_salt, 'little')}")

                log.info(
                    f"Done auth key exchange: {set_client_dh_params_answer.__class__.__name__}"
                )
            except Exception as e:
                if retries_left:
                    retries_left -= 1
                else:
                    raise e

                await asyncio.sleep(1)
                continue
            else:
                return auth_key
            finally:
                self.connection.close()
예제 #4
0
 def read(data: BytesIO, *args: Any) -> "Authorizations":
     # No flags
     
     authorizations = TLObject.read(data)
     
     return Authorizations(authorizations=authorizations)
    def read(data: BytesIO, *args: Any) -> "InputPrivacyValueAllowUsers":
        # No flags

        users = TLObject.read(data)

        return InputPrivacyValueAllowUsers(users=users)
예제 #6
0
 def read(data: BytesIO, *args: Any) -> "GetChannels":
     # No flags
     
     id = TLObject.read(data)
     
     return GetChannels(id=id)
예제 #7
0
    def read(data: BytesIO, *args: Any) -> "TextItalic":
        # No flags

        text = TLObject.read(data)

        return TextItalic(text=text)
예제 #8
0
 def read(data: BytesIO, *args: Any) -> "GetOnlines":
     # No flags
     
     peer = TLObject.read(data)
     
     return GetOnlines(peer=peer)
예제 #9
0
    def read(data: BytesIO, *args: Any) -> "AcceptTermsOfService":
        # No flags

        id = TLObject.read(data)

        return AcceptTermsOfService(id=id)
예제 #10
0
    def read(data: BytesIO, *args: Any) -> "GetWallPaper":
        # No flags

        wallpaper = TLObject.read(data)

        return GetWallPaper(wallpaper=wallpaper)
    def read(data: BytesIO, *args: Any) -> "Message":
        flags = Int.read(data)

        out = True if flags & (1 << 1) else False
        mentioned = True if flags & (1 << 4) else False
        media_unread = True if flags & (1 << 5) else False
        silent = True if flags & (1 << 13) else False
        post = True if flags & (1 << 14) else False
        from_scheduled = True if flags & (1 << 18) else False
        legacy = True if flags & (1 << 19) else False
        edit_hide = True if flags & (1 << 21) else False
        pinned = True if flags & (1 << 24) else False
        id = Int.read(data)

        from_id = TLObject.read(data) if flags & (1 << 8) else None

        peer_id = TLObject.read(data)

        fwd_from = TLObject.read(data) if flags & (1 << 2) else None

        via_bot_id = Int.read(data) if flags & (1 << 11) else None
        reply_to = TLObject.read(data) if flags & (1 << 3) else None

        date = Int.read(data)

        message = String.read(data)

        media = TLObject.read(data) if flags & (1 << 9) else None

        reply_markup = TLObject.read(data) if flags & (1 << 6) else None

        entities = TLObject.read(data) if flags & (1 << 7) else []

        views = Int.read(data) if flags & (1 << 10) else None
        forwards = Int.read(data) if flags & (1 << 10) else None
        replies = TLObject.read(data) if flags & (1 << 23) else None

        edit_date = Int.read(data) if flags & (1 << 15) else None
        post_author = String.read(data) if flags & (1 << 16) else None
        grouped_id = Long.read(data) if flags & (1 << 17) else None
        restriction_reason = TLObject.read(data) if flags & (1 << 22) else []

        return Message(id=id,
                       peer_id=peer_id,
                       date=date,
                       message=message,
                       out=out,
                       mentioned=mentioned,
                       media_unread=media_unread,
                       silent=silent,
                       post=post,
                       from_scheduled=from_scheduled,
                       legacy=legacy,
                       edit_hide=edit_hide,
                       pinned=pinned,
                       from_id=from_id,
                       fwd_from=fwd_from,
                       via_bot_id=via_bot_id,
                       reply_to=reply_to,
                       media=media,
                       reply_markup=reply_markup,
                       entities=entities,
                       views=views,
                       forwards=forwards,
                       replies=replies,
                       edit_date=edit_date,
                       post_author=post_author,
                       grouped_id=grouped_id,
                       restriction_reason=restriction_reason)
    def read(data: BytesIO, *args: Any) -> "TextFixed":
        # No flags

        text = TLObject.read(data)

        return TextFixed(text=text)
예제 #13
0
    def read(data: BytesIO, *args: Any) -> "SaveAppLog":
        # No flags

        events = TLObject.read(data)

        return SaveAppLog(events=events)
 def read(data: BytesIO, *args: Any) -> "ChannelAdminLogEventActionExportedInviteRevoke":
     # No flags
     
     invite = TLObject.read(data)
     
     return ChannelAdminLogEventActionExportedInviteRevoke(invite=invite)
    def read(data: BytesIO, *args: Any) -> "AuthorizationSignUpRequired":
        flags = Int.read(data)

        terms_of_service = TLObject.read(data) if flags & (1 << 0) else None

        return AuthorizationSignUpRequired(terms_of_service=terms_of_service)
예제 #16
0
    def read(data: BytesIO, *args: Any) -> "MessageMediaGeo":
        # No flags

        geo = TLObject.read(data)

        return MessageMediaGeo(geo=geo)
예제 #17
0
 def read(data: BytesIO, *args: Any) -> "JsonObject":
     # No flags
     
     value = TLObject.read(data)
     
     return JsonObject(value=value)
    def read(data: BytesIO, *args: Any) -> "PageListItemBlocks":
        # No flags

        blocks = TLObject.read(data)

        return PageListItemBlocks(blocks=blocks)
    def read(data: BytesIO, *args: Any) -> "MessageMediaGame":
        # No flags

        game = TLObject.read(data)

        return MessageMediaGame(game=game)
예제 #20
0
 def read(data: BytesIO, *args: Any) -> "PageBlockParagraph":
     # No flags
     
     text = TLObject.read(data)
     
     return PageBlockParagraph(text=text)
예제 #21
0
    def read(data: BytesIO, *args: Any) -> "DeleteChannel":
        # No flags

        channel = TLObject.read(data)

        return DeleteChannel(channel=channel)
예제 #22
0
    def read(data: BytesIO, *args: Any) -> "InputMediaGeoPoint":
        # No flags

        geo_point = TLObject.read(data)

        return InputMediaGeoPoint(geo_point=geo_point)
예제 #23
0
    def read(data: BytesIO, *args: Any) -> "GetMessages":
        # No flags

        id = TLObject.read(data)

        return GetMessages(id=id)
예제 #24
0
    def read(data: BytesIO, *args: Any) -> "SetBotCommands":
        # No flags

        commands = TLObject.read(data)

        return SetBotCommands(commands=commands)
 def read(data: BytesIO, *args: Any) -> "MessageActionChatAddUser":
     # No flags
     
     users = TLObject.read(data, Int)
     
     return MessageActionChatAddUser(users=users)
예제 #26
0
 def read(data: BytesIO, *args: Any) -> "InputBotInlineMessageGame":
     flags = Int.read(data)
     
     reply_markup = TLObject.read(data) if flags & (1 << 2) else None
     
     return InputBotInlineMessageGame(reply_markup=reply_markup)
예제 #27
0
 def unpack(b: BytesIO):
     b.seek(
         20)  # Skip auth_key_id (8), message_id (8) and message_length (4)
     return TLObject.read(b)
    def read(data: BytesIO, *args: Any) -> "PrivacyValueDisallowChatParticipants":
        # No flags

        chats = TLObject.read(data, Int)

        return PrivacyValueDisallowChatParticipants(chats=chats)
예제 #29
0
    def read(data: BytesIO, *args: Any) -> "DeletePhotos":
        # No flags

        id = TLObject.read(data)

        return DeletePhotos(id=id)
예제 #30
0
    def read(data: BytesIO, *args: Any) -> "UpdateChatParticipants":
        # No flags

        participants = TLObject.read(data)

        return UpdateChatParticipants(participants=participants)