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+ from hashlib import sha256 , pbkdf2_hmac
1920import os
20- from hashlib import sha256
2121
2222from pyrogram .api import functions , types
2323from ...ext import BaseClient
2424
2525
26+ def compute_hash (algo : types .PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow , password : str ):
27+ hash1 = sha256 (algo .salt1 + password .encode () + algo .salt1 ).digest ()
28+ hash2 = sha256 (algo .salt2 + hash1 + algo .salt2 ).digest ()
29+ hash3 = pbkdf2_hmac ("sha512" , hash2 , algo .salt1 , 100000 )
30+
31+ return sha256 (algo .salt2 + hash3 + algo .salt2 ).digest ()
32+
33+
34+ def btoi (b : bytes ):
35+ return int .from_bytes (b , "big" )
36+
37+
38+ def itob (i : int ):
39+ return i .to_bytes (256 , "big" )
40+
41+
2642class EnableCloudPassword (BaseClient ):
2743 def enable_cloud_password (self , password : str , hint : str = "" , email : str = "" ):
2844 """Use this method to enable the Two-Step Verification security feature (Cloud Password) on your account.
@@ -46,21 +62,86 @@ def enable_cloud_password(self, password: str, hint: str = "", email: str = ""):
4662 :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
4763 """
4864 r = self .send (functions .account .GetPassword ())
65+ print (r )
66+
67+ algo = r .new_algo
68+
69+ p_bytes = algo .p
70+ p = btoi (algo .p )
71+
72+ g_bytes = itob (algo .g )
73+ g = algo .g
74+
75+ B_bytes = r .srp_B or b""
76+ B = btoi (B_bytes )
77+
78+ srp_id = r .srp_id or 0
79+
80+ x_bytes = compute_hash (algo , password )
81+ x = btoi (x_bytes )
4982
50- if isinstance (r , types .account .NoPassword ):
51- salt = r .new_salt + os .urandom (8 )
52- password_hash = sha256 (salt + password .encode () + salt ).digest ()
53-
54- return self .send (
55- functions .account .UpdatePasswordSettings (
56- current_password_hash = salt ,
57- new_settings = types .account .PasswordInputSettings (
58- new_salt = salt ,
59- new_password_hash = password_hash ,
60- hint = hint ,
61- email = email
62- )
63- )
83+ g_x = pow (g , x , p )
84+
85+ k_bytes = sha256 (p_bytes + g_bytes ).digest ()
86+ k = btoi (k_bytes )
87+
88+ kg_x = (k * g_x ) % p
89+
90+ while True :
91+ a_bytes = os .urandom (256 )
92+ a = btoi (a_bytes )
93+
94+ A = pow (g , a , p )
95+ A_bytes = itob (A )
96+
97+ u = btoi (sha256 (A_bytes + B_bytes ).digest ())
98+
99+ if u > 0 :
100+ break
101+
102+ g_b = (B - kg_x ) % p
103+
104+ ux = u * x
105+ a_ux = a + ux
106+ S = pow (g_b , a_ux , p )
107+ S_bytes = itob (S )
108+
109+ K_bytes = sha256 (S_bytes ).digest ()
110+ M1_bytes = sha256 (
111+ b"" .join ([bytes ([int (i ) ^ int (j )]) for (i , j ) in zip (sha256 (p_bytes ).digest (), sha256 (g_bytes ).digest ())])
112+ + sha256 (algo .salt1 ).digest ()
113+ + sha256 (algo .salt2 ).digest ()
114+ + A_bytes
115+ + B_bytes
116+ + K_bytes
117+ ).digest ()
118+
119+ input_check_password = types .InputCheckPasswordSRP (srp_id , A_bytes , M1_bytes )
120+
121+ r2 = self .send (functions .account .UpdatePasswordSettings (
122+ input_check_password , types .account .PasswordInputSettings (
123+ new_algo = algo ,
124+ new_password_hash = b"" ,
125+ hint = ""
64126 )
65- else :
66- return False
127+ ))
128+
129+ print (r2 )
130+
131+ # if isinstance(r, types.account.NoPassword):
132+ # salt = r.new_salt + os.urandom(8)
133+ # password_hash = sha256(salt + password.encode() + salt).digest()
134+ #
135+ # return self.send(
136+ # functions.account.UpdatePasswordSettings(
137+ # current_password_hash=salt,
138+ # new_settings=types.account.PasswordInputSettings(
139+ # new_salt=salt,
140+ # new_password_hash=password_hash,
141+ # hint=hint,
142+ # email=email
143+ # )
144+ # )
145+ # )
146+ # else:
147+ # return False
0 commit comments