diff --git a/pyrogram/client/methods/password/utils.py b/pyrogram/client/methods/password/utils.py new file mode 100644 index 00000000..4bf0ddec --- /dev/null +++ b/pyrogram/client/methods/password/utils.py @@ -0,0 +1,103 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2018 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import hashlib +import os + +from pyrogram.api import types + + +def btoi(b: bytes) -> int: + return int.from_bytes(b, "big") + + +def itob(i: int) -> bytes: + return i.to_bytes(256, "big") + + +def sha256(data: bytes) -> bytes: + return hashlib.sha256(data).digest() + + +def xor(a: bytes, b: bytes) -> bytes: + return bytes(i ^ j for i, j in zip(a, b)) + + +def compute_hash(algo: types.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow, password: str) -> bytes: + hash1 = sha256(algo.salt1 + password.encode() + algo.salt1) + hash2 = sha256(algo.salt2 + hash1 + algo.salt2) + hash3 = hashlib.pbkdf2_hmac("sha512", hash2, algo.salt1, 100000) + + return sha256(algo.salt2 + hash3 + algo.salt2) + + +def compute_check(r: types.account.Password, password: str) -> types.InputCheckPasswordSRP: + algo = r.current_algo + + p_bytes = algo.p + p = btoi(algo.p) + + g_bytes = itob(algo.g) + g = algo.g + + B_bytes = r.srp_B + B = btoi(B_bytes) + + srp_id = r.srp_id + + x_bytes = compute_hash(algo, password) + x = btoi(x_bytes) + + g_x = pow(g, x, p) + + k_bytes = sha256(p_bytes + g_bytes) + k = btoi(k_bytes) + + kg_x = (k * g_x) % p + + while True: + a_bytes = os.urandom(256) + a = btoi(a_bytes) + + A = pow(g, a, p) + A_bytes = itob(A) + + u = btoi(sha256(A_bytes + B_bytes)) + + if u > 0: + break + + g_b = (B - kg_x) % p + + ux = u * x + a_ux = a + ux + S = pow(g_b, a_ux, p) + S_bytes = itob(S) + + K_bytes = sha256(S_bytes) + + M1_bytes = sha256( + xor(sha256(p_bytes), sha256(g_bytes)) + + sha256(algo.salt1) + + sha256(algo.salt2) + + A_bytes + + B_bytes + + K_bytes + ) + + return types.InputCheckPasswordSRP(srp_id, A_bytes, M1_bytes)