Remove broken CdnDecrypter

This commit is contained in:
Lonami Exo 2021-09-17 20:55:27 +02:00
parent b3c23e343a
commit 3bc46e8072
5 changed files with 11 additions and 142 deletions

View File

@ -249,3 +249,9 @@ The TelegramClient is no longer made out of mixins
If you were relying on any of the individual mixins that made up the client, such as
``UserMethods`` inside the ``telethon.client`` subpackage, those are now gone.
There is a single ``TelegramClient`` class now, containing everything you need.
CdnDecrypter has been removed
-----------------------------
It was not really working and was more intended to be an implementation detail than anything else.

View File

@ -428,31 +428,26 @@ def _auth_key_callback(self: 'TelegramClient', auth_key):
self.session.save()
async def _get_dc(self: 'TelegramClient', dc_id, cdn=False):
async def _get_dc(self: 'TelegramClient', dc_id):
"""Gets the Data Center (DC) associated to 'dc_id'"""
cls = self.__class__
if not cls._config:
cls._config = await self(_tl.fn.help.GetConfig())
if cdn and not self._cdn_config:
cls._cdn_config = await self(_tl.fn.help.GetCdnConfig())
for pk in cls._cdn_config.public_keys:
rsa.add_key(pk.public_key)
try:
return next(
dc for dc in cls._config.dc_options
if dc.id == dc_id
and bool(dc.ipv6) == self._use_ipv6 and bool(dc.cdn) == cdn
and bool(dc.ipv6) == self._use_ipv6 and not dc.cdn
)
except StopIteration:
self._log[__name__].warning(
'Failed to get DC %s (cdn = %s) with use_ipv6 = %s; retrying ignoring IPv6 check',
dc_id, cdn, self._use_ipv6
'Failed to get DC %swith use_ipv6 = %s; retrying ignoring IPv6 check',
dc_id, self._use_ipv6
)
return next(
dc for dc in cls._config.dc_options
if dc.id == dc_id and bool(dc.cdn) == cdn
if dc.id == dc_id and not dc.cdn
)
async def _create_exported_sender(self: 'TelegramClient', dc_id):
@ -538,29 +533,3 @@ async def _clean_exported_senders(self: 'TelegramClient'):
# Disconnect should never raise
await sender.disconnect()
state.mark_disconnected()
async def _get_cdn_client(self: 'TelegramClient', cdn_redirect):
"""Similar to ._borrow_exported_client, but for CDNs"""
# TODO Implement
raise NotImplementedError
session = self._exported_sessions.get(cdn_redirect.dc_id)
if not session:
dc = await _get_dc(self, cdn_redirect.dc_id, cdn=True)
session = self.session.clone()
await session.set_dc(dc.id, dc.ip_address, dc.port)
self._exported_sessions[cdn_redirect.dc_id] = session
self._log[__name__].info('Creating new CDN client')
client = TelegramBaseClient(
session, self.api_id, self.api_hash,
proxy=self._sender.connection.conn.proxy,
timeout=self._sender.connection.get_timeout()
)
# This will make use of the new RSA keys for this specific CDN.
#
# We won't be calling GetConfig because it's only called
# when needed by ._get_dc, and also it's static so it's likely
# set already. Avoid invoking non-CDN methods by not syncing updates.
client.connect(_sync_updates=False)
return client

View File

@ -2761,7 +2761,6 @@ class TelegramClient:
# Cached server configuration (with .dc_options), can be "global"
_config = None
_cdn_config = None
def __init__(
self: 'TelegramClient',

View File

@ -7,4 +7,3 @@ from .aes import AES
from .aesctr import AESModeCTR
from .authkey import AuthKey
from .factorization import Factorization
from .cdndecrypter import CdnDecrypter

View File

@ -1,104 +0,0 @@
"""
This module holds the CdnDecrypter utility class.
"""
from hashlib import sha256
from .. import _tl
from .._crypto import AESModeCTR
from ..errors import CdnFileTamperedError
class CdnDecrypter:
"""
Used when downloading a file results in a 'FileCdnRedirect' to
both prepare the redirect, decrypt the file as it downloads, and
ensure the file hasn't been tampered. https://core.telegram.org/cdn
"""
def __init__(self, cdn_client, file_token, cdn_aes, cdn_file_hashes):
"""
Initializes the CDN decrypter.
:param cdn_client: a client connected to a CDN.
:param file_token: the token of the file to be used.
:param cdn_aes: the AES CTR used to decrypt the file.
:param cdn_file_hashes: the hashes the decrypted file must match.
"""
self.client = cdn_client
self.file_token = file_token
self.cdn_aes = cdn_aes
self.cdn_file_hashes = cdn_file_hashes
@staticmethod
async def prepare_decrypter(client, cdn_client, cdn_redirect):
"""
Prepares a new CDN decrypter.
:param client: a TelegramClient connected to the main servers.
:param cdn_client: a new client connected to the CDN.
:param cdn_redirect: the redirect file object that caused this call.
:return: (CdnDecrypter, first chunk file data)
"""
cdn_aes = AESModeCTR(
key=cdn_redirect.encryption_key,
# 12 first bytes of the IV..4 bytes of the offset (0, big endian)
iv=cdn_redirect.encryption_iv[:12] + bytes(4)
)
# We assume that cdn_redirect.cdn_file_hashes are ordered by offset,
# and that there will be enough of these to retrieve the whole file.
decrypter = CdnDecrypter(
cdn_client, cdn_redirect.file_token,
cdn_aes, cdn_redirect.cdn_file_hashes
)
cdn_file = await cdn_client(_tl.fn.upload.GetCdnFile(
file_token=cdn_redirect.file_token,
offset=cdn_redirect.cdn_file_hashes[0].offset,
limit=cdn_redirect.cdn_file_hashes[0].limit
))
if isinstance(cdn_file, _tl.upload.CdnFileReuploadNeeded):
# We need to use the original client here
await client(_tl.fn.upload.ReuploadCdnFile(
file_token=cdn_redirect.file_token,
request_token=cdn_file.request_token
))
# We want to always return a valid upload.CdnFile
cdn_file = decrypter.get_file()
else:
cdn_file.bytes = decrypter.cdn_aes.encrypt(cdn_file.bytes)
cdn_hash = decrypter.cdn_file_hashes.pop(0)
decrypter.check(cdn_file.bytes, cdn_hash)
return decrypter, cdn_file
def get_file(self):
"""
Calls GetCdnFile and decrypts its bytes.
Also ensures that the file hasn't been tampered.
:return: the CdnFile result.
"""
if self.cdn_file_hashes:
cdn_hash = self.cdn_file_hashes.pop(0)
cdn_file = self.client(_tl.fn.upload.GetCdnFile(
self.file_token, cdn_hash.offset, cdn_hash.limit
))
cdn_file.bytes = self.cdn_aes.encrypt(cdn_file.bytes)
self.check(cdn_file.bytes, cdn_hash)
else:
cdn_file = _tl.upload.CdnFile(bytes(0))
return cdn_file
@staticmethod
def check(data, cdn_hash):
"""
Checks the integrity of the given data.
Raises CdnFileTamperedError if the integrity check fails.
:param data: the data to be hashed.
:param cdn_hash: the expected hash.
"""
if sha256(data).digest() != cdn_hash.hash:
raise CdnFileTamperedError()