1616# You should have received a copy of the GNU Lesser General Public License
1717# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818
19+ import logging
20+
21+ log = logging .getLogger (__name__ )
22+
1923try :
2024 import tgcrypto
21- except ImportError as e :
22- e . msg = (
23- "TgCrypto is missing and Pyrogram can't run without. "
24- "Please install it using \" pip3 install tgcrypto \" . "
25+ except ImportError :
26+ log . warning (
27+ "TgCrypto is missing! "
28+ "Pyrogram will work the same, but at a much slower speed . "
2529 "More info: https://docs.pyrogram.ml/resources/TgCrypto"
2630 )
27-
28- raise e
31+ is_fast = False
32+ import pyaes
33+ else :
34+ log .info ("Using TgCrypto" )
35+ is_fast = True
2936
3037
38+ # TODO: Ugly IFs
3139class AES :
3240 @classmethod
3341 def ige_encrypt (cls , data : bytes , key : bytes , iv : bytes ) -> bytes :
34- return tgcrypto .ige_encrypt (data , key , iv )
42+ if is_fast :
43+ return tgcrypto .ige_encrypt (data , key , iv )
44+ else :
45+ return cls .ige (data , key , iv , True )
3546
3647 @classmethod
3748 def ige_decrypt (cls , data : bytes , key : bytes , iv : bytes ) -> bytes :
38- return tgcrypto .ige_decrypt (data , key , iv )
49+ if is_fast :
50+ return tgcrypto .ige_decrypt (data , key , iv )
51+ else :
52+ return cls .ige (data , key , iv , False )
3953
4054 @staticmethod
4155 def ctr_decrypt (data : bytes , key : bytes , iv : bytes , offset : int ) -> bytes :
4256 replace = int .to_bytes (offset // 16 , 4 , "big" )
4357 iv = iv [:- 4 ] + replace
4458
45- return tgcrypto .ctr_decrypt (data , key , iv )
59+ if is_fast :
60+ return tgcrypto .ctr_decrypt (data , key , iv )
61+ else :
62+ ctr = pyaes .AESModeOfOperationCTR (key )
63+ ctr ._counter ._counter = list (iv )
64+ return ctr .decrypt (data )
4665
4766 @staticmethod
4867 def xor (a : bytes , b : bytes ) -> bytes :
@@ -51,3 +70,23 @@ def xor(a: bytes, b: bytes) -> bytes:
5170 len (a ),
5271 "big" ,
5372 )
73+
74+ @classmethod
75+ def ige (cls , data : bytes , key : bytes , iv : bytes , encrypt : bool ) -> bytes :
76+ cipher = pyaes .AES (key )
77+
78+ iv_1 = iv [:16 ]
79+ iv_2 = iv [16 :]
80+
81+ data = [data [i : i + 16 ] for i in range (0 , len (data ), 16 )]
82+
83+ if encrypt :
84+ for i , chunk in enumerate (data ):
85+ iv_1 = data [i ] = cls .xor (cipher .encrypt (cls .xor (chunk , iv_1 )), iv_2 )
86+ iv_2 = chunk
87+ else :
88+ for i , chunk in enumerate (data ):
89+ iv_2 = data [i ] = cls .xor (cipher .decrypt (cls .xor (chunk , iv_2 )), iv_1 )
90+ iv_1 = chunk
91+
92+ return b"" .join (data )
0 commit comments