# Pyrogram - Telegram MTProto API Client Library for Python # Copyright (C) 2017-2020 Dan # # 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) # noinspection PyPep8Naming 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=srp_id, A=A_bytes, M1=M1_bytes)