2222
2323from .tcp import TCP , ProxyDict
2424
25+ import hashlib
26+ import os
27+
28+ from pyrogram .crypto import aes
29+
2530log = logging .getLogger (__name__ )
2631
2732
2833class TCPAbridged (TCP ):
2934 def __init__ (
3035 self ,
36+ dc_id : int ,
3137 ipv6 : bool = False ,
3238 proxy : Optional [Union [str , ProxyDict ]] = None ,
3339 crypto_executor_workers : int = 1 ,
3440 loop : Optional [asyncio .AbstractEventLoop ] = None ,
3541 ) -> None :
3642 super ().__init__ (ipv6 , proxy , crypto_executor_workers , loop )
43+ self .dc_id = dc_id
44+ self .encrypt = None
45+ self .decrypt = None
46+ self .secret = None
47+ self .hostname = None
48+ self .port = None
49+ if isinstance (proxy , dict ) and proxy .get ("scheme" , "" ).lower () == "mtproxy" :
50+ self .hostname = proxy .get ("hostname" )
51+ self .port = proxy .get ("port" )
52+ self .secret = proxy .get ("secret" )
53+
54+ async def connect_via_mtproxy (self , address ):
55+ self .marker_event .clear ()
56+
57+ nonce = bytearray (os .urandom (64 ))
58+
59+ while (
60+ nonce [0 ] == 0xef
61+ or nonce [:4 ] in (b"HEAD" , b"POST" , b"GET " , b"OPTI" , b"\xee " * 4 )
62+ or nonce [4 :8 ] == b"\x00 " * 4
63+ ):
64+ nonce = bytearray (os .urandom (64 ))
65+
66+ temp = bytearray (nonce [55 :7 :- 1 ])
67+
68+ secret = self .secret
69+
70+ if isinstance (secret , str ):
71+ if secret .startswith ("dd" ):
72+ secret = secret [2 :]
73+ secret = bytes .fromhex (secret )
74+
75+ encrypt_key = hashlib .sha256 (
76+ bytes (nonce [8 :40 ]) + secret
77+ ).digest ()
78+
79+ decrypt_key = hashlib .sha256 (
80+ bytes (temp [:32 ]) + secret
81+ ).digest ()
82+
83+ self .encrypt = (
84+ encrypt_key ,
85+ bytes (nonce [40 :56 ]),
86+ bytearray (1 )
87+ )
88+
89+ self .decrypt = (
90+ decrypt_key ,
91+ bytes (temp [32 :48 ]),
92+ bytearray (1 )
93+ )
94+
95+ nonce [56 :60 ] = b'\xef \xef \xef \xef '
96+
97+ nonce [60 :62 ] = self .dc_id .to_bytes (
98+ 2 ,
99+ "little" ,
100+ signed = True
101+ )
102+
103+ encrypted = aes .ctr256_encrypt (
104+ nonce ,
105+ * self .encrypt
106+ )
107+
108+ nonce [56 :64 ] = encrypted [56 :64 ]
37109
110+ await super ().connect ((self .hostname , self .port ))
111+
112+ await super ().send (
113+ nonce ,
114+ wait_for_marker = False
115+ )
116+
117+ self .marker_event .set ()
118+
38119 async def connect (self , address : Tuple [str , int ]) -> None :
120+ if self .hostname and self .port and self .secret :
121+ return await self .connect_via_mtproxy (address )
122+
39123 self .marker_event .clear ()
40124 await super ().connect (address )
41125 await super ().send (b"\xef " , wait_for_marker = False )
42126 self .marker_event .set ()
43127
44- async def send (self , data : bytes , * args ) -> None :
128+ async def send_via_mtproxy (self , data : bytes , * args ):
45129 length = len (data ) // 4
46130
131+ payload = (
132+ bytes ([length ])
133+ if length <= 126
134+ else b"\x7f " + length .to_bytes (3 , "little" )
135+ ) + data
136+
137+ payload = await self .loop .run_in_executor (
138+ self .crypto_executor ,
139+ aes .ctr256_encrypt ,
140+ payload ,
141+ * self .encrypt
142+ )
143+ await super ().send (payload )
144+
145+ async def send (self , data : bytes , * args ) -> None :
146+ if self .hostname and self .port and self .secret :
147+ return await self .send_via_mtproxy (data , * args )
148+
149+ length = len (data ) // 4
47150 await super ().send (
48151 (bytes ([length ])
49- if length <= 126
50- else b"\x7f " + length .to_bytes (3 , "little" ))
152+ if length <= 126
153+ else b"\x7f " + length .to_bytes (3 , "little" ))
51154 + data
52155 )
53156
157+ async def recv_via_mtproxy (self , length : int = 0 ):
158+ length = await super ().recv (1 )
159+
160+ if length is None :
161+ return None
162+
163+ length = aes .ctr256_decrypt (
164+ length ,
165+ * self .decrypt
166+ )
167+
168+ if length == b"\x7f " :
169+ length = await super ().recv (3 )
170+
171+ if length is None :
172+ return None
173+
174+ length = aes .ctr256_decrypt (
175+ length ,
176+ * self .decrypt
177+ )
178+
179+ packet_length = int .from_bytes (
180+ length ,
181+ "little"
182+ ) * 4
183+
184+ data = await super ().recv (packet_length )
185+
186+ if data is None :
187+ return None
188+
189+ return await self .loop .run_in_executor (
190+ self .crypto_executor ,
191+ aes .ctr256_decrypt ,
192+ data ,
193+ * self .decrypt
194+ )
195+
54196 async def recv (self , length : int = 0 ) -> Optional [bytes ]:
197+ if self .hostname and self .port and self .secret :
198+ return await self .recv_via_mtproxy (length )
199+
55200 length = await super ().recv (1 )
56201
57202 if length is None :
@@ -63,4 +208,4 @@ async def recv(self, length: int = 0) -> Optional[bytes]:
63208 if length is None :
64209 return None
65210
66- return await super ().recv (int .from_bytes (length , "little" ) * 4 )
211+ return await super ().recv (int .from_bytes (length , "little" ) * 4 )
0 commit comments