def read(data: BytesIO, *args: Any) -> "HidePromoData": # No flags peer = TLObject.read(data) return HidePromoData(peer=peer)
def read(data: BytesIO, *args: Any) -> "GetAllChats": # No flags except_ids = TLObject.read(data, Int) return GetAllChats(except_ids=except_ids)
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()
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)
def read(data: BytesIO, *args: Any) -> "GetChannels": # No flags id = TLObject.read(data) return GetChannels(id=id)
def read(data: BytesIO, *args: Any) -> "TextItalic": # No flags text = TLObject.read(data) return TextItalic(text=text)
def read(data: BytesIO, *args: Any) -> "GetOnlines": # No flags peer = TLObject.read(data) return GetOnlines(peer=peer)
def read(data: BytesIO, *args: Any) -> "AcceptTermsOfService": # No flags id = TLObject.read(data) return AcceptTermsOfService(id=id)
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)
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)
def read(data: BytesIO, *args: Any) -> "MessageMediaGeo": # No flags geo = TLObject.read(data) return MessageMediaGeo(geo=geo)
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)
def read(data: BytesIO, *args: Any) -> "PageBlockParagraph": # No flags text = TLObject.read(data) return PageBlockParagraph(text=text)
def read(data: BytesIO, *args: Any) -> "DeleteChannel": # No flags channel = TLObject.read(data) return DeleteChannel(channel=channel)
def read(data: BytesIO, *args: Any) -> "InputMediaGeoPoint": # No flags geo_point = TLObject.read(data) return InputMediaGeoPoint(geo_point=geo_point)
def read(data: BytesIO, *args: Any) -> "GetMessages": # No flags id = TLObject.read(data) return GetMessages(id=id)
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)
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)
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)
def read(data: BytesIO, *args: Any) -> "DeletePhotos": # No flags id = TLObject.read(data) return DeletePhotos(id=id)
def read(data: BytesIO, *args: Any) -> "UpdateChatParticipants": # No flags participants = TLObject.read(data) return UpdateChatParticipants(participants=participants)